From fb4789f27fcd2d4180ebc94bc2b732337b4663d6 Mon Sep 17 00:00:00 2001 From: Robby Pratama Date: Tue, 21 Nov 2023 15:49:35 +0700 Subject: [PATCH 001/237] provide missing deprececated function: describeEnum --- .../flutter_enricher_event_processor.dart | 2 ++ flutter/lib/src/utils/enum_wrapper.dart | 12 ++++++++++++ 2 files changed, 14 insertions(+) create mode 100644 flutter/lib/src/utils/enum_wrapper.dart diff --git a/flutter/lib/src/event_processor/flutter_enricher_event_processor.dart b/flutter/lib/src/event_processor/flutter_enricher_event_processor.dart index de6b6bab9f..cb20bfea93 100644 --- a/flutter/lib/src/event_processor/flutter_enricher_event_processor.dart +++ b/flutter/lib/src/event_processor/flutter_enricher_event_processor.dart @@ -8,6 +8,8 @@ import 'package:sentry/sentry.dart'; import '../navigation/sentry_navigator_observer.dart'; import '../sentry_flutter_options.dart'; +import '../utils/enum_wrapper.dart'; + typedef WidgetBindingGetter = WidgetsBinding? Function(); /// Enriches [SentryEvent]s with various kinds of information. diff --git a/flutter/lib/src/utils/enum_wrapper.dart b/flutter/lib/src/utils/enum_wrapper.dart new file mode 100644 index 0000000000..12bcd6f38b --- /dev/null +++ b/flutter/lib/src/utils/enum_wrapper.dart @@ -0,0 +1,12 @@ +String describeEnum(Object enumEntry) { + if (enumEntry is Enum) { + return enumEntry.name; + } + final String description = enumEntry.toString(); + final int indexOfDot = description.indexOf('.'); + assert( + indexOfDot != -1 && indexOfDot < description.length - 1, + 'The provided object "$enumEntry" is not an enum.', + ); + return description.substring(indexOfDot + 1); +} From 0caa9119ef06cc11de30d989df86ee884d8263a5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 Nov 2023 10:11:57 +0100 Subject: [PATCH 002/237] build(deps): bump dart-lang/setup-dart from 1.3.0 to 1.6.0 (#1743) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.3.0 to 1.6.0. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/v1.3...b64355ae6ca0b5d484f0106a033dd1388965d06d) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/hive.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/hive.yml b/.github/workflows/hive.yml index 42b434d30e..09a37140b4 100644 --- a/.github/workflows/hive.yml +++ b/.github/workflows/hive.yml @@ -41,7 +41,7 @@ jobs: - os: macos-latest sdk: beta steps: - - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d # pin@v1 + - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d # pin@v1 with: sdk: ${{ matrix.sdk }} - uses: actions/checkout@v3 From 9de64255e2261473fd999b263ebc6d354b962c1e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 22 Nov 2023 10:20:46 +0100 Subject: [PATCH 003/237] chore(deps): update Android SDK to v6.34.0 (#1746) * chore: update flutter/scripts/update-android.sh to 6.34.0 * Update CHANGELOG --------- Co-authored-by: GitHub Co-authored-by: GIancarlo Buenaflor --- CHANGELOG.md | 12 ++++++++++++ flutter/android/build.gradle | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 20779133ae..88b6540fff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## Unreleased + +### Fixes + +- Fix SIGSEV, SIGABRT and SIGBUS crashes happening after/around the August Google Play System update, see [#2955](https://github-redirect.dependabot.com/getsentry/sentry-java/issues/2955) for more details (fix provided by Native SDK bump) + +### Dependencies + +- Bump Android SDK from v6.33.1 to v6.34.0 ([#1746](https://github.com/getsentry/sentry-dart/pull/1746)) + - [changelog](https://github.com/getsentry/sentry-java/blob/main/CHANGELOG.md#6340) + - [diff](https://github.com/getsentry/sentry-java/compare/6.33.1...6.34.0) + ## 7.13.1 ### Fixes diff --git a/flutter/android/build.gradle b/flutter/android/build.gradle index a532cb03f8..9e956927c8 100644 --- a/flutter/android/build.gradle +++ b/flutter/android/build.gradle @@ -60,7 +60,7 @@ android { } dependencies { - api 'io.sentry:sentry-android:6.33.1' + api 'io.sentry:sentry-android:6.34.0' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" // Required -- JUnit 4 framework From 683fd34f35c964a36534f6df6b3d4cb325f5069c Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Wed, 22 Nov 2023 10:44:30 +0100 Subject: [PATCH 004/237] deps: update `package_info_plus` constraints (#1749) * Update constraints * Update CHANGELOG --- CHANGELOG.md | 1 + flutter/pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 88b6540fff..3ba9c93434 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ ### Dependencies +- Update package-info-plus constraint to include 5.0.1 ([#1749](https://github.com/getsentry/sentry-dart/pull/1749)) - Bump Android SDK from v6.33.1 to v6.34.0 ([#1746](https://github.com/getsentry/sentry-dart/pull/1746)) - [changelog](https://github.com/getsentry/sentry-java/blob/main/CHANGELOG.md#6340) - [diff](https://github.com/getsentry/sentry-java/compare/6.33.1...6.34.0) diff --git a/flutter/pubspec.yaml b/flutter/pubspec.yaml index c6880608ca..4e44427a1e 100644 --- a/flutter/pubspec.yaml +++ b/flutter/pubspec.yaml @@ -16,7 +16,7 @@ dependencies: flutter_web_plugins: sdk: flutter sentry: 7.13.1 - package_info_plus: '>=1.0.0 <5.0.0' + package_info_plus: '>=1.0.0 <=5.0.1' meta: ^1.3.0 ffi: ^2.0.0 From a6940c1a7697cb2a52ff08d0da59519d8d7e4dda Mon Sep 17 00:00:00 2001 From: getsentry-bot Date: Wed, 22 Nov 2023 10:52:01 +0000 Subject: [PATCH 005/237] release: 7.13.2 --- CHANGELOG.md | 2 +- dart/lib/src/version.dart | 2 +- dart/pubspec.yaml | 2 +- dio/lib/src/version.dart | 2 +- dio/pubspec.yaml | 4 ++-- drift/lib/src/version.dart | 2 +- drift/pubspec.yaml | 4 ++-- file/lib/src/version.dart | 2 +- file/pubspec.yaml | 4 ++-- flutter/example/pubspec.yaml | 2 +- flutter/lib/src/version.dart | 2 +- flutter/pubspec.yaml | 4 ++-- hive/lib/src/version.dart | 2 +- hive/pubspec.yaml | 4 ++-- logging/lib/src/version.dart | 2 +- logging/pubspec.yaml | 4 ++-- sqflite/lib/src/version.dart | 2 +- sqflite/pubspec.yaml | 4 ++-- 18 files changed, 25 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ba9c93434..f7a599a956 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## Unreleased +## 7.13.2 ### Fixes diff --git a/dart/lib/src/version.dart b/dart/lib/src/version.dart index ae1db0d901..3f3c44b449 100644 --- a/dart/lib/src/version.dart +++ b/dart/lib/src/version.dart @@ -9,7 +9,7 @@ library version; /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.13.1'; +const String sdkVersion = '7.13.2'; String sdkName(bool isWeb) => isWeb ? _browserSdkName : _ioSdkName; diff --git a/dart/pubspec.yaml b/dart/pubspec.yaml index 4dc923be94..e2e2a7c1c6 100644 --- a/dart/pubspec.yaml +++ b/dart/pubspec.yaml @@ -1,5 +1,5 @@ name: sentry -version: 7.13.1 +version: 7.13.2 description: > A crash reporting library for Dart that sends crash reports to Sentry.io. This library supports Dart VM and Web. For Flutter consider sentry_flutter instead. diff --git a/dio/lib/src/version.dart b/dio/lib/src/version.dart index 5d8e41f2aa..2e88298a45 100644 --- a/dio/lib/src/version.dart +++ b/dio/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.13.1'; +const String sdkVersion = '7.13.2'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_dio'; diff --git a/dio/pubspec.yaml b/dio/pubspec.yaml index 4fd89221bb..b8c55a1147 100644 --- a/dio/pubspec.yaml +++ b/dio/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_dio description: An integration which adds support for performance tracing for the Dio package. -version: 7.13.1 +version: 7.13.2 homepage: https://docs.sentry.io/platforms/dart/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -11,7 +11,7 @@ environment: dependencies: dio: ^5.0.0 - sentry: 7.13.1 + sentry: 7.13.2 dev_dependencies: meta: ^1.3.0 diff --git a/drift/lib/src/version.dart b/drift/lib/src/version.dart index 39be251dbf..5fe2e65abd 100644 --- a/drift/lib/src/version.dart +++ b/drift/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.13.1'; +const String sdkVersion = '7.13.2'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_drift'; diff --git a/drift/pubspec.yaml b/drift/pubspec.yaml index 7f474b73e7..7d871c6156 100644 --- a/drift/pubspec.yaml +++ b/drift/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_drift description: An integration which adds support for performance tracing for the drift package. -version: 7.13.1 +version: 7.13.2 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -10,7 +10,7 @@ environment: flutter: '>=3.3.0' dependencies: - sentry: 7.13.1 + sentry: 7.13.2 meta: ^1.3.0 drift: ^2.13.0 diff --git a/file/lib/src/version.dart b/file/lib/src/version.dart index da534425a9..a979700d5a 100644 --- a/file/lib/src/version.dart +++ b/file/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.13.1'; +const String sdkVersion = '7.13.2'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_file'; diff --git a/file/pubspec.yaml b/file/pubspec.yaml index d1cb6a6036..fe9d2fe916 100644 --- a/file/pubspec.yaml +++ b/file/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_file description: An integration which adds support for performance tracing for dart.io.File. -version: 7.13.1 +version: 7.13.2 homepage: https://docs.sentry.io/platforms/dart/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -10,7 +10,7 @@ environment: sdk: '>=2.19.0 <4.0.0' dependencies: - sentry: 7.13.1 + sentry: 7.13.2 meta: ^1.3.0 dev_dependencies: diff --git a/flutter/example/pubspec.yaml b/flutter/example/pubspec.yaml index aa5c959aa3..fc09a3776e 100644 --- a/flutter/example/pubspec.yaml +++ b/flutter/example/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_flutter_example description: Demonstrates how to use the sentry_flutter plugin. -version: 7.13.1 +version: 7.13.2 publish_to: 'none' # Remove this line if you wish to publish to pub.dev diff --git a/flutter/lib/src/version.dart b/flutter/lib/src/version.dart index 8dfdd16262..598160e5d9 100644 --- a/flutter/lib/src/version.dart +++ b/flutter/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.13.1'; +const String sdkVersion = '7.13.2'; /// The default SDK name reported to Sentry.io in the submitted events. const String sdkName = 'sentry.dart.flutter'; diff --git a/flutter/pubspec.yaml b/flutter/pubspec.yaml index 4e44427a1e..5c4d529917 100644 --- a/flutter/pubspec.yaml +++ b/flutter/pubspec.yaml @@ -1,5 +1,5 @@ name: sentry_flutter -version: 7.13.1 +version: 7.13.2 description: Sentry SDK for Flutter. This package aims to support different Flutter targets by relying on the many platforms supported by Sentry with native SDKs. homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart @@ -15,7 +15,7 @@ dependencies: sdk: flutter flutter_web_plugins: sdk: flutter - sentry: 7.13.1 + sentry: 7.13.2 package_info_plus: '>=1.0.0 <=5.0.1' meta: ^1.3.0 ffi: ^2.0.0 diff --git a/hive/lib/src/version.dart b/hive/lib/src/version.dart index 00e8950582..080ff8f0f2 100644 --- a/hive/lib/src/version.dart +++ b/hive/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.13.1'; +const String sdkVersion = '7.13.2'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_hive'; diff --git a/hive/pubspec.yaml b/hive/pubspec.yaml index 0a53ab3f16..a89e369324 100644 --- a/hive/pubspec.yaml +++ b/hive/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_hive description: An integration which adds support for performance tracing for the hive package. -version: 7.13.1 +version: 7.13.2 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -9,7 +9,7 @@ environment: sdk: '>=2.17.0 <4.0.0' dependencies: - sentry: 7.13.1 + sentry: 7.13.2 hive: ^2.2.3 meta: ^1.3.0 diff --git a/logging/lib/src/version.dart b/logging/lib/src/version.dart index 9e5b7e8364..70c5b7d597 100644 --- a/logging/lib/src/version.dart +++ b/logging/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.13.1'; +const String sdkVersion = '7.13.2'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_logging'; diff --git a/logging/pubspec.yaml b/logging/pubspec.yaml index e8254560c7..4b6145bc85 100644 --- a/logging/pubspec.yaml +++ b/logging/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_logging description: An integration which adds support for recording log from the logging package. -version: 7.13.1 +version: 7.13.2 homepage: https://docs.sentry.io/platforms/dart/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -11,7 +11,7 @@ environment: dependencies: logging: ^1.0.0 - sentry: 7.13.1 + sentry: 7.13.2 dev_dependencies: lints: ^3.0.0 diff --git a/sqflite/lib/src/version.dart b/sqflite/lib/src/version.dart index 912423e889..3df0f707c4 100644 --- a/sqflite/lib/src/version.dart +++ b/sqflite/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.13.1'; +const String sdkVersion = '7.13.2'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_sqflite'; diff --git a/sqflite/pubspec.yaml b/sqflite/pubspec.yaml index e7ca891fec..653adbe3de 100644 --- a/sqflite/pubspec.yaml +++ b/sqflite/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_sqflite description: An integration which adds support for performance tracing for the sqflite package. -version: 7.13.1 +version: 7.13.2 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -10,7 +10,7 @@ environment: flutter: '>=3.3.0' # matching sqflite dependencies: - sentry: 7.13.1 + sentry: 7.13.2 sqflite: ^2.0.0 sqflite_common: ^2.0.0 meta: ^1.3.0 From dd08ebb62823412b98e2f2fc9cca581d50fe1670 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 23 Nov 2023 13:54:20 +0100 Subject: [PATCH 006/237] build(deps): bump codecov/codecov-action from 3.1.1 to 3.1.4 (#1742) Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 3.1.1 to 3.1.4. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/v3.1.1...eaaf4bedf32dbdc6b720b63067d99c4d77d6047d) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor --- .github/workflows/hive.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/hive.yml b/.github/workflows/hive.yml index 09a37140b4..7ed624e9d4 100644 --- a/.github/workflows/hive.yml +++ b/.github/workflows/hive.yml @@ -52,7 +52,7 @@ jobs: dart test -p vm --coverage=coverage --test-randomize-ordering-seed=random --chain-stack-traces dart pub run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.dart_tool/package_config.json --report-on=lib - - uses: codecov/codecov-action@d9f34f8cd5cb3b3eb79b3e4b5dae3a16df499a70 # pin@v3 + - uses: codecov/codecov-action@eaaf4bedf32dbdc6b720b63067d99c4d77d6047d # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: name: sentry_hive From 14950f1e7a5fc460a90d4da80bc0a2344443ce38 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 23 Nov 2023 13:54:35 +0100 Subject: [PATCH 007/237] build(deps): bump styfle/cancel-workflow-action from 0.11.0 to 0.12.0 (#1741) Bumps [styfle/cancel-workflow-action](https://github.com/styfle/cancel-workflow-action) from 0.11.0 to 0.12.0. - [Release notes](https://github.com/styfle/cancel-workflow-action/releases) - [Commits](https://github.com/styfle/cancel-workflow-action/compare/0.11.0...01ce38bf961b4e243a6342cbade0dbc8ba3f0432) --- updated-dependencies: - dependency-name: styfle/cancel-workflow-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor --- .github/workflows/hive.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/hive.yml b/.github/workflows/hive.yml index 7ed624e9d4..2a924aceb8 100644 --- a/.github/workflows/hive.yml +++ b/.github/workflows/hive.yml @@ -18,7 +18,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Cancel Previous Runs - uses: styfle/cancel-workflow-action@b173b6ec0100793626c2d9e6b90435061f4fc3e5 # pin@0.11.0 + uses: styfle/cancel-workflow-action@01ce38bf961b4e243a6342cbade0dbc8ba3f0432 # pin@0.12.0 with: access_token: ${{ github.token }} From b6eb97996a07d6df1b2c3e5059deb16cb1de2b7d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 23 Nov 2023 13:54:54 +0100 Subject: [PATCH 008/237] build(deps): bump actions/checkout from 3 to 4 (#1740) Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor --- .github/workflows/hive.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/hive.yml b/.github/workflows/hive.yml index 2a924aceb8..8302ccab79 100644 --- a/.github/workflows/hive.yml +++ b/.github/workflows/hive.yml @@ -44,7 +44,7 @@ jobs: - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d # pin@v1 with: sdk: ${{ matrix.sdk }} - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Test VM run: | From 6fe4faba54f09e5b62da2cf7d74c3ac0231ceeea Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 23 Nov 2023 13:55:26 +0100 Subject: [PATCH 009/237] build(deps): bump VeryGoodOpenSource/very_good_coverage (#1739) Bumps [VeryGoodOpenSource/very_good_coverage](https://github.com/verygoodopensource/very_good_coverage) from 2.1.0 to 2.2.0. - [Release notes](https://github.com/verygoodopensource/very_good_coverage/releases) - [Changelog](https://github.com/VeryGoodOpenSource/very_good_coverage/blob/main/CHANGELOG.md) - [Commits](https://github.com/verygoodopensource/very_good_coverage/compare/e5c91bc7ce9843e87c800b3bcafdfb86fbe28491...3b475421464c564c0714d92ce02742bd81fa9eda) --- updated-dependencies: - dependency-name: VeryGoodOpenSource/very_good_coverage dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor --- .github/workflows/dart.yml | 2 +- .github/workflows/dio.yml | 2 +- .github/workflows/drift.yml | 2 +- .github/workflows/file.yml | 2 +- .github/workflows/flutter.yml | 2 +- .github/workflows/hive.yml | 2 +- .github/workflows/logging.yml | 2 +- .github/workflows/sqflite.yml | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml index 32b805a524..5f61c73903 100644 --- a/.github/workflows/dart.yml +++ b/.github/workflows/dart.yml @@ -77,7 +77,7 @@ jobs: name: sentry files: ./dart/coverage/lcov.info - - uses: VeryGoodOpenSource/very_good_coverage@e5c91bc7ce9843e87c800b3bcafdfb86fbe28491 # pin@v2.1.0 + - uses: VeryGoodOpenSource/very_good_coverage@3b475421464c564c0714d92ce02742bd81fa9eda # pin@v2.2.0 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: path: "./dart/coverage/lcov.info" diff --git a/.github/workflows/dio.yml b/.github/workflows/dio.yml index 6b011213e0..064c175698 100644 --- a/.github/workflows/dio.yml +++ b/.github/workflows/dio.yml @@ -60,7 +60,7 @@ jobs: name: sentry_dio files: ./dio/coverage/lcov.info - - uses: VeryGoodOpenSource/very_good_coverage@e5c91bc7ce9843e87c800b3bcafdfb86fbe28491 # pin@v2.1.0 + - uses: VeryGoodOpenSource/very_good_coverage@3b475421464c564c0714d92ce02742bd81fa9eda # pin@v2.2.0 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: path: "./dio/coverage/lcov.info" diff --git a/.github/workflows/drift.yml b/.github/workflows/drift.yml index 3f2285bb7c..a7597909ad 100644 --- a/.github/workflows/drift.yml +++ b/.github/workflows/drift.yml @@ -101,7 +101,7 @@ jobs: file: ./drift/coverage/lcov.info functionalities: "search" # remove after https://github.com/codecov/codecov-action/issues/600 - - uses: VeryGoodOpenSource/very_good_coverage@e5c91bc7ce9843e87c800b3bcafdfb86fbe28491 # pin@v2.1.0 + - uses: VeryGoodOpenSource/very_good_coverage@3b475421464c564c0714d92ce02742bd81fa9eda # pin@v2.2.0 if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' with: path: "./drift/coverage/lcov.info" diff --git a/.github/workflows/file.yml b/.github/workflows/file.yml index f9f03aa5cf..7fed334c62 100644 --- a/.github/workflows/file.yml +++ b/.github/workflows/file.yml @@ -59,7 +59,7 @@ jobs: name: sentry_file files: ./file/coverage/lcov.info - - uses: VeryGoodOpenSource/very_good_coverage@e5c91bc7ce9843e87c800b3bcafdfb86fbe28491 # pin@v2.1.0 + - uses: VeryGoodOpenSource/very_good_coverage@3b475421464c564c0714d92ce02742bd81fa9eda # pin@v2.2.0 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: path: "./file/coverage/lcov.info" diff --git a/.github/workflows/flutter.yml b/.github/workflows/flutter.yml index 6c48bf4747..d5b5fb3472 100644 --- a/.github/workflows/flutter.yml +++ b/.github/workflows/flutter.yml @@ -114,7 +114,7 @@ jobs: file: ./flutter/coverage/lcov.info functionalities: "search" # remove after https://github.com/codecov/codecov-action/issues/600 - - uses: VeryGoodOpenSource/very_good_coverage@e5c91bc7ce9843e87c800b3bcafdfb86fbe28491 # pin@v2.1.0 + - uses: VeryGoodOpenSource/very_good_coverage@3b475421464c564c0714d92ce02742bd81fa9eda # pin@v2.2.0 if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' with: path: "./flutter/coverage/lcov.info" diff --git a/.github/workflows/hive.yml b/.github/workflows/hive.yml index 8302ccab79..582f4e36ac 100644 --- a/.github/workflows/hive.yml +++ b/.github/workflows/hive.yml @@ -58,7 +58,7 @@ jobs: name: sentry_hive files: ./hive/coverage/lcov.info - - uses: VeryGoodOpenSource/very_good_coverage@e5c91bc7ce9843e87c800b3bcafdfb86fbe28491 # pin@v2.1.0 + - uses: VeryGoodOpenSource/very_good_coverage@3b475421464c564c0714d92ce02742bd81fa9eda # pin@v2.2.0 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: path: "./hive/coverage/lcov.info" diff --git a/.github/workflows/logging.yml b/.github/workflows/logging.yml index 8529b2db12..b489d1be86 100644 --- a/.github/workflows/logging.yml +++ b/.github/workflows/logging.yml @@ -60,7 +60,7 @@ jobs: name: sentry_logging files: ./logging/coverage/lcov.info - - uses: VeryGoodOpenSource/very_good_coverage@e5c91bc7ce9843e87c800b3bcafdfb86fbe28491 # pin@v2.1.0 if: runner.os == 'Linux' && matrix.sdk == 'stable' + - uses: VeryGoodOpenSource/very_good_coverage@3b475421464c564c0714d92ce02742bd81fa9eda # pin@v2.1.0 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: path: "./logging/coverage/lcov.info" min_coverage: 90 diff --git a/.github/workflows/sqflite.yml b/.github/workflows/sqflite.yml index 5da5b7e557..41ab13aba5 100644 --- a/.github/workflows/sqflite.yml +++ b/.github/workflows/sqflite.yml @@ -102,7 +102,7 @@ jobs: file: ./sqflite/coverage/lcov.info functionalities: "search" # remove after https://github.com/codecov/codecov-action/issues/600 - - uses: VeryGoodOpenSource/very_good_coverage@e5c91bc7ce9843e87c800b3bcafdfb86fbe28491 # pin@v2.1.0 + - uses: VeryGoodOpenSource/very_good_coverage@3b475421464c564c0714d92ce02742bd81fa9eda # pin@v2.2.0 if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' with: path: "./sqflite/coverage/lcov.info" From a971204e4d646d881cf1f2bf0d3439e50637b4ba Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 23 Nov 2023 13:56:05 +0100 Subject: [PATCH 010/237] chore: update scripts/update-symbol-collector.sh to 1.13.0 (#1737) Co-authored-by: GitHub --- .../flutter_symbol_collector/lib/src/symbol_collector_cli.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/flutter_symbol_collector/lib/src/symbol_collector_cli.dart b/scripts/flutter_symbol_collector/lib/src/symbol_collector_cli.dart index 0f4c97d6a6..d89cbaeb84 100644 --- a/scripts/flutter_symbol_collector/lib/src/symbol_collector_cli.dart +++ b/scripts/flutter_symbol_collector/lib/src/symbol_collector_cli.dart @@ -19,7 +19,7 @@ class SymbolCollectorCli { // https://github.com/getsentry/symbol-collector/releases @internal - static const version = '1.12.1'; + static const version = '1.13.0'; @internal late final String cli; From 041d84de0540b1da829433f102c870bac73aec79 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 23 Nov 2023 16:22:40 +0100 Subject: [PATCH 011/237] chore: update scripts/update-symbol-collector.sh to 1.13.0 (#1754) Co-authored-by: GitHub From edecfc9040b3dde0b71f1ef128490f2333496bc5 Mon Sep 17 00:00:00 2001 From: Robby Pratama Date: Mon, 27 Nov 2023 14:10:43 +0700 Subject: [PATCH 012/237] rename deprecated method to avoid conflict if the method still available --- .../event_processor/flutter_enricher_event_processor.dart | 8 ++++---- flutter/lib/src/utils/enum_wrapper.dart | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/flutter/lib/src/event_processor/flutter_enricher_event_processor.dart b/flutter/lib/src/event_processor/flutter_enricher_event_processor.dart index cb20bfea93..32ee91acbe 100644 --- a/flutter/lib/src/event_processor/flutter_enricher_event_processor.dart +++ b/flutter/lib/src/event_processor/flutter_enricher_event_processor.dart @@ -141,16 +141,16 @@ class FlutterEnricherEventProcessor implements EventProcessor { return { 'has_render_view': hasRenderView.toString(), if (tempDebugBrightnessOverride != null) - 'debug_brightness_override': describeEnum(tempDebugBrightnessOverride), + 'debug_brightness_override': pDescribeEnum(tempDebugBrightnessOverride), if (debugPlatformOverride != null) 'debug_default_target_platform_override': - describeEnum(debugPlatformOverride), + pDescribeEnum(debugPlatformOverride), if (initialLifecycleState != null && initialLifecycleState.isNotEmpty) 'initial_lifecycle_state': initialLifecycleState, if (defaultRouteName != null && defaultRouteName.isNotEmpty) 'default_route_name': defaultRouteName, if (currentLifecycle != null) - 'current_lifecycle_state': describeEnum(currentLifecycle), + 'current_lifecycle_state': pDescribeEnum(currentLifecycle), // Seems to always return false. // Also always fails in tests. // See https://github.com/flutter/flutter/issues/83919 @@ -197,7 +197,7 @@ class FlutterEnricherEventProcessor implements EventProcessor { SentryOperatingSystem _getOperatingSystem(SentryOperatingSystem? os) { return (os ?? SentryOperatingSystem()).copyWith( // ignore: deprecated_member_use - theme: os?.theme ?? describeEnum(window.platformBrightness), + theme: os?.theme ?? pDescribeEnum(window.platformBrightness), ); } diff --git a/flutter/lib/src/utils/enum_wrapper.dart b/flutter/lib/src/utils/enum_wrapper.dart index 12bcd6f38b..6f7772af55 100644 --- a/flutter/lib/src/utils/enum_wrapper.dart +++ b/flutter/lib/src/utils/enum_wrapper.dart @@ -1,4 +1,4 @@ -String describeEnum(Object enumEntry) { +String pDescribeEnum(Object enumEntry) { if (enumEntry is Enum) { return enumEntry.name; } From d4120ac3aa1b3297e224a93b2f9d790adb0e683b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20Andra=C5=A1ec?= Date: Tue, 28 Nov 2023 09:24:04 +0000 Subject: [PATCH 013/237] Add option to opt out of fatal level for automatically collected errors (#1738) --- CHANGELOG.md | 6 +++++ .../src/run_zoned_guarded_integration.dart | 4 +++- dart/lib/src/sentry_isolate.dart | 4 +++- dart/lib/src/sentry_options.dart | 5 ++++ .../run_zoned_guarded_integration_test.dart | 17 ++++++++++++++ dart/test/sentry_isolate_test.dart | 18 +++++++++++++++ .../flutter_error_integration.dart | 4 +++- flutter/lib/src/native/cocoa/binding.dart | 23 +++++++++++-------- .../flutter_error_integration_test.dart | 14 +++++++++++ 9 files changed, 82 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f7a599a956..3056915989 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## Unreleased + +### Features + +- Add option to opt out of fatal level for automatically collected errors ([#1738](https://github.com/getsentry/sentry-dart/pull/1738)) + ## 7.13.2 ### Fixes diff --git a/dart/lib/src/run_zoned_guarded_integration.dart b/dart/lib/src/run_zoned_guarded_integration.dart index ba70fc2472..05ef5be2b0 100644 --- a/dart/lib/src/run_zoned_guarded_integration.dart +++ b/dart/lib/src/run_zoned_guarded_integration.dart @@ -50,7 +50,9 @@ class RunZonedGuardedIntegration extends Integration { final event = SentryEvent( throwable: throwableMechanism, - level: SentryLevel.fatal, + level: options.markAutomaticallyCollectedErrorsAsFatal + ? SentryLevel.fatal + : SentryLevel.error, timestamp: hub.options.clock(), ); diff --git a/dart/lib/src/sentry_isolate.dart b/dart/lib/src/sentry_isolate.dart index 898904cd27..0af2978e24 100644 --- a/dart/lib/src/sentry_isolate.dart +++ b/dart/lib/src/sentry_isolate.dart @@ -74,7 +74,9 @@ class SentryIsolate { final throwableMechanism = ThrowableMechanism(mechanism, throwable); final event = SentryEvent( throwable: throwableMechanism, - level: SentryLevel.fatal, + level: hub.options.markAutomaticallyCollectedErrorsAsFatal + ? SentryLevel.fatal + : SentryLevel.error, timestamp: hub.options.clock(), ); diff --git a/dart/lib/src/sentry_options.dart b/dart/lib/src/sentry_options.dart index 27d95fb9f3..7d0d18622a 100644 --- a/dart/lib/src/sentry_options.dart +++ b/dart/lib/src/sentry_options.dart @@ -369,6 +369,11 @@ class SentryOptions { @internal bool automatedTestMode = false; + /// Errors that the SDK automatically collects, for example in + /// [SentryIsolate], have `level` [SentryLevel.fatal] set per default. + /// Settings this to `false` will set the `level` to [SentryLevel.error]. + bool markAutomaticallyCollectedErrorsAsFatal = true; + SentryOptions({this.dsn, PlatformChecker? checker}) { if (checker != null) { platformChecker = checker; diff --git a/dart/test/run_zoned_guarded_integration_test.dart b/dart/test/run_zoned_guarded_integration_test.dart index 7e8045445d..13b102d7da 100644 --- a/dart/test/run_zoned_guarded_integration_test.dart +++ b/dart/test/run_zoned_guarded_integration_test.dart @@ -54,6 +54,23 @@ void main() { expect(onErrorCalled, true); }); + + test('sets level to error instead of fatal', () async { + final exception = StateError('error'); + final stackTrace = StackTrace.current; + + final hub = Hub(fixture.options); + final client = MockSentryClient(); + hub.bindClient(client); + + final sut = fixture.getSut(runner: () async {}); + + fixture.options.markAutomaticallyCollectedErrorsAsFatal = false; + await sut.captureError(hub, fixture.options, exception, stackTrace); + + final capturedEvent = client.captureEventCalls.last.event; + expect(capturedEvent.level, SentryLevel.error); + }); }); } diff --git a/dart/test/sentry_isolate_test.dart b/dart/test/sentry_isolate_test.dart index 1b1939ac2f..7cebc3e5e4 100644 --- a/dart/test/sentry_isolate_test.dart +++ b/dart/test/sentry_isolate_test.dart @@ -1,6 +1,7 @@ @TestOn('vm') import 'package:sentry/src/hub.dart'; +import 'package:sentry/src/protocol/sentry_level.dart'; import 'package:sentry/src/protocol/span_status.dart'; import 'package:sentry/src/sentry_isolate.dart'; import 'package:sentry/src/sentry_options.dart'; @@ -48,6 +49,23 @@ void main() { await span?.finish(); }); + + test('sets level to error instead of fatal', () async { + final exception = StateError('error'); + final stackTrace = StackTrace.current.toString(); + + final hub = Hub(fixture.options); + final client = MockSentryClient(); + hub.bindClient(client); + + fixture.options.markAutomaticallyCollectedErrorsAsFatal = false; + + await SentryIsolate.handleIsolateError( + hub, [exception.toString(), stackTrace]); + + final capturedEvent = client.captureEventCalls.last.event; + expect(capturedEvent.level, SentryLevel.error); + }); }); } diff --git a/flutter/lib/src/integrations/flutter_error_integration.dart b/flutter/lib/src/integrations/flutter_error_integration.dart index a9f10bcc09..3f88b99361 100644 --- a/flutter/lib/src/integrations/flutter_error_integration.dart +++ b/flutter/lib/src/integrations/flutter_error_integration.dart @@ -63,7 +63,9 @@ class FlutterErrorIntegration implements Integration { var event = SentryEvent( throwable: throwableMechanism, - level: SentryLevel.fatal, + level: options.markAutomaticallyCollectedErrorsAsFatal + ? SentryLevel.fatal + : SentryLevel.error, contexts: flutterErrorDetails.isNotEmpty ? (Contexts()..['flutter_error_details'] = flutterErrorDetails) : null, diff --git a/flutter/lib/src/native/cocoa/binding.dart b/flutter/lib/src/native/cocoa/binding.dart index 646a6bea83..0bd2e0437e 100644 --- a/flutter/lib/src/native/cocoa/binding.dart +++ b/flutter/lib/src/native/cocoa/binding.dart @@ -37603,7 +37603,8 @@ class ObjCBlock_bool_ObjCObject_ffiUnsignedLong_bool extends _ObjCBlockBase { ObjCBlock_bool_ObjCObject_ffiUnsignedLong_bool.fromFunctionPointer( SentryCocoa lib, ffi.Pointer< - ffi.NativeFunction< + ffi + .NativeFunction< ffi.Bool Function(ffi.Pointer arg0, ffi.UnsignedLong arg1, ffi.Pointer arg2)>> ptr) @@ -42031,15 +42032,17 @@ class ObjCBlock_bool_ObjCObject_bool extends _ObjCBlockBase { ffi.Pointer arg1)>> ptr) : this._( - lib._newBlock1( - _cFuncTrampoline ??= ffi.Pointer.fromFunction< - ffi.Bool Function( - ffi.Pointer<_ObjCBlock> block, - ffi.Pointer arg0, - ffi.Pointer arg1)>( - _ObjCBlock_bool_ObjCObject_bool_fnPtrTrampoline, false) - .cast(), - ptr.cast()), + lib + ._newBlock1( + _cFuncTrampoline ??= ffi.Pointer.fromFunction< + ffi.Bool Function( + ffi.Pointer<_ObjCBlock> block, + ffi.Pointer arg0, + ffi.Pointer arg1)>( + _ObjCBlock_bool_ObjCObject_bool_fnPtrTrampoline, + false) + .cast(), + ptr.cast()), lib); static ffi.Pointer? _cFuncTrampoline; diff --git a/flutter/test/integrations/flutter_error_integration_test.dart b/flutter/test/integrations/flutter_error_integration_test.dart index 53446caeda..6c479fdf39 100644 --- a/flutter/test/integrations/flutter_error_integration_test.dart +++ b/flutter/test/integrations/flutter_error_integration_test.dart @@ -246,6 +246,20 @@ void main() { await span?.finish(); }); + + test('captures error with level error', () async { + final exception = StateError('error'); + + fixture.options.markAutomaticallyCollectedErrorsAsFatal = false; + + _reportError(exception: exception); + + final event = verify( + await fixture.hub.captureEvent(captureAny, hint: anyNamed('hint')), + ).captured.first as SentryEvent; + + expect(event.level, SentryLevel.error); + }); }); } From 886fc8c6af1fdf1bd4e4b118869f777fe3481c7b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 28 Nov 2023 13:28:24 +0100 Subject: [PATCH 014/237] build(deps): bump natiginfo/action-detekt-all from 1.23.3 to 1.23.4 (#1758) Bumps [natiginfo/action-detekt-all](https://github.com/natiginfo/action-detekt-all) from 1.23.3 to 1.23.4. - [Release notes](https://github.com/natiginfo/action-detekt-all/releases) - [Commits](https://github.com/natiginfo/action-detekt-all/compare/68eb02dd9f2c2686d5026f5957756064424261a9...1349d3d957cba64d7b6b2752ef874d1e03e402a2) --- updated-dependencies: - dependency-name: natiginfo/action-detekt-all dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/flutter.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/flutter.yml b/.github/workflows/flutter.yml index d5b5fb3472..df20a20efd 100644 --- a/.github/workflows/flutter.yml +++ b/.github/workflows/flutter.yml @@ -202,6 +202,6 @@ jobs: steps: - uses: actions/checkout@v4 # To recreate baseline run: detekt -i flutter/android,flutter/example/android -b flutter/config/detekt-bl.xml -cb - - uses: natiginfo/action-detekt-all@68eb02dd9f2c2686d5026f5957756064424261a9 # pin@1.23.3 + - uses: natiginfo/action-detekt-all@1349d3d957cba64d7b6b2752ef874d1e03e402a2 # pin@1.23.4 with: args: -i flutter/android,flutter/example/android --baseline flutter/config/detekt-bl.xml --jvm-target 1.8 --build-upon-default-config --all-rules From 8fb602f1a48412640bfb16e465a7428be2d74cf5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 28 Nov 2023 14:27:49 +0100 Subject: [PATCH 015/237] chore(deps): update Cocoa SDK to v8.17.0 (#1761) * chore: update flutter/scripts/update-cocoa.sh to 8.17.0 * Apply format --------- Co-authored-by: GitHub Co-authored-by: GIancarlo Buenaflor --- CHANGELOG.md | 6 ++++++ flutter/ios/sentry_flutter.podspec | 2 +- flutter/lib/src/native/cocoa/binding.dart | 23 ++++++++++------------- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3056915989..b00adcfff0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,12 @@ - Add option to opt out of fatal level for automatically collected errors ([#1738](https://github.com/getsentry/sentry-dart/pull/1738)) +### Dependencies + +- Bump Cocoa SDK from v8.15.2 to v8.17.0 ([#1761](https://github.com/getsentry/sentry-dart/pull/1761)) + - [changelog](https://github.com/getsentry/sentry-cocoa/blob/main/CHANGELOG.md#8170) + - [diff](https://github.com/getsentry/sentry-cocoa/compare/8.15.2...8.17.0) + ## 7.13.2 ### Fixes diff --git a/flutter/ios/sentry_flutter.podspec b/flutter/ios/sentry_flutter.podspec index a309f686b6..403f5378b5 100644 --- a/flutter/ios/sentry_flutter.podspec +++ b/flutter/ios/sentry_flutter.podspec @@ -12,7 +12,7 @@ Sentry SDK for Flutter with support to native through sentry-cocoa. :tag => s.version.to_s } s.source_files = 'Classes/**/*' s.public_header_files = 'Classes/**/*.h' - s.dependency 'Sentry/HybridSDK', '8.15.2' + s.dependency 'Sentry/HybridSDK', '8.17.0' s.ios.dependency 'Flutter' s.osx.dependency 'FlutterMacOS' s.ios.deployment_target = '11.0' diff --git a/flutter/lib/src/native/cocoa/binding.dart b/flutter/lib/src/native/cocoa/binding.dart index 0bd2e0437e..646a6bea83 100644 --- a/flutter/lib/src/native/cocoa/binding.dart +++ b/flutter/lib/src/native/cocoa/binding.dart @@ -37603,8 +37603,7 @@ class ObjCBlock_bool_ObjCObject_ffiUnsignedLong_bool extends _ObjCBlockBase { ObjCBlock_bool_ObjCObject_ffiUnsignedLong_bool.fromFunctionPointer( SentryCocoa lib, ffi.Pointer< - ffi - .NativeFunction< + ffi.NativeFunction< ffi.Bool Function(ffi.Pointer arg0, ffi.UnsignedLong arg1, ffi.Pointer arg2)>> ptr) @@ -42032,17 +42031,15 @@ class ObjCBlock_bool_ObjCObject_bool extends _ObjCBlockBase { ffi.Pointer arg1)>> ptr) : this._( - lib - ._newBlock1( - _cFuncTrampoline ??= ffi.Pointer.fromFunction< - ffi.Bool Function( - ffi.Pointer<_ObjCBlock> block, - ffi.Pointer arg0, - ffi.Pointer arg1)>( - _ObjCBlock_bool_ObjCObject_bool_fnPtrTrampoline, - false) - .cast(), - ptr.cast()), + lib._newBlock1( + _cFuncTrampoline ??= ffi.Pointer.fromFunction< + ffi.Bool Function( + ffi.Pointer<_ObjCBlock> block, + ffi.Pointer arg0, + ffi.Pointer arg1)>( + _ObjCBlock_bool_ObjCObject_bool_fnPtrTrampoline, false) + .cast(), + ptr.cast()), lib); static ffi.Pointer? _cFuncTrampoline; From 9220bb8489e224b3dd0a78070d933f1e5fe62403 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 28 Nov 2023 17:03:54 +0100 Subject: [PATCH 016/237] build(deps): bump subosito/flutter-action from 2.10.0 to 2.12.0 (#1759) Bumps [subosito/flutter-action](https://github.com/subosito/flutter-action) from 2.10.0 to 2.12.0. - [Release notes](https://github.com/subosito/flutter-action/releases) - [Commits](https://github.com/subosito/flutter-action/compare/v2.10.0...2783a3f08e1baf891508463f8c6653c258246225) --- updated-dependencies: - dependency-name: subosito/flutter-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor --- .github/workflows/drift.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/drift.yml b/.github/workflows/drift.yml index a7597909ad..2cf22e8bbd 100644 --- a/.github/workflows/drift.yml +++ b/.github/workflows/drift.yml @@ -78,7 +78,7 @@ jobs: sudo apt install -y network-manager upower if: matrix.os == 'ubuntu-latest' && matrix.target == 'linux' - - uses: subosito/flutter-action@48cafc24713cca54bbe03cdc3a423187d413aafa # pin@v2.10.0 + - uses: subosito/flutter-action@2783a3f08e1baf891508463f8c6653c258246225 # pin@v2.12.0 with: channel: ${{ matrix.sdk }} From 3f3ef0be1de5e508cf4723d8ea213dcc1b7751f8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 29 Nov 2023 12:34:25 +0100 Subject: [PATCH 017/237] chore: update metrics/flutter.properties to 3.16.1 (#1760) Co-authored-by: GitHub --- metrics/flutter.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/metrics/flutter.properties b/metrics/flutter.properties index 46cc19edb4..49d9615381 100644 --- a/metrics/flutter.properties +++ b/metrics/flutter.properties @@ -1,2 +1,2 @@ -version = 3.13.9 +version = 3.16.1 repo = https://github.com/flutter/flutter From 4829ad36de3c9b0c6cd7c1d030ee2987d7bb7347 Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Wed, 29 Nov 2023 15:11:59 +0100 Subject: [PATCH 018/237] fix(example): web obfuscation not working (#1766) --- flutter/example/run.sh | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/flutter/example/run.sh b/flutter/example/run.sh index d40bc89df2..025a6f31b4 100755 --- a/flutter/example/run.sh +++ b/flutter/example/run.sh @@ -6,7 +6,10 @@ set -euo pipefail # Or try out the Alpha version of the Sentry Dart Plugin that does it automatically for you, feedback is welcomed. # https://github.com/getsentry/sentry-dart-plugin -export SENTRY_RELEASE=$(date +%Y-%m-%d_%H-%M-%S) +VERSION=$(grep '^version:' pubspec.yaml | awk '{print $2}') +CURRENT_DATE=$(date +%Y-%m-%d_%H-%M-%S) + +export SENTRY_RELEASE="$CURRENT_DATE"@"$VERSION" echo -e "[\033[92mrun\033[0m] $1" @@ -23,7 +26,7 @@ elif [ "$1" == "android" ]; then launchCmd='adb shell am start -n io.sentry.samples.flutter/io.sentry.samples.flutter.MainActivity' echo -e "[\033[92mrun\033[0m] Android app installed" elif [ "$1" == "web" ]; then - flutter build web --dart-define=SENTRY_RELEASE=$SENTRY_RELEASE --source-maps + flutter build web --dart-define=SENTRY_RELEASE="$SENTRY_RELEASE" --source-maps buildDir='./build/web/' port='8132' ls -lah $buildDir From f25f20767a49557d3024ff6d3220ae01dfcab209 Mon Sep 17 00:00:00 2001 From: Stefano Date: Wed, 29 Nov 2023 17:56:32 +0100 Subject: [PATCH 019/237] Add debug_meta to all events (#1756) * load_image_list_integration now appends debug_meta info to all non-transaction events with a stacktrace, instead of checking for Exception existence --- CHANGELOG.md | 5 +++++ .../load_image_list_integration.dart | 21 ++++++++++++++----- .../integrations/load_image_list_test.dart | 7 +------ 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b00adcfff0..11a30dc056 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ ## Unreleased +### Fixes + +- Add debug_meta to all events ([#1756](https://github.com/getsentry/sentry-dart/pull/1756)) + - Fixes obfuscated stacktraces when `captureMessage` or `captureEvent` is called with `attachStacktrace` option + ### Features - Add option to opt out of fatal level for automatically collected errors ([#1738](https://github.com/getsentry/sentry-dart/pull/1738)) diff --git a/flutter/lib/src/integrations/load_image_list_integration.dart b/flutter/lib/src/integrations/load_image_list_integration.dart index c2a0c98848..8838ae0e4b 100644 --- a/flutter/lib/src/integrations/load_image_list_integration.dart +++ b/flutter/lib/src/integrations/load_image_list_integration.dart @@ -25,14 +25,25 @@ extension _NeedsSymbolication on SentryEvent { if (this is SentryTransaction) { return false; } - if (exceptions?.isNotEmpty == false) { - return false; - } - final frames = exceptions?.first.stackTrace?.frames; + final frames = _getStacktraceFrames(); if (frames == null) { return false; } - return frames.any((frame) => 'native' == frame.platform); + return frames.any((frame) => 'native' == frame?.platform); + } + + List? _getStacktraceFrames() { + if (exceptions?.isNotEmpty == true) { + return exceptions?.first.stackTrace?.frames; + } + if (threads?.isNotEmpty == true) { + var stacktraces = threads?.map((e) => e.stacktrace); + return stacktraces + ?.where((element) => element != null) + .expand((element) => element!.frames) + .toList(); + } + return null; } } diff --git a/flutter/test/integrations/load_image_list_test.dart b/flutter/test/integrations/load_image_list_test.dart index bb78561dae..085bbcd3dc 100644 --- a/flutter/test/integrations/load_image_list_test.dart +++ b/flutter/test/integrations/load_image_list_test.dart @@ -187,12 +187,7 @@ void main() { SentryEvent _getEvent() { final frame = SentryStackFrame(platform: 'native'); final st = SentryStackTrace(frames: [frame]); - final ex = SentryException( - type: 'type', - value: 'value', - stackTrace: st, - ); - return SentryEvent(exceptions: [ex]); + return SentryEvent(threads: [SentryThread(stacktrace: st)]); } class Fixture { From 4b3af28592b0043da0712a8173a8b6bde7724f5c Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Fri, 1 Dec 2023 16:00:32 +0100 Subject: [PATCH 020/237] chore: Update README to include drift and hive (#1735) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: GitHub Co-authored-by: GIancarlo Buenaflor Co-authored-by: Giancarlo Buenaflor Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: getsentry-bot Co-authored-by: Denis Andrašec --- README.md | 18 ++++++++++-------- drift/README.md | 2 +- hive/README.md | 6 +++--- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 8ab372fc5a..1a6d03bc41 100644 --- a/README.md +++ b/README.md @@ -14,18 +14,20 @@ Sentry SDK for Dart and Flutter [![codecov](https://codecov.io/gh/getsentry/sentry-dart/branch/main/graph/badge.svg?token=J0QX0LPmwy)](https://codecov.io/gh/getsentry/sentry-dart) -| package | build | pub | likes | popularity | pub points | -| ------- | ------- | ------- | ------- | ------- | ------- | -| sentry | [![build](https://github.com/getsentry/sentry-dart/workflows/sentry-dart/badge.svg?branch=main)](https://github.com/getsentry/sentry-dart/actions?query=workflow%3Asentry-dart) | [![pub package](https://img.shields.io/pub/v/sentry.svg)](https://pub.dev/packages/sentry) | [![likes](https://img.shields.io/pub/likes/sentry?logo=dart)](https://pub.dev/packages/sentry/score) | [![popularity](https://img.shields.io/pub/popularity/sentry?logo=dart)](https://pub.dev/packages/sentry/score) | [![pub points](https://img.shields.io/pub/points/sentry?logo=dart)](https://pub.dev/packages/sentry/score) +| package | build | pub | likes | popularity | pub points | +|----------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------| ------- | ------- | +| sentry | [![build](https://github.com/getsentry/sentry-dart/actions/workflows/dart.yml/badge.svg?branch=main)](https://github.com/getsentry/sentry-dart/actions?query=workflow%3Asentry-dart) | [![pub package](https://img.shields.io/pub/v/sentry.svg)](https://pub.dev/packages/sentry) | [![likes](https://img.shields.io/pub/likes/sentry?logo=dart)](https://pub.dev/packages/sentry/score) | [![popularity](https://img.shields.io/pub/popularity/sentry?logo=dart)](https://pub.dev/packages/sentry/score) | [![pub points](https://img.shields.io/pub/points/sentry?logo=dart)](https://pub.dev/packages/sentry/score) | sentry_flutter | [![build](https://github.com/getsentry/sentry-dart/workflows/sentry-flutter/badge.svg?branch=main)](https://github.com/getsentry/sentry-dart/actions?query=workflow%3Asentry-flutter) | [![pub package](https://img.shields.io/pub/v/sentry_flutter.svg)](https://pub.dev/packages/sentry_flutter) | [![likes](https://img.shields.io/pub/likes/sentry_flutter?logo=dart)](https://pub.dev/packages/sentry_flutter/score) | [![popularity](https://img.shields.io/pub/popularity/sentry_flutter?logo=dart)](https://pub.dev/packages/sentry_flutter/score) | [![pub points](https://img.shields.io/pub/points/sentry_flutter?logo=dart)](https://pub.dev/packages/sentry_flutter/score) -| sentry_logging | [![build](https://github.com/getsentry/sentry-dart/workflows/sentry-logging/badge.svg?branch=main)](https://github.com/getsentry/sentry-dart/actions?query=workflow%3Alogging) | [![pub package](https://img.shields.io/pub/v/sentry_logging.svg)](https://pub.dev/packages/sentry_logging) | [![likes](https://img.shields.io/pub/likes/sentry_logging?logo=dart)](https://pub.dev/packages/sentry_logging/score) | [![popularity](https://img.shields.io/pub/popularity/sentry_logging?logo=dart)](https://pub.dev/packages/sentry_logging/score) | [![pub points](https://img.shields.io/pub/points/sentry_logging?logo=dart)](https://pub.dev/packages/sentry_logging/score) -| sentry_dio | [![build](https://github.com/getsentry/sentry-dart/workflows/sentry-dio/badge.svg?branch=main)](https://github.com/getsentry/sentry-dart/actions?query=workflow%3Asentry-dio) | [![pub package](https://img.shields.io/pub/v/sentry_dio.svg)](https://pub.dev/packages/sentry_dio) | [![likes](https://img.shields.io/pub/likes/sentry_dio?logo=dart)](https://pub.dev/packages/sentry_dio/score) | [![popularity](https://img.shields.io/pub/popularity/sentry_dio?logo=dart)](https://pub.dev/packages/sentry_dio/score) | [![pub points](https://img.shields.io/pub/points/sentry_dio?logo=dart)](https://pub.dev/packages/sentry_dio/score) -| sentry_file | [![build](https://github.com/getsentry/sentry-dart/workflows/sentry-file/badge.svg?branch=main)](https://github.com/getsentry/sentry-dart/actions?query=workflow%3Asentry-file) | [![pub package](https://img.shields.io/pub/v/sentry_file.svg)](https://pub.dev/packages/sentry_file) | [![likes](https://img.shields.io/pub/likes/sentry_file?logo=dart)](https://pub.dev/packages/sentry_file/score) | [![popularity](https://img.shields.io/pub/popularity/sentry_file?logo=dart)](https://pub.dev/packages/sentry_file/score) | [![pub points](https://img.shields.io/pub/points/sentry_file?logo=dart)](https://pub.dev/packages/sentry_file/score) -| sentry_sqflite | [![build](https://github.com/getsentry/sentry-dart/workflows/sentry-sqflite/badge.svg?branch=main)](https://github.com/getsentry/sentry-dart/actions?query=workflow%3Asentry-sqflite) | [![pub package](https://img.shields.io/pub/v/sentry_sqflite.svg)](https://pub.dev/packages/sentry_sqflite) | [![likes](https://img.shields.io/pub/likes/sentry_sqflite)](https://pub.dev/packages/sentry_sqflite/score) | [![popularity](https://img.shields.io/pub/popularity/sentry_sqflite)](https://pub.dev/packages/sentry_sqflite/score) | [![pub points](https://img.shields.io/pub/points/sentry_sqflite)](https://pub.dev/packages/sentry_sqflite/score) +| sentry_logging | [![build](https://github.com/getsentry/sentry-dart/workflows/sentry-logging/badge.svg?branch=main)](https://github.com/getsentry/sentry-dart/actions?query=workflow%3Alogging) | [![pub package](https://img.shields.io/pub/v/sentry_logging.svg)](https://pub.dev/packages/sentry_logging) | [![likes](https://img.shields.io/pub/likes/sentry_logging?logo=dart)](https://pub.dev/packages/sentry_logging/score) | [![popularity](https://img.shields.io/pub/popularity/sentry_logging?logo=dart)](https://pub.dev/packages/sentry_logging/score) | [![pub points](https://img.shields.io/pub/points/sentry_logging?logo=dart)](https://pub.dev/packages/sentry_logging/score) +| sentry_dio | [![build](https://github.com/getsentry/sentry-dart/workflows/sentry-dio/badge.svg?branch=main)](https://github.com/getsentry/sentry-dart/actions?query=workflow%3Asentry-dio) | [![pub package](https://img.shields.io/pub/v/sentry_dio.svg)](https://pub.dev/packages/sentry_dio) | [![likes](https://img.shields.io/pub/likes/sentry_dio?logo=dart)](https://pub.dev/packages/sentry_dio/score) | [![popularity](https://img.shields.io/pub/popularity/sentry_dio?logo=dart)](https://pub.dev/packages/sentry_dio/score) | [![pub points](https://img.shields.io/pub/points/sentry_dio?logo=dart)](https://pub.dev/packages/sentry_dio/score) +| sentry_file | [![build](https://github.com/getsentry/sentry-dart/workflows/sentry-file/badge.svg?branch=main)](https://github.com/getsentry/sentry-dart/actions?query=workflow%3Asentry-file) | [![pub package](https://img.shields.io/pub/v/sentry_file.svg)](https://pub.dev/packages/sentry_file) | [![likes](https://img.shields.io/pub/likes/sentry_file?logo=dart)](https://pub.dev/packages/sentry_file/score) | [![popularity](https://img.shields.io/pub/popularity/sentry_file?logo=dart)](https://pub.dev/packages/sentry_file/score) | [![pub points](https://img.shields.io/pub/points/sentry_file?logo=dart)](https://pub.dev/packages/sentry_file/score) +| sentry_sqflite | [![build](https://github.com/getsentry/sentry-dart/workflows/sentry-sqflite/badge.svg?branch=main)](https://github.com/getsentry/sentry-dart/actions?query=workflow%3Asentry-sqflite) | [![pub package](https://img.shields.io/pub/v/sentry_sqflite.svg)](https://pub.dev/packages/sentry_sqflite) | [![likes](https://img.shields.io/pub/likes/sentry_sqflite)](https://pub.dev/packages/sentry_sqflite/score) | [![popularity](https://img.shields.io/pub/popularity/sentry_sqflite)](https://pub.dev/packages/sentry_sqflite/score) | [![pub points](https://img.shields.io/pub/points/sentry_sqflite)](https://pub.dev/packages/sentry_sqflite/score) +| sentry_drift | [![build](https://github.com/getsentry/sentry-dart/actions/workflows/drift.yml/badge.svg?branch=main)](https://github.com/getsentry/sentry-dart/actions?query=workflow%3Asentry-drift) | [![pub package](https://img.shields.io/pub/v/sentry_drift.svg)](https://pub.dev/packages/sentry_drift) | [![likes](https://img.shields.io/pub/likes/sentry_drift)](https://pub.dev/packages/sentry_drift/score) | [![popularity](https://img.shields.io/pub/popularity/sentry_drift)](https://pub.dev/packages/sentry_drift/score) | [![pub points](https://img.shields.io/pub/points/sentry_drift)](https://pub.dev/packages/sentry_drift/score) +| sentry_hive | [![build](https://github.com/getsentry/sentry-dart/actions/workflows/hive.yml/badge.svg?branch=main)](https://github.com/getsentry/sentry-dart/actions?query=workflow%3Asentry-hive) | [![pub package](https://img.shields.io/pub/v/sentry_hive.svg)](https://pub.dev/packages/sentry_hive) | [![likes](https://img.shields.io/pub/likes/sentry_hive)](https://pub.dev/packages/sentry_hive/score) | [![popularity](https://img.shields.io/pub/popularity/sentry_hive)](https://pub.dev/packages/sentry_hive/score) | [![pub points](https://img.shields.io/pub/points/sentry_hive)](https://pub.dev/packages/sentry_hive/score) ##### Usage -For detailed usage, check out the inner [dart](https://github.com/getsentry/sentry-dart/tree/main/dart), [flutter](https://github.com/getsentry/sentry-dart/tree/main/flutter), [logging](https://github.com/getsentry/sentry-dart/tree/main/logging), [dio](https://github.com/getsentry/sentry-dart/tree/main/dio), [file](https://github.com/getsentry/sentry-dart/tree/main/file) and [sqflite](https://github.com/getsentry/sentry-dart/tree/main/sqflite) `README's` or our `Resources` section below. +For detailed usage, check out the inner [dart](https://github.com/getsentry/sentry-dart/tree/main/dart), [flutter](https://github.com/getsentry/sentry-dart/tree/main/flutter), [logging](https://github.com/getsentry/sentry-dart/tree/main/logging), [dio](https://github.com/getsentry/sentry-dart/tree/main/dio), [file](https://github.com/getsentry/sentry-dart/tree/main/file), [sqflite](https://github.com/getsentry/sentry-dart/tree/main/sqflite), [drift](https://github.com/getsentry/sentry-dart/tree/main/drift) and [hive](https://github.com/getsentry/sentry-dart/tree/main/hive) `README's` or our `Resources` section below. #### Blog posts diff --git a/drift/README.md b/drift/README.md index e6fd9e6d11..43d26893e4 100644 --- a/drift/README.md +++ b/drift/README.md @@ -10,7 +10,7 @@ Sentry integration for `drift` package | package | build | pub | likes | popularity | pub points | |-------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------| ------- | -| sentry_drift | [![build](https://github.com/getsentry/sentry-dart/workflows/sentry-drift/badge.svg?branch=main)](https://github.com/getsentry/sentry-dart/actions?query=workflow%3Asentry-drift) | [![pub package](https://img.shields.io/pub/v/sentry_drift.svg)](https://pub.dev/packages/sentry_drift) | [![likes](https://img.shields.io/pub/likes/sentry_drift)](https://pub.dev/packages/sentry_drift/score) | [![popularity](https://img.shields.io/pub/popularity/sentry_drift)](https://pub.dev/packages/sentry_drift/score) | [![pub points](https://img.shields.io/pub/points/sentry_drift)](https://pub.dev/packages/sentry_drift/score) +| sentry_drift | [![build](https://github.com/getsentry/sentry-dart/actions/workflows/drift.yml/badge.svg?branch=main)](https://github.com/getsentry/sentry-dart/actions?query=workflow%3Asentry-drift) | [![pub package](https://img.shields.io/pub/v/sentry_drift.svg)](https://pub.dev/packages/sentry_drift) | [![likes](https://img.shields.io/pub/likes/sentry_drift)](https://pub.dev/packages/sentry_drift/score) | [![popularity](https://img.shields.io/pub/popularity/sentry_drift)](https://pub.dev/packages/sentry_drift/score) | [![pub points](https://img.shields.io/pub/points/sentry_drift)](https://pub.dev/packages/sentry_drift/score) Integration for the [`drift`](https://pub.dev/packages/drift) package. diff --git a/hive/README.md b/hive/README.md index 593d367100..a5347c31a4 100644 --- a/hive/README.md +++ b/hive/README.md @@ -8,9 +8,9 @@ Sentry integration for `hive` package =========== -| package | build | pub | likes | popularity | pub points | -|-------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------| ------- | -| sentry_hive | [![build](https://github.com/getsentry/sentry-dart/workflows/sentry-hive/badge.svg?branch=main)](https://github.com/getsentry/sentry-dart/actions?query=workflow%3Asentry-hive) | [![pub package](https://img.shields.io/pub/v/sentry_hive.svg)](https://pub.dev/packages/sentry_hive) | [![likes](https://img.shields.io/pub/likes/sentry_hive)](https://pub.dev/packages/sentry_hive/score) | [![popularity](https://img.shields.io/pub/popularity/sentry_hive)](https://pub.dev/packages/sentry_hive/score) | [![pub points](https://img.shields.io/pub/points/sentry_hive)](https://pub.dev/packages/sentry_hive/score) +| package | build | pub | likes | popularity | pub points | +|-------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------| ------- | +| sentry_hive | [![build](https://github.com/getsentry/sentry-dart/actions/workflows/hive.yml/badge.svg?branch=main)](https://github.com/getsentry/sentry-dart/actions?query=workflow%3Asentry-hive) | [![pub package](https://img.shields.io/pub/v/sentry_hive.svg)](https://pub.dev/packages/sentry_hive) | [![likes](https://img.shields.io/pub/likes/sentry_hive)](https://pub.dev/packages/sentry_hive/score) | [![popularity](https://img.shields.io/pub/popularity/sentry_hive)](https://pub.dev/packages/sentry_hive/score) | [![pub points](https://img.shields.io/pub/points/sentry_hive)](https://pub.dev/packages/sentry_hive/score) Integration for the [`hive`](https://pub.dev/packages/hive) package. From 47664e3c2abb87b18bde99ff91db7ef565ccf9ca Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 5 Dec 2023 13:01:40 +0100 Subject: [PATCH 021/237] chore: update metrics/flutter.properties to 3.16.2 (#1769) Co-authored-by: GitHub --- metrics/flutter.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/metrics/flutter.properties b/metrics/flutter.properties index 49d9615381..a0e5a0f324 100644 --- a/metrics/flutter.properties +++ b/metrics/flutter.properties @@ -1,2 +1,2 @@ -version = 3.16.1 +version = 3.16.2 repo = https://github.com/flutter/flutter From 2d74010a6f7e9329b48218a0a8931cf732203bd7 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 5 Dec 2023 13:01:59 +0100 Subject: [PATCH 022/237] chore(deps): update Cocoa SDK to v8.17.1 (#1771) * chore: update flutter/scripts/update-cocoa.sh to 8.17.1 * Formatting --------- Co-authored-by: GitHub Co-authored-by: GIancarlo Buenaflor --- CHANGELOG.md | 6 +++--- flutter/ios/sentry_flutter.podspec | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 11a30dc056..9ca2ec553e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,9 +13,9 @@ ### Dependencies -- Bump Cocoa SDK from v8.15.2 to v8.17.0 ([#1761](https://github.com/getsentry/sentry-dart/pull/1761)) - - [changelog](https://github.com/getsentry/sentry-cocoa/blob/main/CHANGELOG.md#8170) - - [diff](https://github.com/getsentry/sentry-cocoa/compare/8.15.2...8.17.0) +- Bump Cocoa SDK from v8.15.2 to v8.17.1 ([#1761](https://github.com/getsentry/sentry-dart/pull/1761), [#1771](https://github.com/getsentry/sentry-dart/pull/1771)) + - [changelog](https://github.com/getsentry/sentry-cocoa/blob/main/CHANGELOG.md#8171) + - [diff](https://github.com/getsentry/sentry-cocoa/compare/8.15.2...8.17.1) ## 7.13.2 diff --git a/flutter/ios/sentry_flutter.podspec b/flutter/ios/sentry_flutter.podspec index 403f5378b5..9a9f6265a6 100644 --- a/flutter/ios/sentry_flutter.podspec +++ b/flutter/ios/sentry_flutter.podspec @@ -12,7 +12,7 @@ Sentry SDK for Flutter with support to native through sentry-cocoa. :tag => s.version.to_s } s.source_files = 'Classes/**/*' s.public_header_files = 'Classes/**/*.h' - s.dependency 'Sentry/HybridSDK', '8.17.0' + s.dependency 'Sentry/HybridSDK', '8.17.1' s.ios.dependency 'Flutter' s.osx.dependency 'FlutterMacOS' s.ios.deployment_target = '11.0' From d3801f8538ee716bbb90756a87188fd84693cdf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20Andra=C5=A1ec?= Date: Tue, 5 Dec 2023 14:04:42 +0000 Subject: [PATCH 023/237] Add `Hive` breadcrumbs (#1773) --- CHANGELOG.md | 1 + hive/lib/src/sentry_span_helper.dart | 22 +- hive/test/sentry_box_base_test.dart | 272 +++++++++++++++++++++ hive/test/sentry_box_collection_test.dart | 173 ++++++++++++++ hive/test/sentry_hive_impl_test.dart | 278 ++++++++++++++++++++++ hive/test/sentry_lazy_box_test.dart | 121 ++++++++++ 6 files changed, 866 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ca2ec553e..4c983f6680 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ ### Features - Add option to opt out of fatal level for automatically collected errors ([#1738](https://github.com/getsentry/sentry-dart/pull/1738)) +- Add `Hive` breadcrumbs ([#1773](https://github.com/getsentry/sentry-dart/pull/1773)) ### Dependencies diff --git a/hive/lib/src/sentry_span_helper.dart b/hive/lib/src/sentry_span_helper.dart index a1c780ef08..38a67501a4 100644 --- a/hive/lib/src/sentry_span_helper.dart +++ b/hive/lib/src/sentry_span_helper.dart @@ -35,24 +35,44 @@ class SentrySpanHelper { // ignore: invalid_use_of_internal_member span?.origin = _origin; - span?.setData(SentryHiveImpl.dbSystemKey, SentryHiveImpl.dbSystem); + var breadcrumb = Breadcrumb( + message: description, + data: {}, + type: 'query', + ); + span?.setData(SentryHiveImpl.dbSystemKey, SentryHiveImpl.dbSystem); if (dbName != null) { span?.setData(SentryHiveImpl.dbNameKey, dbName); } + breadcrumb.data?[SentryHiveImpl.dbSystemKey] = SentryHiveImpl.dbSystem; + if (dbName != null) { + breadcrumb.data?[SentryHiveImpl.dbNameKey] = dbName; + } + try { final result = await execute(); + span?.status = SpanStatus.ok(); + breadcrumb.data?['status'] = 'ok'; return result; } catch (exception) { span?.throwable = exception; span?.status = SpanStatus.internalError(); + breadcrumb.data?['status'] = 'internal_error'; + breadcrumb = breadcrumb.copyWith( + level: SentryLevel.warning, + ); + rethrow; } finally { await span?.finish(); + + // ignore: invalid_use_of_internal_member + await _hub.scope.addBreadcrumb(breadcrumb); } } } diff --git a/hive/test/sentry_box_base_test.dart b/hive/test/sentry_box_base_test.dart index 3caf5e06e5..3821b8b341 100644 --- a/hive/test/sentry_box_base_test.dart +++ b/hive/test/sentry_box_base_test.dart @@ -40,6 +40,23 @@ void main() { expect(span?.throwable, exception); } + void verifyBreadcrumb( + String message, + Breadcrumb? crumb, { + bool checkName = false, + String status = 'ok', + }) { + expect( + crumb?.message, + message, + ); + expect(crumb?.type, 'query'); + if (checkName) { + expect(crumb?.data?[SentryHiveImpl.dbNameKey], Fixture.dbName); + } + expect(crumb?.data?['status'], status); + } + group('adds span', () { late Fixture fixture; @@ -49,6 +66,7 @@ void main() { when(fixture.hub.options).thenReturn(fixture.options); when(fixture.hub.getSpan()).thenReturn(fixture.tracer); + when(fixture.hub.scope).thenReturn(fixture.scope); }); tearDown(() async { @@ -131,6 +149,7 @@ void main() { when(fixture.hub.options).thenReturn(fixture.options); when(fixture.hub.getSpan()).thenReturn(fixture.tracer); when(fixture.mockBox.name).thenReturn(Fixture.dbName); + when(fixture.hub.scope).thenReturn(fixture.scope); }); tearDown(() async { @@ -253,6 +272,254 @@ void main() { verifyErrorSpan('deleteAt', fixture.exception, fixture.getCreatedSpan()); }); }); + + group('adds breadcrumb', () { + late Fixture fixture; + + setUp(() async { + fixture = Fixture(); + await fixture.setUp(); + + when(fixture.hub.options).thenReturn(fixture.options); + when(fixture.hub.getSpan()).thenReturn(fixture.tracer); + when(fixture.hub.scope).thenReturn(fixture.scope); + }); + + tearDown(() async { + await fixture.tearDown(); + }); + + test('add adds breadcrumb', () async { + final sut = fixture.getSut(); + + await sut.add(Person('Joe Dirt')); + + verifyBreadcrumb('add', fixture.getCreatedBreadcrumb()); + }); + + test('addAll adds breadcrumb', () async { + final sut = fixture.getSut(); + + await sut.addAll([Person('Joe Dirt')]); + + verifyBreadcrumb('addAll', fixture.getCreatedBreadcrumb()); + }); + + test('clear adds breadcrumb', () async { + final sut = fixture.getSut(); + + await sut.clear(); + + verifyBreadcrumb('clear', fixture.getCreatedBreadcrumb()); + }); + + test('close adds breadcrumb', () async { + final sut = fixture.getSut(); + + await sut.close(); + + verifyBreadcrumb('close', fixture.getCreatedBreadcrumb()); + }); + + test('compact adds breadcrumb', () async { + final sut = fixture.getSut(); + + await sut.compact(); + + verifyBreadcrumb('compact', fixture.getCreatedBreadcrumb()); + }); + + test('delete adds breadcrumb', () async { + final sut = fixture.getSut(); + + await sut.delete('fixture-key'); + + verifyBreadcrumb('delete', fixture.getCreatedBreadcrumb()); + }); + + test('deleteAll adds breadcrumb', () async { + final sut = fixture.getSut(); + + await sut.deleteAll(['fixture-key']); + + verifyBreadcrumb('deleteAll', fixture.getCreatedBreadcrumb()); + }); + + test('deleteAt adds breadcrumb', () async { + final sut = fixture.getSut(); + + await sut.add(Person('Joe Dirt')); + await sut.deleteAt(0); + + verifyBreadcrumb('deleteAt', fixture.getCreatedBreadcrumb()); + }); + }); + + group('adds error breadcrumb', () { + late Fixture fixture; + + setUp(() async { + fixture = Fixture(); + await fixture.setUp(); + + when(fixture.hub.options).thenReturn(fixture.options); + when(fixture.hub.getSpan()).thenReturn(fixture.tracer); + when(fixture.mockBox.name).thenReturn(Fixture.dbName); + when(fixture.hub.scope).thenReturn(fixture.scope); + }); + + tearDown(() async { + await fixture.tearDown(); + }); + + test('throwing add adds error breadcrumb', () async { + when(fixture.mockBox.add(any)).thenThrow(fixture.exception); + + final sut = fixture.getSut(injectMockBox: true); + + try { + await sut.add(Person('Joe Dirt')); + } catch (error) { + expect(error, fixture.exception); + } + + verifyBreadcrumb( + 'add', + fixture.getCreatedBreadcrumb(), + status: 'internal_error', + ); + }); + + test('throwing addAll adds error breadcrumb', () async { + when(fixture.mockBox.addAll(any)).thenThrow(fixture.exception); + + final sut = fixture.getSut(injectMockBox: true); + + try { + await sut.addAll([Person('Joe Dirt')]); + } catch (error) { + expect(error, fixture.exception); + } + + verifyBreadcrumb( + 'addAll', + fixture.getCreatedBreadcrumb(), + status: 'internal_error', + ); + }); + + test('throwing clear adds error breadcrumb', () async { + when(fixture.mockBox.clear()).thenThrow(fixture.exception); + + final sut = fixture.getSut(injectMockBox: true); + + try { + await sut.clear(); + } catch (error) { + expect(error, fixture.exception); + } + + verifyBreadcrumb( + 'clear', + fixture.getCreatedBreadcrumb(), + status: 'internal_error', + ); + }); + + test('throwing close adds error breadcrumb', () async { + when(fixture.mockBox.close()).thenThrow(fixture.exception); + + final sut = fixture.getSut(injectMockBox: true); + + try { + await sut.close(); + } catch (error) { + expect(error, fixture.exception); + } + + verifyBreadcrumb( + 'close', + fixture.getCreatedBreadcrumb(), + status: 'internal_error', + ); + }); + + test('throwing compact adds error breadcrumb', () async { + when(fixture.mockBox.compact()).thenThrow(fixture.exception); + + final sut = fixture.getSut(injectMockBox: true); + + try { + await sut.compact(); + } catch (error) { + expect(error, fixture.exception); + } + + verifyBreadcrumb( + 'compact', + fixture.getCreatedBreadcrumb(), + status: 'internal_error', + ); + }); + + test('throwing delete adds error breadcrumb', () async { + when(fixture.mockBox.delete(any)).thenThrow(fixture.exception); + + final sut = fixture.getSut(injectMockBox: true); + + try { + await sut.delete('fixture-key'); + } catch (error) { + expect(error, fixture.exception); + } + + verifyBreadcrumb( + 'delete', + fixture.getCreatedBreadcrumb(), + status: 'internal_error', + ); + }); + + test('throwing deleteAll adds error breadcrumb', () async { + when(fixture.mockBox.deleteAll(any)).thenThrow(fixture.exception); + + final sut = fixture.getSut(injectMockBox: true); + + try { + await sut.deleteAll(['fixture-key']); + } catch (error) { + expect(error, fixture.exception); + } + + verifyBreadcrumb( + 'deleteAll', + fixture.getCreatedBreadcrumb(), + status: 'internal_error', + ); + }); + + test('throwing deleteAt adds error breadcrumb', () async { + when(fixture.mockBox.add(any)).thenAnswer((_) async { + return 1; + }); + when(fixture.mockBox.deleteAt(any)).thenThrow(fixture.exception); + + final sut = fixture.getSut(injectMockBox: true); + + await sut.add(Person('Joe Dirt')); + try { + await sut.deleteAt(0); + } catch (error) { + expect(error, fixture.exception); + } + + verifyBreadcrumb( + 'deleteAt', + fixture.getCreatedBreadcrumb(), + status: 'internal_error', + ); + }); + }); } class Fixture { @@ -266,6 +533,7 @@ class Fixture { final _context = SentryTransactionContext('name', 'operation'); late final tracer = SentryTracer(_context, hub); + late final scope = Scope(options); Future setUp() async { Hive.init(Directory.systemTemp.path); @@ -294,4 +562,8 @@ class Fixture { SentrySpan? getCreatedSpan() { return tracer.children.last; } + + Breadcrumb? getCreatedBreadcrumb() { + return hub.scope.breadcrumbs.last; + } } diff --git a/hive/test/sentry_box_collection_test.dart b/hive/test/sentry_box_collection_test.dart index 4965896611..f13b95e1c8 100644 --- a/hive/test/sentry_box_collection_test.dart +++ b/hive/test/sentry_box_collection_test.dart @@ -42,6 +42,23 @@ void main() { expect(span?.throwable, exception); } + void verifyBreadcrumb( + String message, + Breadcrumb? crumb, { + bool checkName = false, + String status = 'ok', + }) { + expect( + crumb?.message, + message, + ); + expect(crumb?.type, 'query'); + if (checkName) { + expect(crumb?.data?[SentryHiveImpl.dbNameKey], Fixture.dbName); + } + expect(crumb?.data?['status'], status); + } + group('adds span when calling', () { late Fixture fixture; @@ -51,6 +68,7 @@ void main() { when(fixture.hub.options).thenReturn(fixture.options); when(fixture.hub.getSpan()).thenReturn(fixture.tracer); + when(fixture.hub.scope).thenReturn(fixture.scope); }); tearDown(() async { @@ -111,6 +129,7 @@ void main() { when(fixture.hub.options).thenReturn(fixture.options); when(fixture.hub.getSpan()).thenReturn(fixture.tracer); when(fixture.mockBoxCollection.name).thenReturn(Fixture.dbName); + when(fixture.hub.scope).thenReturn(fixture.scope); }); tearDown(() async { @@ -184,6 +203,155 @@ void main() { ); }); }); + + group('adds breadcrumb when calling', () { + late Fixture fixture; + + setUp(() async { + fixture = Fixture(); + await fixture.setUp(); + + when(fixture.hub.options).thenReturn(fixture.options); + when(fixture.hub.getSpan()).thenReturn(fixture.tracer); + when(fixture.hub.scope).thenReturn(fixture.scope); + }); + + tearDown(() async { + await fixture.tearDown(); + }); + + test('open', () async { + await SentryBoxCollection.open( + Fixture.dbName, + {'people'}, + hub: fixture.hub, + ); + + final span = fixture.getCreatedBreadcrumb(); + verifyBreadcrumb('open', span); + }); + + test('openBox', () async { + final sut = await fixture.getSut(); + + await sut.openBox('people'); + + final span = fixture.getCreatedBreadcrumb(); + verifyBreadcrumb('openBox', span); + }); + + test('transaction', () async { + final sut = await fixture.getSut(); + + final people = await sut.openBox('people'); + await sut.transaction( + () async { + print(people.name); + }, + boxNames: ['people'], + ); + final span = fixture.getCreatedBreadcrumb(); + verifyBreadcrumb('transaction', span); + }); + + test('deleteFromDisk', () async { + final sut = await fixture.getSut(); + + await sut.deleteFromDisk(); + + final span = fixture.getCreatedBreadcrumb(); + verifyBreadcrumb('deleteFromDisk', span); + }); + }); + + group('adds error breadcrumb when calling', () { + late Fixture fixture; + + setUp(() async { + fixture = Fixture(); + await fixture.setUp(); + + when(fixture.hub.options).thenReturn(fixture.options); + when(fixture.hub.getSpan()).thenReturn(fixture.tracer); + when(fixture.mockBoxCollection.name).thenReturn(Fixture.dbName); + when(fixture.hub.scope).thenReturn(fixture.scope); + }); + + tearDown(() async { + await fixture.tearDown(); + }); + + // open is static and cannot be mocked + + test('throwing openBox', () async { + when( + // ignore: inference_failure_on_function_invocation + fixture.mockBoxCollection.openBox( + any, + preload: anyNamed('preload'), + boxCreator: anyNamed('boxCreator'), + ), + ).thenThrow(fixture.exception); + + final sut = await fixture.getSut(injectMock: true); + + try { + // ignore: inference_failure_on_function_invocation + await sut.openBox('people'); + } catch (error) { + expect(error, fixture.exception); + } + + verifyBreadcrumb( + 'openBox', + fixture.getCreatedBreadcrumb(), + status: 'internal_error', + ); + }); + + test('throwing transaction', () async { + when( + fixture.mockBoxCollection.transaction( + any, + boxNames: anyNamed('boxNames'), + readOnly: anyNamed('readOnly'), + ), + ).thenThrow(fixture.exception); + + final sut = await fixture.getSut(injectMock: true); + + try { + await sut.transaction(() async {}); + } catch (error) { + expect(error, fixture.exception); + } + + verifyBreadcrumb( + 'transaction', + fixture.getCreatedBreadcrumb(), + status: 'internal_error', + ); + }); + + test('throwing deleteFromDisk', () async { + when(fixture.mockBoxCollection.deleteFromDisk()) + .thenThrow(fixture.exception); + + final sut = await fixture.getSut(injectMock: true); + + try { + await sut.deleteFromDisk(); + } catch (error) { + expect(error, fixture.exception); + } + + verifyBreadcrumb( + 'deleteFromDisk', + fixture.getCreatedBreadcrumb(), + status: 'internal_error', + ); + }); + }); } class Fixture { @@ -197,6 +365,7 @@ class Fixture { final _context = SentryTransactionContext('name', 'operation'); late final tracer = SentryTracer(_context, hub); + late final scope = Scope(options); Future setUp() async { SentryHive.init(Directory.systemTemp.path); @@ -222,4 +391,8 @@ class Fixture { SentrySpan? getCreatedSpan() { return tracer.children.last; } + + Breadcrumb? getCreatedBreadcrumb() { + return hub.scope.breadcrumbs.last; + } } diff --git a/hive/test/sentry_hive_impl_test.dart b/hive/test/sentry_hive_impl_test.dart index df5c8502f9..521415d1ed 100644 --- a/hive/test/sentry_hive_impl_test.dart +++ b/hive/test/sentry_hive_impl_test.dart @@ -41,6 +41,23 @@ void main() { expect(span?.throwable, error); } + void verifyBreadcrumb( + String message, + Breadcrumb? crumb, { + bool checkName = false, + String status = 'ok', + }) { + expect( + crumb?.message, + message, + ); + expect(crumb?.type, 'query'); + if (checkName) { + expect(crumb?.data?[SentryHiveImpl.dbNameKey], Fixture.dbName); + } + expect(crumb?.data?['status'], status); + } + group('adds span', () { late Fixture fixture; @@ -49,6 +66,7 @@ void main() { when(fixture.hub.options).thenReturn(fixture.options); when(fixture.hub.getSpan()).thenReturn(fixture.tracer); + when(fixture.hub.scope).thenReturn(fixture.scope); await fixture.setUp(); }); @@ -119,6 +137,7 @@ void main() { when(fixture.hub.options).thenReturn(fixture.options); when(fixture.hub.getSpan()).thenReturn(fixture.tracer); when(fixture.mockHive.close()).thenAnswer((_) async => {}); + when(fixture.hub.scope).thenReturn(fixture.scope); await fixture.setUp(injectMockHive: true); }); @@ -274,6 +293,259 @@ void main() { }); }); + group('adds breadcrumbs', () { + late Fixture fixture; + + setUp(() async { + fixture = Fixture(); + + when(fixture.hub.options).thenReturn(fixture.options); + when(fixture.hub.getSpan()).thenReturn(fixture.tracer); + when(fixture.hub.scope).thenReturn(fixture.scope); + + await fixture.setUp(); + }); + + tearDown(() async { + await fixture.tearDown(); + }); + + test('boxExists adds breadcrumb', () async { + final sut = fixture.getSut(); + + await sut.openBox(Fixture.dbName); + await sut.boxExists(Fixture.dbName); + + verifyBreadcrumb('boxExists', fixture.getCreatedBreadcrumb()); + }); + + test('close adds breadcrumb', () async { + final sut = fixture.getSut(); + + await sut.close(); + + verifyBreadcrumb('close', fixture.getCreatedBreadcrumb()); + }); + + test('deleteBoxFromDisk adds breadcrumb', () async { + final sut = fixture.getSut(); + + await sut.openBox(Fixture.dbName); + await sut.deleteBoxFromDisk(Fixture.dbName); + + verifyBreadcrumb('deleteBoxFromDisk', fixture.getCreatedBreadcrumb()); + }); + + test('deleteFromDisk adds breadcrumb', () async { + final sut = fixture.getSut(); + + await sut.deleteFromDisk(); + + verifyBreadcrumb('deleteFromDisk', fixture.getCreatedBreadcrumb()); + }); + + test('openBox adds breadcrumb', () async { + final sut = fixture.getSut(); + + await sut.openBox(Fixture.dbName); + + verifyBreadcrumb( + 'openBox', + fixture.getCreatedBreadcrumb(), + checkName: true, + ); + }); + + test('openLazyBox adds breadcrumb', () async { + final sut = fixture.getSut(); + + await sut.openLazyBox(Fixture.dbName); + + verifyBreadcrumb( + 'openLazyBox', + fixture.getCreatedBreadcrumb(), + checkName: true, + ); + }); + }); + + group('adds error breadcrumb', () { + late Fixture fixture; + + setUp(() async { + fixture = Fixture(); + + when(fixture.hub.options).thenReturn(fixture.options); + when(fixture.hub.getSpan()).thenReturn(fixture.tracer); + when(fixture.mockHive.close()).thenAnswer((_) async => {}); + when(fixture.hub.scope).thenReturn(fixture.scope); + + await fixture.setUp(injectMockHive: true); + }); + + test('throwing boxExists adds error span', () async { + final Box box = MockBox(); + when( + fixture.mockHive.openBox( + any, + encryptionCipher: anyNamed('encryptionCipher'), + keyComparator: anyNamed('keyComparator'), + compactionStrategy: anyNamed('compactionStrategy'), + crashRecovery: anyNamed('crashRecovery'), + path: anyNamed('path'), + bytes: anyNamed('bytes'), + collection: anyNamed('collection'), + encryptionKey: anyNamed('encryptionKey'), + ), + ).thenAnswer((_) => Future(() => box)); + when(fixture.mockHive.boxExists(any)).thenThrow(fixture.exception); + + final sut = fixture.getSut(); + + await sut.openBox(Fixture.dbName); + try { + await sut.boxExists(Fixture.dbName); + } catch (error) { + expect(error, fixture.exception); + } + + verifyBreadcrumb( + 'boxExists', + fixture.getCreatedBreadcrumb(), + status: 'internal_error', + ); + }); + + test('throwing close adds error span', () async { + when(fixture.mockHive.close()).thenThrow(fixture.exception); + + final sut = fixture.getSut(); + + try { + await sut.close(); + } catch (error) { + expect(error, fixture.exception); + } + + verifyBreadcrumb( + 'close', + fixture.getCreatedBreadcrumb(), + status: 'internal_error', + ); + }); + + test('throwing deleteBoxFromDisk adds error span', () async { + final Box box = MockBox(); + when( + fixture.mockHive.openBox( + any, + encryptionCipher: anyNamed('encryptionCipher'), + keyComparator: anyNamed('keyComparator'), + compactionStrategy: anyNamed('compactionStrategy'), + crashRecovery: anyNamed('crashRecovery'), + path: anyNamed('path'), + bytes: anyNamed('bytes'), + collection: anyNamed('collection'), + encryptionKey: anyNamed('encryptionKey'), + ), + ).thenAnswer((_) => Future(() => box)); + when(fixture.mockHive.deleteBoxFromDisk(any)) + .thenThrow(fixture.exception); + + final sut = fixture.getSut(); + + await sut.openBox(Fixture.dbName); + try { + await sut.deleteBoxFromDisk(Fixture.dbName); + } catch (error) { + expect(error, fixture.exception); + } + + verifyBreadcrumb( + 'deleteBoxFromDisk', + fixture.getCreatedBreadcrumb(), + status: 'internal_error', + ); + }); + + test('throwing deleteFromDisk adds error span', () async { + when(fixture.mockHive.deleteFromDisk()).thenThrow(fixture.exception); + + final sut = fixture.getSut(); + + try { + await sut.deleteFromDisk(); + } catch (error) { + expect(error, fixture.exception); + } + + verifyBreadcrumb( + 'deleteFromDisk', + fixture.getCreatedBreadcrumb(), + status: 'internal_error', + ); + }); + + test('throwing openBox adds error span', () async { + when( + fixture.mockHive.openBox( + any, + encryptionCipher: anyNamed('encryptionCipher'), + keyComparator: anyNamed('keyComparator'), + compactionStrategy: anyNamed('compactionStrategy'), + crashRecovery: anyNamed('crashRecovery'), + path: anyNamed('path'), + bytes: anyNamed('bytes'), + collection: anyNamed('collection'), + encryptionKey: anyNamed('encryptionKey'), + ), + ).thenThrow(fixture.exception); + + final sut = fixture.getSut(); + + try { + await sut.openBox(Fixture.dbName); + } catch (error) { + expect(error, fixture.exception); + } + + verifyBreadcrumb( + 'openBox', + fixture.getCreatedBreadcrumb(), + status: 'internal_error', + ); + }); + + test('throwing openLazyBox adds error span', () async { + when( + fixture.mockHive.openLazyBox( + any, + encryptionCipher: anyNamed('encryptionCipher'), + keyComparator: anyNamed('keyComparator'), + compactionStrategy: anyNamed('compactionStrategy'), + crashRecovery: anyNamed('crashRecovery'), + path: anyNamed('path'), + collection: anyNamed('collection'), + encryptionKey: anyNamed('encryptionKey'), + ), + ).thenThrow(fixture.exception); + + final sut = fixture.getSut(); + + try { + await sut.openLazyBox(Fixture.dbName); + } catch (error) { + expect(error, fixture.exception); + } + + verifyBreadcrumb( + 'openLazyBox', + fixture.getCreatedBreadcrumb(), + status: 'internal_error', + ); + }); + }); + group('integrations', () { late Fixture fixture; @@ -282,6 +554,7 @@ void main() { when(fixture.hub.options).thenReturn(fixture.options); when(fixture.hub.getSpan()).thenReturn(fixture.tracer); + when(fixture.hub.scope).thenReturn(fixture.scope); await fixture.setUp(); }); @@ -319,6 +592,7 @@ class Fixture { final _context = SentryTransactionContext('name', 'operation'); late final tracer = SentryTracer(_context, hub); late SentryHiveImpl sut; + late final scope = Scope(options); Future setUp({bool injectMockHive = false}) async { if (injectMockHive) { @@ -344,4 +618,8 @@ class Fixture { SentrySpan? getCreatedSpan() { return tracer.children.last; } + + Breadcrumb? getCreatedBreadcrumb() { + return hub.scope.breadcrumbs.last; + } } diff --git a/hive/test/sentry_lazy_box_test.dart b/hive/test/sentry_lazy_box_test.dart index 263658af8d..291dc3fc20 100644 --- a/hive/test/sentry_lazy_box_test.dart +++ b/hive/test/sentry_lazy_box_test.dart @@ -40,6 +40,23 @@ void main() { expect(span?.throwable, exception); } + void verifyBreadcrumb( + String message, + Breadcrumb? crumb, { + bool checkName = false, + String status = 'ok', + }) { + expect( + crumb?.message, + message, + ); + expect(crumb?.type, 'query'); + if (checkName) { + expect(crumb?.data?[SentryHiveImpl.dbNameKey], Fixture.dbName); + } + expect(crumb?.data?['status'], status); + } + group('adds span', () { late Fixture fixture; @@ -49,6 +66,7 @@ void main() { when(fixture.hub.options).thenReturn(fixture.options); when(fixture.hub.getSpan()).thenReturn(fixture.tracer); + when(fixture.hub.scope).thenReturn(fixture.scope); }); tearDown(() async { @@ -84,6 +102,7 @@ void main() { when(fixture.hub.options).thenReturn(fixture.options); when(fixture.hub.getSpan()).thenReturn(fixture.tracer); when(fixture.mockBox.name).thenReturn(Fixture.dbName); + when(fixture.hub.scope).thenReturn(fixture.scope); }); tearDown(() async { @@ -126,6 +145,103 @@ void main() { verifyErrorSpan('getAt', fixture.exception, fixture.getCreatedSpan()); }); }); + + group('adds breadcrumb', () { + late Fixture fixture; + + setUp(() async { + fixture = Fixture(); + await fixture.setUp(); + + when(fixture.hub.options).thenReturn(fixture.options); + when(fixture.hub.getSpan()).thenReturn(fixture.tracer); + when(fixture.hub.scope).thenReturn(fixture.scope); + }); + + tearDown(() async { + await fixture.tearDown(); + }); + + test('get adds breadcrumb', () async { + final sut = fixture.getSut(); + + await sut.put('fixture-key', Person('John Malkovich')); + await sut.get('fixture-key'); + + verifyBreadcrumb('get', fixture.getCreatedBreadcrumb()); + }); + + test('getAt adds breadcrumb', () async { + final sut = fixture.getSut(); + + await sut.add(Person('John Malkovich')); + await sut.getAt(0); + + verifyBreadcrumb('getAt', fixture.getCreatedBreadcrumb()); + }); + }); + + group('adds error breadcrumbs', () { + late Fixture fixture; + + setUp(() async { + fixture = Fixture(); + await fixture.setUp(); + + when(fixture.hub.options).thenReturn(fixture.options); + when(fixture.hub.getSpan()).thenReturn(fixture.tracer); + when(fixture.mockBox.name).thenReturn(Fixture.dbName); + when(fixture.hub.scope).thenReturn(fixture.scope); + }); + + tearDown(() async { + await fixture.tearDown(); + }); + + test('throwing get adds error breadcrumbs', () async { + when(fixture.mockBox.add(any)).thenAnswer((_) async { + return 1; + }); + when(fixture.mockBox.get(any)).thenThrow(fixture.exception); + + final sut = fixture.getSut(injectMockBox: true); + + await sut.put('fixture-key', Person('John Malkovich')); + try { + await sut.get('fixture-key'); + } catch (error) { + expect(error, fixture.exception); + } + + verifyBreadcrumb( + 'get', + fixture.getCreatedBreadcrumb(), + status: 'internal_error', + ); + }); + + test('throwing getAt adds error breadcrumbs', () async { + when(fixture.mockBox.add(any)).thenAnswer((_) async { + return 1; + }); + when(fixture.mockBox.getAt(any)).thenThrow(fixture.exception); + + final sut = fixture.getSut(injectMockBox: true); + + await sut.add(Person('John Malkovich')); + try { + await sut.getAt(0); + } catch (error) { + expect(error, fixture.exception); + } + + verifyBreadcrumb( + 'getAt', + fixture.getCreatedBreadcrumb(), + status: 'internal_error', + ); + }); + }); } class Fixture { @@ -139,6 +255,7 @@ class Fixture { final _context = SentryTransactionContext('name', 'operation'); late final tracer = SentryTracer(_context, hub); + late final scope = Scope(options); Future setUp() async { Hive.init(Directory.systemTemp.path); @@ -167,4 +284,8 @@ class Fixture { SentrySpan? getCreatedSpan() { return tracer.children.last; } + + Breadcrumb? getCreatedBreadcrumb() { + return hub.scope.breadcrumbs.last; + } } From 13446e11c3e3097518657339a8fe8f869c8b0e97 Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Mon, 11 Dec 2023 16:56:25 +0100 Subject: [PATCH 024/237] improvements(example): fix router navigation issue and add improvements (#1767) * Change http url and add route navigation observer example * Remove comment * Improve sample * Format * Add padding * Fix analyze issues --- flutter/example/lib/auto_close_screen.dart | 47 ++++ flutter/example/lib/main.dart | 277 ++++++++++++++------- 2 files changed, 232 insertions(+), 92 deletions(-) create mode 100644 flutter/example/lib/auto_close_screen.dart diff --git a/flutter/example/lib/auto_close_screen.dart b/flutter/example/lib/auto_close_screen.dart new file mode 100644 index 0000000000..15e8fac1fb --- /dev/null +++ b/flutter/example/lib/auto_close_screen.dart @@ -0,0 +1,47 @@ +import 'package:flutter/material.dart'; +import 'package:sentry/sentry.dart'; + +/// This screen is only used to demonstrate how route navigation works. +/// Init will create a child span and pop the screen after 3 seconds. +/// Afterwards the transaction should be seen on the performance page. +class AutoCloseScreen extends StatefulWidget { + const AutoCloseScreen({super.key}); + + @override + AutoCloseScreenState createState() => AutoCloseScreenState(); +} + +class AutoCloseScreenState extends State { + static const delayInSeconds = 3; + + @override + void initState() { + super.initState(); + _doComplexOperationThenClose(); + } + + Future _doComplexOperationThenClose() async { + final activeSpan = Sentry.getSpan(); + final childSpan = activeSpan?.startChild('complex operation', + description: 'running a $delayInSeconds seconds operation'); + await Future.delayed(const Duration(seconds: delayInSeconds)); + childSpan?.finish(); + // ignore: use_build_context_synchronously + Navigator.of(context).pop(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Delayed Screen'), + ), + body: const Center( + child: Text( + 'This screen will automatically close in $delayInSeconds seconds...', + textAlign: TextAlign.center, + ), + ), + ); + } +} diff --git a/flutter/example/lib/main.dart b/flutter/example/lib/main.dart index 8ff567b8cb..61c05ab741 100644 --- a/flutter/example/lib/main.dart +++ b/flutter/example/lib/main.dart @@ -18,6 +18,7 @@ import 'package:sqflite/sqflite.dart'; import 'package:universal_platform/universal_platform.dart'; import 'package:feedback/feedback.dart' as feedback; import 'package:provider/provider.dart'; +import 'auto_close_screen.dart'; import 'drift/database.dart'; import 'drift/connection/connection.dart'; import 'user_feedback_dialog.dart'; @@ -30,9 +31,14 @@ import 'package:sentry_hive/sentry_hive.dart'; const String exampleDsn = 'https://e85b375ffb9f43cf8bdf9787768149e0@o447951.ingest.sentry.io/5428562'; +/// This is an exampleUrl that will be used to demonstrate how http requests are captured. +const String exampleUrl = 'https://jsonplaceholder.typicode.com/todos/'; + const _channel = MethodChannel('example.flutter.sentry.io'); var _isIntegrationTest = false; +final GlobalKey navigatorKey = GlobalKey(); + Future main() async { await setupSentry( () => runApp( @@ -100,6 +106,7 @@ class _MyAppState extends State { create: (_) => ThemeProvider(), child: Builder( builder: (context) => MaterialApp( + navigatorKey: navigatorKey, navigatorObservers: [ SentryNavigatorObserver(), ], @@ -112,6 +119,30 @@ class _MyAppState extends State { } } +class TooltipButton extends StatelessWidget { + final String text; + final String buttonTitle; + final void Function()? onPressed; + + const TooltipButton( + {required this.onPressed, + required this.buttonTitle, + required this.text, + Key? key}) + : super(key: key); + + @override + Widget build(BuildContext context) { + return Tooltip( + message: text, + child: ElevatedButton( + onPressed: onPressed, + key: key, + child: Text(buttonTitle), + )); + } +} + class MainScaffold extends StatelessWidget { const MainScaffold({ Key? key, @@ -154,77 +185,115 @@ class MainScaffold extends StatelessWidget { child: Column( children: [ if (_isIntegrationTest) const IntegrationTestWidget(), - const Center(child: Text('Trigger an action:\n')), - // For simplicity sake we skip the web set up for now. + const Center(child: Text('Trigger an action.\n')), + const Padding( + padding: EdgeInsets.all(15), //apply padding to all four sides + child: Center( + child: Text( + 'Long press a button to see more information. (hover on web)')), + ), + TooltipButton( + onPressed: () => navigateToAutoCloseScreen(context), + text: + 'Pushes a screen and creates a transaction named \'AutoCloseScreen\' with a child span that finishes after 3 seconds. \nAfter the screen has popped the transaction can then be seen on the performance page.', + buttonTitle: 'Route Navigation Observer', + ), if (!UniversalPlatform.isWeb) - ElevatedButton( - onPressed: () => driftTest(), - child: const Text('drift'), + TooltipButton( + onPressed: driftTest, + text: + 'Executes CRUD operations on an in-memory with Drift and sends the created transaction to Sentry.', + buttonTitle: 'drift', ), - ElevatedButton( - onPressed: () => hiveTest(), - child: const Text('hive'), - ), - ElevatedButton( - onPressed: () => sqfliteTest(), - child: const Text('sqflite'), + if (!UniversalPlatform.isWeb) + TooltipButton( + onPressed: hiveTest, + text: + 'Executes CRUD operations on an in-memory with Hive and sends the created transaction to Sentry.', + buttonTitle: 'hive', + ), + TooltipButton( + onPressed: sqfliteTest, + text: + 'Executes CRUD operations on an in-memory with Hive and sends the created transaction to Sentry.', + buttonTitle: 'sqflite', ), - ElevatedButton( + TooltipButton( onPressed: () => SecondaryScaffold.openSecondaryScaffold(context), - child: const Text('Open another Scaffold'), + text: + 'Demonstrates how the router integration adds a navigation event to the breadcrumbs that can be seen when throwing an exception for example.', + buttonTitle: 'Open another Scaffold', ), - ElevatedButton( - onPressed: () => tryCatch(), - key: const Key('dart_try_catch'), - child: const Text('Dart: try catch'), + const TooltipButton( + onPressed: tryCatch, + key: Key('dart_try_catch'), + text: 'Creates a caught exception and sends it to Sentry.', + buttonTitle: 'Dart: try catch', ), - ElevatedButton( + TooltipButton( onPressed: () => Scaffold.of(context).showBottomSheet( (context) => const Text('Scaffold error'), ), - child: const Text('Flutter error : Scaffold.of()'), + text: + 'Creates an uncaught exception and sends it to Sentry. This demonstrates how our flutter error integration catches unhandled exceptions.', + buttonTitle: 'Flutter error : Scaffold.of()', ), - ElevatedButton( + TooltipButton( // Warning : not captured if a debugger is attached // https://github.com/flutter/flutter/issues/48972 onPressed: () => throw Exception('Throws onPressed'), - child: const Text('Dart: throw onPressed'), + text: + 'Creates an uncaught exception and sends it to Sentry. This demonstrates how our flutter error integration catches unhandled exceptions.', + buttonTitle: 'Dart: throw onPressed', ), - ElevatedButton( + TooltipButton( + // Warning : not captured if a debugger is attached + // https://github.com/flutter/flutter/issues/48972 onPressed: () { - // Only relevant in debug builds - // Warning : not captured if a debugger is attached - // https://github.com/flutter/flutter/issues/48972 assert(false, 'assert failure'); }, - child: const Text('Dart: assert'), + text: + 'Creates an uncaught exception and sends it to Sentry. This demonstrates how our flutter error integration catches unhandled exceptions.', + buttonTitle: 'Dart: assert', ), // Calling the SDK with an appRunner will handle errors from Futures // in SDKs runZonedGuarded onError handler - ElevatedButton( + TooltipButton( onPressed: () async => asyncThrows(), - child: const Text('Dart: async throws'), + text: + 'Creates an async uncaught exception and sends it to Sentry. This demonstrates how our flutter error integration catches unhandled exceptions.', + buttonTitle: 'Dart: async throws', ), - ElevatedButton( + TooltipButton( onPressed: () async => { await Future.microtask( () => throw StateError('Failure in a microtask'), ) }, - child: const Text('Dart: Fail in microtask.'), + text: + 'Creates an uncaught exception in a microtask and sends it to Sentry. This demonstrates how our flutter error integration catches unhandled exceptions.', + buttonTitle: 'Dart: Fail in microtask', ), - ElevatedButton( - onPressed: () async => {await compute(loop, 10)}, - child: const Text('Dart: Fail in compute'), + TooltipButton( + onPressed: () async => { + await compute(loop, 10), + }, + text: + 'Creates an uncaught exception in a compute isolate and sends it to Sentry. This demonstrates how our flutter error integration catches unhandled exceptions.', + buttonTitle: 'Dart: Fail in compute', ), - ElevatedButton( - onPressed: () => Future.delayed( - const Duration(milliseconds: 100), - () => throw Exception('Throws in Future.delayed'), - ), - child: const Text('Throws in Future.delayed'), + TooltipButton( + onPressed: () async => { + await Future.delayed( + const Duration(milliseconds: 100), + () => throw StateError('Failure in a Future.delayed'), + ), + }, + text: + 'Creates an uncaught exception in a Future.delayed and sends it to Sentry. This demonstrates how our flutter error integration catches unhandled exceptions.', + buttonTitle: 'Throws in Future.delayed', ), - ElevatedButton( + TooltipButton( onPressed: () { // modeled after a real exception FlutterError.onError?.call(FlutterErrorDetails( @@ -242,9 +311,11 @@ class MainScaffold extends StatelessWidget { ], )); }, - child: const Text('Capture from FlutterError.onError'), + text: + 'Creates a FlutterError and passes it to FlutterError.onError callback. This demonstrates how our flutter error integration catches unhandled exceptions.', + buttonTitle: 'Capture from FlutterError.onError', ), - ElevatedButton( + TooltipButton( onPressed: () { // Only usable on Flutter >= 3.3 // and needs the following additional setup: @@ -256,41 +327,41 @@ class MainScaffold extends StatelessWidget { StackTrace.current, ); }, - child: const Text('Capture from PlatformDispatcher.onError'), + text: + 'This is only usable on Flutter >= 3.3 and requires additional setup: options.addIntegration(OnErrorIntegration());', + buttonTitle: 'Capture from PlatformDispatcher.onError', ), - ElevatedButton( - key: const Key('view hierarchy'), - onPressed: () => {}, - child: const Visibility( - visible: true, - child: Opacity( - opacity: 0.5, - child: Text('view hierarchy'), - ), - ), - ), - ElevatedButton( + TooltipButton( onPressed: () => makeWebRequest(context), - child: const Text('Dart: Web request'), - ), - ElevatedButton( - onPressed: () => showDialogWithTextAndImage(context), - child: const Text('Flutter: Load assets'), + text: + 'Attaches web request related spans to the transaction and send it to Sentry.', + buttonTitle: 'Dart: Web request', ), - ElevatedButton( + TooltipButton( + onPressed: () => makeWebRequestWithDio(context), key: const Key('dio_web_request'), - onPressed: () async => await makeWebRequestWithDio(context), - child: const Text('Dio: Web request'), + text: + 'Attaches web request related spans to the transaction and send it to Sentry.', + buttonTitle: 'Dio: Web request', ), - ElevatedButton( + + TooltipButton( + onPressed: () => showDialogWithTextAndImage(context), + text: + 'Attaches asset bundle related spans to the transaction and send it to Sentry.', + buttonTitle: 'Flutter: Load assets', + ), + TooltipButton( onPressed: () { // ignore: avoid_print print('A print breadcrumb'); Sentry.captureMessage('A message with a print() Breadcrumb'); }, - child: const Text('Record print() as breadcrumb'), + text: + 'Sends a captureMessage to Sentry with a breadcrumb created by a print() statement.', + buttonTitle: 'Record print() as breadcrumb', ), - ElevatedButton( + TooltipButton( onPressed: () { Sentry.captureMessage( 'This event has an extra tag', @@ -299,10 +370,11 @@ class MainScaffold extends StatelessWidget { }, ); }, - child: - const Text('Capture message with scope with additional tag'), + text: + 'Sends the capture message event with additional Tag to Sentry.', + buttonTitle: 'Capture message with scope with additional tag', ), - ElevatedButton( + TooltipButton( onPressed: () async { final transaction = Sentry.getSpan() ?? Sentry.startTransaction( @@ -347,9 +419,11 @@ class MainScaffold extends StatelessWidget { // findPrimeNumber(1000000); // Uncomment to see it with profiling await transaction.finish(status: const SpanStatus.ok()); }, - child: const Text('Capture transaction'), + text: + 'Creates a custom transaction, adds child spans and send them to Sentry.', + buttonTitle: 'Capture transaction', ), - ElevatedButton( + TooltipButton( onPressed: () { Sentry.captureMessage( 'This message has an attachment', @@ -365,9 +439,10 @@ class MainScaffold extends StatelessWidget { }, ); }, - child: const Text('Capture message with attachment'), + text: 'Sends the capture message with an attachment to Sentry.', + buttonTitle: 'Capture message with attachment', ), - ElevatedButton( + TooltipButton( onPressed: () { feedback.BetterFeedback.of(context) .show((feedback.UserFeedback feedback) { @@ -391,9 +466,11 @@ class MainScaffold extends StatelessWidget { ); }); }, - child: const Text('Capture message with image attachment'), + text: + 'Sends the capture message with an image attachment to Sentry.', + buttonTitle: 'Capture message with image attachment', ), - ElevatedButton( + TooltipButton( onPressed: () async { final id = await Sentry.captureMessage('UserFeedback'); // ignore: use_build_context_synchronously @@ -409,9 +486,11 @@ class MainScaffold extends StatelessWidget { }, ); }, - child: const Text('Capture User Feedback'), + text: + 'Shows a custom user feedback dialog without an ongoing event that captures and sends user feedback data to Sentry.', + buttonTitle: 'Capture User Feedback', ), - ElevatedButton( + TooltipButton( onPressed: () async { await showDialog( context: context, @@ -420,19 +499,31 @@ class MainScaffold extends StatelessWidget { }, ); }, - child: const Text('Show UserFeedback Dialog without event'), + text: '', + buttonTitle: 'Show UserFeedback Dialog without event', ), - ElevatedButton( + TooltipButton( onPressed: () { final log = Logger('Logging'); log.info('My Logging test'); }, - child: const Text('Logging'), + text: + 'Demonstrates the logging integration. log.info() will create an info event send it to Sentry.', + buttonTitle: 'Logging', ), if (UniversalPlatform.isIOS || UniversalPlatform.isMacOS) const CocoaExample(), if (UniversalPlatform.isAndroid) const AndroidExample(), - ], + ].map((widget) { + if (kIsWeb) { + // Add vertical padding to web so the tooltip doesn't obstruct the clicking of the button below. + return Padding( + padding: const EdgeInsets.only(top: 18.0, bottom: 18.0), + child: widget, + ); + } + return widget; + }).toList(), ), ), ); @@ -596,6 +687,16 @@ class AndroidExample extends StatelessWidget { } } +void navigateToAutoCloseScreen(BuildContext context) { + Navigator.push( + context, + MaterialPageRoute( + settings: const RouteSettings(name: 'AutoCloseScreen'), + builder: (context) => const AutoCloseScreen(), + ), + ); +} + Future tryCatch() async { try { throw StateError('try catch'); @@ -769,7 +870,7 @@ Future makeWebRequest(BuildContext context) async { ); // We don't do any exception handling here. // In case of an exception, let it get caught and reported to Sentry - final response = await client.get(Uri.parse('https://flutter.dev/')); + final response = await client.get(Uri.parse(exampleUrl)); await transaction.finish(status: const SpanStatus.ok()); @@ -781,10 +882,6 @@ Future makeWebRequest(BuildContext context) async { // ignore: use_build_context_synchronously await showDialog( context: context, - // gets tracked if using SentryNavigatorObserver - routeSettings: const RouteSettings( - name: 'flutter.dev dialog', - ), builder: (context) { return AlertDialog( title: Text('Response ${response.statusCode}'), @@ -818,7 +915,7 @@ Future makeWebRequestWithDio(BuildContext context) async { ); Response? response; try { - response = await dio.get('https://flutter.dev/'); + response = await dio.get(exampleUrl); span.status = const SpanStatus.ok(); } catch (exception, stackTrace) { span.throwable = exception; @@ -836,10 +933,6 @@ Future makeWebRequestWithDio(BuildContext context) async { // ignore: use_build_context_synchronously await showDialog( context: context, - // gets tracked if using SentryNavigatorObserver - routeSettings: const RouteSettings( - name: 'flutter.dev dialog', - ), builder: (context) { return AlertDialog( title: Text('Response ${response?.statusCode}'), From d5f600b89be5270826f3de928015fdf5a59a9229 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Dec 2023 16:57:14 +0100 Subject: [PATCH 025/237] build(deps): bump actions/setup-java from 3 to 4 (#1772) Bumps [actions/setup-java](https://github.com/actions/setup-java) from 3 to 4. - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/setup-java dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/drift.yml | 2 +- .github/workflows/flutter.yml | 2 +- .github/workflows/flutter_test.yml | 2 +- .github/workflows/metrics.yml | 2 +- .github/workflows/min_version_test.yml | 2 +- .github/workflows/sqflite.yml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/drift.yml b/.github/workflows/drift.yml index 2cf22e8bbd..cc4da1177e 100644 --- a/.github/workflows/drift.yml +++ b/.github/workflows/drift.yml @@ -64,7 +64,7 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: actions/setup-java@v3 + - uses: actions/setup-java@v4 if: ${{ matrix.target == 'android' }} with: java-version: "11" diff --git a/.github/workflows/flutter.yml b/.github/workflows/flutter.yml index df20a20efd..7b7a4c8f27 100644 --- a/.github/workflows/flutter.yml +++ b/.github/workflows/flutter.yml @@ -69,7 +69,7 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: actions/setup-java@v3 + - uses: actions/setup-java@v4 if: ${{ matrix.target == 'android' }} with: java-version: "11" diff --git a/.github/workflows/flutter_test.yml b/.github/workflows/flutter_test.yml index 6a1806189f..3b9e2e3839 100644 --- a/.github/workflows/flutter_test.yml +++ b/.github/workflows/flutter_test.yml @@ -35,7 +35,7 @@ jobs: - name: checkout uses: actions/checkout@v4 - - uses: actions/setup-java@v3 + - uses: actions/setup-java@v4 with: distribution: "adopt" java-version: "11" diff --git a/.github/workflows/metrics.yml b/.github/workflows/metrics.yml index 5e461d86eb..c190889723 100644 --- a/.github/workflows/metrics.yml +++ b/.github/workflows/metrics.yml @@ -57,7 +57,7 @@ jobs: with: flutter-version: ${{ steps.conf.outputs.flutter }} - - uses: actions/setup-java@v3 + - uses: actions/setup-java@v4 if: ${{ matrix.platform == 'android' }} with: java-version: "11" diff --git a/.github/workflows/min_version_test.yml b/.github/workflows/min_version_test.yml index b9116cdc52..c40c015b16 100644 --- a/.github/workflows/min_version_test.yml +++ b/.github/workflows/min_version_test.yml @@ -28,7 +28,7 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: actions/setup-java@v3 + - uses: actions/setup-java@v4 with: distribution: "adopt" java-version: "11" diff --git a/.github/workflows/sqflite.yml b/.github/workflows/sqflite.yml index 41ab13aba5..7943eb0e92 100644 --- a/.github/workflows/sqflite.yml +++ b/.github/workflows/sqflite.yml @@ -65,7 +65,7 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: actions/setup-java@v3 + - uses: actions/setup-java@v4 if: ${{ matrix.target == 'android' }} with: java-version: "11" From 13c328da2656f30424e80497ae54e90bef1f15f5 Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Tue, 12 Dec 2023 11:34:55 +0100 Subject: [PATCH 026/237] docs: add new package release process (#1734) * add docs * Add flutter example step * Add analyze info * Update * Update new-package-release-checklist.md --- docs/new-package-release-checklist.md | 57 +++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 docs/new-package-release-checklist.md diff --git a/docs/new-package-release-checklist.md b/docs/new-package-release-checklist.md new file mode 100644 index 0000000000..0a7cd19821 --- /dev/null +++ b/docs/new-package-release-checklist.md @@ -0,0 +1,57 @@ +# New Package Release Checklist + +This page serves as a checklist of what to do when releasing a new package for the first time. + +## Release Preparation + +- [ ] Make sure the project is set up + - [ ] The package only exports the public API + - [ ] The package contains an example folder + - [ ] The package contains a README.md file + - [ ] CI badges show a status + - [ ] The package contains a CHANGELOG.md file (symlink to the root changelog) + - [ ] The package contains a dartdoc_options.yaml file (symlink to the root file) + - [ ] The package contains a LICENSE (default is `MIT`) + - [ ] The package contains a pubspec.yaml file + - [ ] The package contains a analysis_options.yaml file + +- [ ] Update the [Flutter example](https://github.com/getsentry/sentry-dart/tree/main/flutter/example) to use your new package if applicable + +- [ ] Make sure your new package has a `version.dart` in the `lib/src` folder. + - This is used to set the version and package in the `Hub`. See this [example](https://github.com/getsentry/sentry-dart/blob/8609bd8dd7ea572e5d241a59643c7570e5621bda/sqflite/lib/src/sentry_database.dart#L69). + - The version will be updated to the newest version after triggering the release process. + +- [ ] Create a new workflow called `your-package-name.yml` for building and testing the package. + +- [ ] Excluding `your-package-name.yml`, add the package to the `paths-ignore` section of all package workflow files. + - For examples see `sqflite.yml`, `dio.yml` etc... + +- [ ] Add an entry to [diagram.yml](https://github.com/getsentry/sentry-dart/blob/main/.github/workflows/diagrams.yml) for your package. + +- [ ] In the root `.gitignore` file add the package coverage as ignored. + +The `analyze` workflow will fail in your PR and in the main branch because the package is not released yet and the `pubspec.yaml` is not 'valid' according to the analyzer. +This is expected - it will succeed after the release. +- [ ] Make sure the analyze workflow doesn't have other failures, only the one mentioned above. + +- [ ] **Very important**: add your package to `scripts/bump-version.sh`. + +## Doing the Release + +Do these steps in the **correct order** + +- [ ] Add your package only as a `pub-dev` target in `.craft.yml`. (**not registry**) + - The release process might fail if you add it to the registry at this point. +- [ ] Trigger the release + - [ ] Check that the release bot successfully updated the versions in `version.dart` and `pubspec.yaml` in the release branch. + +## After the first release + +- [ ] Check if package is succesfully released on `pub.dev` +- [ ] Add the package to the Sentry Release Registry + - Instructions on how to do this can be found [here](https://github.com/getsentry/sentry-release-registry#adding-new-sdks) + - [Example PR](https://github.com/getsentry/sentry-release-registry/pull/136) +- [ ] Add an entry to `.craft.yml` for the package in the `registry` section. + - Now all future releases will be added to the registry automatically. +- [ ] Update the repo's `README.md` +- [ ] Prepare and merge [Sentry documentation](https://github.com/getsentry/sentry-docs/) From 9d7e8623dbcfd7498c1cf1bcf5ba4c8b3e99a860 Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Wed, 13 Dec 2023 17:46:43 +0100 Subject: [PATCH 027/237] fix(ci): compile error in example using flutter beta channel (#1783) * fix ci --- flutter/example/lib/main.dart | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/flutter/example/lib/main.dart b/flutter/example/lib/main.dart index 61c05ab741..4e39b96db2 100644 --- a/flutter/example/lib/main.dart +++ b/flutter/example/lib/main.dart @@ -231,9 +231,8 @@ class MainScaffold extends StatelessWidget { buttonTitle: 'Dart: try catch', ), TooltipButton( - onPressed: () => Scaffold.of(context).showBottomSheet( - (context) => const Text('Scaffold error'), - ), + onPressed: () => Scaffold.of(context) + .showBottomSheet((context) => const Text('Scaffold error')), text: 'Creates an uncaught exception and sends it to Sentry. This demonstrates how our flutter error integration catches unhandled exceptions.', buttonTitle: 'Flutter error : Scaffold.of()', From e5c91717e6bb377edb3b3c59e93f301db3d477e4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 18 Dec 2023 11:34:51 +0100 Subject: [PATCH 028/237] chore(deps): update Cocoa SDK to v8.17.2 (#1787) * chore: update flutter/scripts/update-cocoa.sh to 8.17.2 --------- Co-authored-by: GitHub Co-authored-by: GIancarlo Buenaflor --- CHANGELOG.md | 6 +++--- flutter/ios/sentry_flutter.podspec | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c983f6680..e476635366 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,9 +14,9 @@ ### Dependencies -- Bump Cocoa SDK from v8.15.2 to v8.17.1 ([#1761](https://github.com/getsentry/sentry-dart/pull/1761), [#1771](https://github.com/getsentry/sentry-dart/pull/1771)) - - [changelog](https://github.com/getsentry/sentry-cocoa/blob/main/CHANGELOG.md#8171) - - [diff](https://github.com/getsentry/sentry-cocoa/compare/8.15.2...8.17.1) +- Bump Cocoa SDK from v8.15.2 to v8.17.2 ([#1761](https://github.com/getsentry/sentry-dart/pull/1761), [#1771](https://github.com/getsentry/sentry-dart/pull/1771), [#1787](https://github.com/getsentry/sentry-dart/pull/1787)) + - [changelog](https://github.com/getsentry/sentry-cocoa/blob/main/CHANGELOG.md#8172) + - [diff](https://github.com/getsentry/sentry-cocoa/compare/8.15.2...8.17.2) ## 7.13.2 diff --git a/flutter/ios/sentry_flutter.podspec b/flutter/ios/sentry_flutter.podspec index 9a9f6265a6..15edfce6d7 100644 --- a/flutter/ios/sentry_flutter.podspec +++ b/flutter/ios/sentry_flutter.podspec @@ -12,7 +12,7 @@ Sentry SDK for Flutter with support to native through sentry-cocoa. :tag => s.version.to_s } s.source_files = 'Classes/**/*' s.public_header_files = 'Classes/**/*.h' - s.dependency 'Sentry/HybridSDK', '8.17.1' + s.dependency 'Sentry/HybridSDK', '8.17.2' s.ios.dependency 'Flutter' s.osx.dependency 'FlutterMacOS' s.ios.deployment_target = '11.0' From 4b29d6e00433309052c4edd19c448fb33dd371f5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 18 Dec 2023 11:44:56 +0100 Subject: [PATCH 029/237] chore: update flutter/scripts/update-android.sh to 7.0.0 (#1768) Co-authored-by: GitHub Co-authored-by: Giancarlo Buenaflor --- CHANGELOG.md | 3 +++ flutter/android/build.gradle | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e476635366..079380af7d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,9 @@ ### Dependencies +- Bump Android SDK from v6.34.0 to v7.0.0 ([#1768](https://github.com/getsentry/sentry-dart/pull/1768)) + - [changelog](https://github.com/getsentry/sentry-java/blob/main/CHANGELOG.md#700) + - [diff](https://github.com/getsentry/sentry-java/compare/6.34.0...7.0.0) - Bump Cocoa SDK from v8.15.2 to v8.17.2 ([#1761](https://github.com/getsentry/sentry-dart/pull/1761), [#1771](https://github.com/getsentry/sentry-dart/pull/1771), [#1787](https://github.com/getsentry/sentry-dart/pull/1787)) - [changelog](https://github.com/getsentry/sentry-cocoa/blob/main/CHANGELOG.md#8172) - [diff](https://github.com/getsentry/sentry-cocoa/compare/8.15.2...8.17.2) diff --git a/flutter/android/build.gradle b/flutter/android/build.gradle index 9e956927c8..859103b80f 100644 --- a/flutter/android/build.gradle +++ b/flutter/android/build.gradle @@ -60,7 +60,7 @@ android { } dependencies { - api 'io.sentry:sentry-android:6.34.0' + api 'io.sentry:sentry-android:7.0.0' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" // Required -- JUnit 4 framework From d914f354fa8ff3e5d0b78a8fe958a11420a81f66 Mon Sep 17 00:00:00 2001 From: getsentry-bot Date: Mon, 18 Dec 2023 13:49:22 +0000 Subject: [PATCH 030/237] release: 7.14.0 --- CHANGELOG.md | 2 +- dart/lib/src/version.dart | 2 +- dart/pubspec.yaml | 2 +- dio/lib/src/version.dart | 2 +- dio/pubspec.yaml | 4 ++-- drift/lib/src/version.dart | 2 +- drift/pubspec.yaml | 4 ++-- file/lib/src/version.dart | 2 +- file/pubspec.yaml | 4 ++-- flutter/example/pubspec.yaml | 2 +- flutter/lib/src/version.dart | 2 +- flutter/pubspec.yaml | 4 ++-- hive/lib/src/version.dart | 2 +- hive/pubspec.yaml | 4 ++-- logging/lib/src/version.dart | 2 +- logging/pubspec.yaml | 4 ++-- sqflite/lib/src/version.dart | 2 +- sqflite/pubspec.yaml | 4 ++-- 18 files changed, 25 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 079380af7d..cc89efe310 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## Unreleased +## 7.14.0 ### Fixes diff --git a/dart/lib/src/version.dart b/dart/lib/src/version.dart index 3f3c44b449..dc38fd3e11 100644 --- a/dart/lib/src/version.dart +++ b/dart/lib/src/version.dart @@ -9,7 +9,7 @@ library version; /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.13.2'; +const String sdkVersion = '7.14.0'; String sdkName(bool isWeb) => isWeb ? _browserSdkName : _ioSdkName; diff --git a/dart/pubspec.yaml b/dart/pubspec.yaml index e2e2a7c1c6..e3207ffda2 100644 --- a/dart/pubspec.yaml +++ b/dart/pubspec.yaml @@ -1,5 +1,5 @@ name: sentry -version: 7.13.2 +version: 7.14.0 description: > A crash reporting library for Dart that sends crash reports to Sentry.io. This library supports Dart VM and Web. For Flutter consider sentry_flutter instead. diff --git a/dio/lib/src/version.dart b/dio/lib/src/version.dart index 2e88298a45..9737ee6520 100644 --- a/dio/lib/src/version.dart +++ b/dio/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.13.2'; +const String sdkVersion = '7.14.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_dio'; diff --git a/dio/pubspec.yaml b/dio/pubspec.yaml index b8c55a1147..92e57a96a9 100644 --- a/dio/pubspec.yaml +++ b/dio/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_dio description: An integration which adds support for performance tracing for the Dio package. -version: 7.13.2 +version: 7.14.0 homepage: https://docs.sentry.io/platforms/dart/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -11,7 +11,7 @@ environment: dependencies: dio: ^5.0.0 - sentry: 7.13.2 + sentry: 7.14.0 dev_dependencies: meta: ^1.3.0 diff --git a/drift/lib/src/version.dart b/drift/lib/src/version.dart index 5fe2e65abd..621ab96e95 100644 --- a/drift/lib/src/version.dart +++ b/drift/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.13.2'; +const String sdkVersion = '7.14.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_drift'; diff --git a/drift/pubspec.yaml b/drift/pubspec.yaml index 7d871c6156..df6380ba9d 100644 --- a/drift/pubspec.yaml +++ b/drift/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_drift description: An integration which adds support for performance tracing for the drift package. -version: 7.13.2 +version: 7.14.0 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -10,7 +10,7 @@ environment: flutter: '>=3.3.0' dependencies: - sentry: 7.13.2 + sentry: 7.14.0 meta: ^1.3.0 drift: ^2.13.0 diff --git a/file/lib/src/version.dart b/file/lib/src/version.dart index a979700d5a..6900c8de5d 100644 --- a/file/lib/src/version.dart +++ b/file/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.13.2'; +const String sdkVersion = '7.14.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_file'; diff --git a/file/pubspec.yaml b/file/pubspec.yaml index fe9d2fe916..273124df8f 100644 --- a/file/pubspec.yaml +++ b/file/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_file description: An integration which adds support for performance tracing for dart.io.File. -version: 7.13.2 +version: 7.14.0 homepage: https://docs.sentry.io/platforms/dart/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -10,7 +10,7 @@ environment: sdk: '>=2.19.0 <4.0.0' dependencies: - sentry: 7.13.2 + sentry: 7.14.0 meta: ^1.3.0 dev_dependencies: diff --git a/flutter/example/pubspec.yaml b/flutter/example/pubspec.yaml index fc09a3776e..cdbbbd0e0d 100644 --- a/flutter/example/pubspec.yaml +++ b/flutter/example/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_flutter_example description: Demonstrates how to use the sentry_flutter plugin. -version: 7.13.2 +version: 7.14.0 publish_to: 'none' # Remove this line if you wish to publish to pub.dev diff --git a/flutter/lib/src/version.dart b/flutter/lib/src/version.dart index 598160e5d9..ff71dd6e87 100644 --- a/flutter/lib/src/version.dart +++ b/flutter/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.13.2'; +const String sdkVersion = '7.14.0'; /// The default SDK name reported to Sentry.io in the submitted events. const String sdkName = 'sentry.dart.flutter'; diff --git a/flutter/pubspec.yaml b/flutter/pubspec.yaml index 5c4d529917..0e321ab82f 100644 --- a/flutter/pubspec.yaml +++ b/flutter/pubspec.yaml @@ -1,5 +1,5 @@ name: sentry_flutter -version: 7.13.2 +version: 7.14.0 description: Sentry SDK for Flutter. This package aims to support different Flutter targets by relying on the many platforms supported by Sentry with native SDKs. homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart @@ -15,7 +15,7 @@ dependencies: sdk: flutter flutter_web_plugins: sdk: flutter - sentry: 7.13.2 + sentry: 7.14.0 package_info_plus: '>=1.0.0 <=5.0.1' meta: ^1.3.0 ffi: ^2.0.0 diff --git a/hive/lib/src/version.dart b/hive/lib/src/version.dart index 080ff8f0f2..08b6cbe335 100644 --- a/hive/lib/src/version.dart +++ b/hive/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.13.2'; +const String sdkVersion = '7.14.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_hive'; diff --git a/hive/pubspec.yaml b/hive/pubspec.yaml index a89e369324..1bdad09235 100644 --- a/hive/pubspec.yaml +++ b/hive/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_hive description: An integration which adds support for performance tracing for the hive package. -version: 7.13.2 +version: 7.14.0 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -9,7 +9,7 @@ environment: sdk: '>=2.17.0 <4.0.0' dependencies: - sentry: 7.13.2 + sentry: 7.14.0 hive: ^2.2.3 meta: ^1.3.0 diff --git a/logging/lib/src/version.dart b/logging/lib/src/version.dart index 70c5b7d597..b1e21478f7 100644 --- a/logging/lib/src/version.dart +++ b/logging/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.13.2'; +const String sdkVersion = '7.14.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_logging'; diff --git a/logging/pubspec.yaml b/logging/pubspec.yaml index 4b6145bc85..02cef6966a 100644 --- a/logging/pubspec.yaml +++ b/logging/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_logging description: An integration which adds support for recording log from the logging package. -version: 7.13.2 +version: 7.14.0 homepage: https://docs.sentry.io/platforms/dart/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -11,7 +11,7 @@ environment: dependencies: logging: ^1.0.0 - sentry: 7.13.2 + sentry: 7.14.0 dev_dependencies: lints: ^3.0.0 diff --git a/sqflite/lib/src/version.dart b/sqflite/lib/src/version.dart index 3df0f707c4..9c361f297d 100644 --- a/sqflite/lib/src/version.dart +++ b/sqflite/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.13.2'; +const String sdkVersion = '7.14.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_sqflite'; diff --git a/sqflite/pubspec.yaml b/sqflite/pubspec.yaml index 653adbe3de..22188a8d91 100644 --- a/sqflite/pubspec.yaml +++ b/sqflite/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_sqflite description: An integration which adds support for performance tracing for the sqflite package. -version: 7.13.2 +version: 7.14.0 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -10,7 +10,7 @@ environment: flutter: '>=3.3.0' # matching sqflite dependencies: - sentry: 7.13.2 + sentry: 7.14.0 sqflite: ^2.0.0 sqflite_common: ^2.0.0 meta: ^1.3.0 From 117d988b347861588d574fcc789ecbb4f7c8bdb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20Andra=C5=A1ec?= Date: Mon, 18 Dec 2023 15:01:52 +0000 Subject: [PATCH 031/237] Add `ConnectivityIntegration` for web (#1765) --- CHANGELOG.md | 2 + .../connectivity_integration.dart | 36 ++++++++++ .../connectivity/connectivity_provider.dart | 9 +++ .../noop_connectivity_provider.dart | 17 +++++ .../web_connectivity_provider.dart | 32 +++++++++ flutter/lib/src/sentry_flutter.dart | 5 ++ .../connectivity_integration_test.dart | 56 +++++++++++++++ flutter/test/sentry_flutter_options_test.dart | 2 +- flutter/test/sentry_flutter_test.dart | 71 +++++++++++++------ 9 files changed, 206 insertions(+), 24 deletions(-) create mode 100644 flutter/lib/src/integrations/connectivity/connectivity_integration.dart create mode 100644 flutter/lib/src/integrations/connectivity/connectivity_provider.dart create mode 100644 flutter/lib/src/integrations/connectivity/noop_connectivity_provider.dart create mode 100644 flutter/lib/src/integrations/connectivity/web_connectivity_provider.dart create mode 100644 flutter/test/integrations/connectivity_integration_test.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index cc89efe310..8818d3b035 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,8 @@ - Add option to opt out of fatal level for automatically collected errors ([#1738](https://github.com/getsentry/sentry-dart/pull/1738)) - Add `Hive` breadcrumbs ([#1773](https://github.com/getsentry/sentry-dart/pull/1773)) +- Add `ConnectivityIntegration` for web ([#1765](https://github.com/getsentry/sentry-dart/pull/1765)) + - We only get the info if online/offline on web platform. The added breadcrumb is set to either `wifi` or `none`. ### Dependencies diff --git a/flutter/lib/src/integrations/connectivity/connectivity_integration.dart b/flutter/lib/src/integrations/connectivity/connectivity_integration.dart new file mode 100644 index 0000000000..c8d0b80c86 --- /dev/null +++ b/flutter/lib/src/integrations/connectivity/connectivity_integration.dart @@ -0,0 +1,36 @@ +import 'package:meta/meta.dart'; +import '../../../sentry_flutter.dart'; +import 'connectivity_provider.dart'; + +class ConnectivityIntegration extends Integration { + Hub? _hub; + ConnectivityProvider? _connectivityProvider; + + @override + void call(Hub hub, SentryFlutterOptions options) { + _hub = hub; + _connectivityProvider = ConnectivityProvider(); + _connectivityProvider?.listen((connectivity) { + addBreadcrumb(connectivity); + }); + options.sdk.addIntegration('connectivityIntegration'); + } + + @override + void close() { + _hub = null; + _connectivityProvider?.cancel(); + } + + @internal + @visibleForTesting + void addBreadcrumb(String connectivity) { + _hub?.addBreadcrumb( + Breadcrumb( + category: 'device.connectivity', + level: SentryLevel.info, + type: 'connectivity', + data: {'connectivity': connectivity}), + ); + } +} diff --git a/flutter/lib/src/integrations/connectivity/connectivity_provider.dart b/flutter/lib/src/integrations/connectivity/connectivity_provider.dart new file mode 100644 index 0000000000..30095dda0d --- /dev/null +++ b/flutter/lib/src/integrations/connectivity/connectivity_provider.dart @@ -0,0 +1,9 @@ +import 'noop_connectivity_provider.dart' + if (dart.library.html) 'web_connectivity_provider.dart'; + +abstract class ConnectivityProvider { + factory ConnectivityProvider() => connectivityProvider(); + + void listen(void Function(String connectivity) onChange); + void cancel(); +} diff --git a/flutter/lib/src/integrations/connectivity/noop_connectivity_provider.dart b/flutter/lib/src/integrations/connectivity/noop_connectivity_provider.dart new file mode 100644 index 0000000000..4276448b7a --- /dev/null +++ b/flutter/lib/src/integrations/connectivity/noop_connectivity_provider.dart @@ -0,0 +1,17 @@ +import 'connectivity_provider.dart'; + +ConnectivityProvider connectivityProvider() { + return NoOpConnectivityProvider(); +} + +class NoOpConnectivityProvider implements ConnectivityProvider { + @override + void listen(void Function(String connectivity) onChange) { + // NoOp + } + + @override + void cancel() { + // NoOp + } +} diff --git a/flutter/lib/src/integrations/connectivity/web_connectivity_provider.dart b/flutter/lib/src/integrations/connectivity/web_connectivity_provider.dart new file mode 100644 index 0000000000..34d0e0ab42 --- /dev/null +++ b/flutter/lib/src/integrations/connectivity/web_connectivity_provider.dart @@ -0,0 +1,32 @@ +import 'dart:async'; +import 'dart:html' as html; + +import 'connectivity_provider.dart'; + +ConnectivityProvider connectivityProvider() { + return WebConnectivityProvider(); +} + +class WebConnectivityProvider implements ConnectivityProvider { + StreamSubscription? _onOnlineSub; + StreamSubscription? _onOfflineSub; + + @override + void listen(void Function(String connectivity) onChange) { + _onOnlineSub = html.window.onOnline.listen((_) { + onChange('wifi'); + }); + _onOfflineSub = html.window.onOffline.listen((_) { + onChange('none'); + }); + } + + @override + void cancel() { + _onOnlineSub?.cancel(); + _onOnlineSub = null; + + _onOfflineSub?.cancel(); + _onOfflineSub = null; + } +} diff --git a/flutter/lib/src/sentry_flutter.dart b/flutter/lib/src/sentry_flutter.dart index cef52ee564..62a9043bc9 100644 --- a/flutter/lib/src/sentry_flutter.dart +++ b/flutter/lib/src/sentry_flutter.dart @@ -9,6 +9,7 @@ import '../sentry_flutter.dart'; import 'event_processor/android_platform_exception_event_processor.dart'; import 'event_processor/flutter_exception_event_processor.dart'; import 'event_processor/platform_exception_event_processor.dart'; +import 'integrations/connectivity/connectivity_integration.dart'; import 'integrations/screenshot_integration.dart'; import 'native/factory.dart'; import 'native/native_scope_observer.dart'; @@ -171,6 +172,10 @@ mixin SentryFlutter { integrations.add(ScreenshotIntegration()); } + if (platformChecker.isWeb) { + integrations.add(ConnectivityIntegration()); + } + // works with Skia, CanvasKit and HTML renderer integrations.add(SentryViewHierarchyIntegration()); diff --git a/flutter/test/integrations/connectivity_integration_test.dart b/flutter/test/integrations/connectivity_integration_test.dart new file mode 100644 index 0000000000..2f0781e9ec --- /dev/null +++ b/flutter/test/integrations/connectivity_integration_test.dart @@ -0,0 +1,56 @@ +import 'package:flutter/widgets.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mockito/mockito.dart'; +import 'package:sentry/sentry.dart'; +import 'package:sentry_flutter/src/integrations/connectivity/connectivity_integration.dart'; +import 'package:sentry_flutter/src/sentry_flutter_options.dart'; + +import '../mocks.dart'; +import '../mocks.mocks.dart'; + +void main() { + WidgetsFlutterBinding.ensureInitialized(); + + late Fixture fixture; + + setUp(() { + fixture = Fixture(); + }); + + verifyBreadcrumb(Breadcrumb crumb, String connectivityData) { + expect(crumb.category, 'device.connectivity'); + expect(crumb.type, 'connectivity'); + expect(crumb.level, SentryLevel.info); + expect(crumb.data?['connectivity'], connectivityData); + } + + test('adds integration', () { + final sut = fixture.getSut(); + sut(fixture.hub, fixture.options); + + expect(fixture.options.sdk.integrations.contains('connectivityIntegration'), + true); + }); + + test('$ConnectivityIntegration: addsBreadcrumb', () { + final integration = fixture.getSut(); + integration.call(fixture.hub, fixture.options); + + integration.addBreadcrumb('wifi'); + + final crumb = verify( + fixture.hub.addBreadcrumb(captureAny), + ).captured.first as Breadcrumb; + + verifyBreadcrumb(crumb, 'wifi'); + }); +} + +class Fixture { + final hub = MockHub(); + final options = SentryFlutterOptions(dsn: fakeDsn); + + ConnectivityIntegration getSut() { + return ConnectivityIntegration(); + } +} diff --git a/flutter/test/sentry_flutter_options_test.dart b/flutter/test/sentry_flutter_options_test.dart index a6d871318b..ed4a3ea7f7 100644 --- a/flutter/test/sentry_flutter_options_test.dart +++ b/flutter/test/sentry_flutter_options_test.dart @@ -32,7 +32,7 @@ void main() { expect(options.enableAutoNativeBreadcrumbs, isFalse); }); - testWidgets('useFlutterBreadcrumbTracking', (WidgetTester tester) async { + testWidgets('useNativeBreadcrumbTracking', (WidgetTester tester) async { final options = SentryFlutterOptions(); options.useNativeBreadcrumbTracking(); diff --git a/flutter/test/sentry_flutter_test.dart b/flutter/test/sentry_flutter_test.dart index 87e4f46e84..f01c9a8d3f 100644 --- a/flutter/test/sentry_flutter_test.dart +++ b/flutter/test/sentry_flutter_test.dart @@ -3,6 +3,7 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; +import 'package:sentry_flutter/src/integrations/connectivity/connectivity_integration.dart'; import 'package:sentry_flutter/src/integrations/integrations.dart'; import 'package:sentry_flutter/src/integrations/screenshot_integration.dart'; import 'package:sentry_flutter/src/profiling.dart'; @@ -23,6 +24,10 @@ final platformAgnosticIntegrations = [ SentryViewHierarchyIntegration, ]; +final webIntegrations = [ + ConnectivityIntegration, +]; + final nonWebIntegrations = [ OnErrorIntegration, ]; @@ -81,14 +86,18 @@ void main() { options: sentryFlutterOptions!, expectedHasNativeScopeObserver: true); testConfiguration( - integrations: integrations, - shouldHaveIntegrations: [ - ...androidIntegrations, - ...nativeIntegrations, - ...platformAgnosticIntegrations, - ...nonWebIntegrations, - ], - shouldNotHaveIntegrations: iOsAndMacOsIntegrations); + integrations: integrations, + shouldHaveIntegrations: [ + ...androidIntegrations, + ...nativeIntegrations, + ...platformAgnosticIntegrations, + ...nonWebIntegrations, + ], + shouldNotHaveIntegrations: [ + ...iOsAndMacOsIntegrations, + ...nonWebIntegrations, + ], + ); integrations .indexWhere((element) => element is WidgetsFlutterBindingIntegration); @@ -138,7 +147,10 @@ void main() { ...platformAgnosticIntegrations, ...nonWebIntegrations, ], - shouldNotHaveIntegrations: androidIntegrations, + shouldNotHaveIntegrations: [ + ...androidIntegrations, + ...nonWebIntegrations, + ], ); testBefore( @@ -179,16 +191,15 @@ void main() { testScopeObserver( options: sentryFlutterOptions!, expectedHasNativeScopeObserver: true); - testConfiguration( - integrations: integrations, - shouldHaveIntegrations: [ - ...iOsAndMacOsIntegrations, - ...nativeIntegrations, - ...platformAgnosticIntegrations, - ...nonWebIntegrations, - ], - shouldNotHaveIntegrations: androidIntegrations, - ); + testConfiguration(integrations: integrations, shouldHaveIntegrations: [ + ...iOsAndMacOsIntegrations, + ...nativeIntegrations, + ...platformAgnosticIntegrations, + ...nonWebIntegrations, + ], shouldNotHaveIntegrations: [ + ...androidIntegrations, + ...nonWebIntegrations, + ]); testBefore( integrations: integrations, @@ -239,6 +250,7 @@ void main() { ...androidIntegrations, ...iOsAndMacOsIntegrations, ...nativeIntegrations, + ...webIntegrations, ], ); @@ -290,6 +302,7 @@ void main() { ...androidIntegrations, ...iOsAndMacOsIntegrations, ...nativeIntegrations, + ...webIntegrations, ], ); @@ -336,7 +349,10 @@ void main() { testConfiguration( integrations: integrations, - shouldHaveIntegrations: platformAgnosticIntegrations, + shouldHaveIntegrations: [ + ...platformAgnosticIntegrations, + ...webIntegrations, + ], shouldNotHaveIntegrations: [ ...androidIntegrations, ...iOsAndMacOsIntegrations, @@ -383,7 +399,10 @@ void main() { testConfiguration( integrations: integrations, - shouldHaveIntegrations: platformAgnosticIntegrations, + shouldHaveIntegrations: [ + ...platformAgnosticIntegrations, + ...webIntegrations, + ], shouldNotHaveIntegrations: [ ...androidIntegrations, ...iOsAndMacOsIntegrations, @@ -427,7 +446,10 @@ void main() { testConfiguration( integrations: integrations, - shouldHaveIntegrations: platformAgnosticIntegrations, + shouldHaveIntegrations: [ + ...platformAgnosticIntegrations, + ...webIntegrations, + ], shouldNotHaveIntegrations: [ ...androidIntegrations, ...iOsAndMacOsIntegrations, @@ -472,7 +494,10 @@ void main() { testConfiguration( integrations: integrations, - shouldHaveIntegrations: platformAgnosticIntegrations, + shouldHaveIntegrations: [ + ...platformAgnosticIntegrations, + ...webIntegrations, + ], shouldNotHaveIntegrations: [ ...androidIntegrations, ...iOsAndMacOsIntegrations, From f27dcdfb4152e5f61f1fdbb80def7a7e07ce5583 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20Andra=C5=A1ec?= Date: Mon, 18 Dec 2023 16:33:06 +0000 Subject: [PATCH 032/237] Fix changelog (#1791) --- CHANGELOG.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8818d3b035..facd194bf6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## Unreleased + +### Features + +- Add `ConnectivityIntegration` for web ([#1765](https://github.com/getsentry/sentry-dart/pull/1765)) + - We only get the info if online/offline on web platform. The added breadcrumb is set to either `wifi` or `none`. + ## 7.14.0 ### Fixes @@ -11,8 +18,6 @@ - Add option to opt out of fatal level for automatically collected errors ([#1738](https://github.com/getsentry/sentry-dart/pull/1738)) - Add `Hive` breadcrumbs ([#1773](https://github.com/getsentry/sentry-dart/pull/1773)) -- Add `ConnectivityIntegration` for web ([#1765](https://github.com/getsentry/sentry-dart/pull/1765)) - - We only get the info if online/offline on web platform. The added breadcrumb is set to either `wifi` or `none`. ### Dependencies From f649a83206e0638da84b3f21e38132a20a4f7c2e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 19 Dec 2023 09:18:29 +0100 Subject: [PATCH 033/237] build(deps): bump actions/upload-artifact from 3 to 4 (#1789) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 3 to 4. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/flutter-symbols.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/flutter-symbols.yml b/.github/workflows/flutter-symbols.yml index fba63c6cac..cf4af7c71c 100644 --- a/.github/workflows/flutter-symbols.yml +++ b/.github/workflows/flutter-symbols.yml @@ -51,7 +51,7 @@ jobs: GITHUB_TOKEN: ${{ github.token }} - name: Upload updated status cache of processed files - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: always() with: name: flutter-symbol-collector-database From f275487b349060e5e84df5d00e3c98d0b8a7cc68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20Andra=C5=A1ec?= Date: Tue, 19 Dec 2023 12:35:58 +0000 Subject: [PATCH 034/237] APM for isar (#1726) --- .craft.yml | 2 + .github/workflows/dart.yml | 1 + .github/workflows/diagrams.yml | 4 + .github/workflows/dio.yml | 1 + .github/workflows/drift.yml | 2 + .github/workflows/e2e_dart.yml | 1 + .github/workflows/file.yml | 1 + .github/workflows/flutter.yml | 1 + .github/workflows/hive.yml | 2 + .github/workflows/isar.yml | 116 ++ .github/workflows/logging.yml | 1 + .github/workflows/min_version_test.yml | 1 + .github/workflows/sqflite.yml | 1 + .gitignore | 1 + CHANGELOG.md | 3 + README.md | 3 +- dart/lib/src/sentry_trace_origins.dart | 2 + flutter/example/lib/isar/user.dart | 12 + flutter/example/lib/isar/user.g.dart | 553 ++++++++ flutter/example/lib/main.dart | 45 +- flutter/example/pubspec.yaml | 3 + flutter/example/pubspec_overrides.yaml | 2 + isar/.gitignore | 17 + isar/.metadata | 10 + isar/CHANGELOG.md | 1 + isar/LICENSE | 21 + isar/README.md | 83 ++ isar/analysis_options.yaml | 33 + isar/dartdoc_options.yaml | 1 + isar/example/main.dart | 47 + isar/example/user.dart | 12 + isar/example/user.g.dart | 553 ++++++++ isar/lib/sentry_isar.dart | 4 + isar/lib/src/sentry_isar.dart | 253 ++++ isar/lib/src/sentry_isar_collection.dart | 433 +++++++ isar/lib/src/sentry_span_helper.dart | 65 + isar/lib/src/version.dart | 5 + isar/pubspec.yaml | 28 + isar/pubspec_overrides.yaml | 3 + isar/test/mocks/mocks.dart | 10 + isar/test/mocks/mocks.mocks.dart | 1340 ++++++++++++++++++++ isar/test/person.dart | 11 + isar/test/person.g.dart | 518 ++++++++ isar/test/sentry_isar_collection_test.dart | 476 +++++++ isar/test/sentry_isar_test.dart | 277 ++++ scripts/bump-version.sh | 2 +- 46 files changed, 4954 insertions(+), 7 deletions(-) create mode 100644 .github/workflows/isar.yml create mode 100644 flutter/example/lib/isar/user.dart create mode 100644 flutter/example/lib/isar/user.g.dart create mode 100644 isar/.gitignore create mode 100644 isar/.metadata create mode 120000 isar/CHANGELOG.md create mode 100644 isar/LICENSE create mode 100644 isar/README.md create mode 100644 isar/analysis_options.yaml create mode 120000 isar/dartdoc_options.yaml create mode 100644 isar/example/main.dart create mode 100644 isar/example/user.dart create mode 100644 isar/example/user.g.dart create mode 100644 isar/lib/sentry_isar.dart create mode 100644 isar/lib/src/sentry_isar.dart create mode 100644 isar/lib/src/sentry_isar_collection.dart create mode 100644 isar/lib/src/sentry_span_helper.dart create mode 100644 isar/lib/src/version.dart create mode 100644 isar/pubspec.yaml create mode 100644 isar/pubspec_overrides.yaml create mode 100644 isar/test/mocks/mocks.dart create mode 100644 isar/test/mocks/mocks.mocks.dart create mode 100644 isar/test/person.dart create mode 100644 isar/test/person.g.dart create mode 100644 isar/test/sentry_isar_collection_test.dart create mode 100644 isar/test/sentry_isar_test.dart diff --git a/.craft.yml b/.craft.yml index 04d1af925d..45554efb25 100644 --- a/.craft.yml +++ b/.craft.yml @@ -24,3 +24,5 @@ targets: pub:sentry_sqflite: pub:sentry_drift: pub:sentry_hive: + # Initial release on pub.dev needed first before uncommenting + # pub:sentry_isar: diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml index 5f61c73903..3d6e4229fd 100644 --- a/.github/workflows/dart.yml +++ b/.github/workflows/dart.yml @@ -13,6 +13,7 @@ on: - "sqflite/**" - "hive/**" - "drift/**" + - "isar/**" jobs: cancel-previous-workflow: diff --git a/.github/workflows/diagrams.yml b/.github/workflows/diagrams.yml index b4f403b78c..a534112e8b 100644 --- a/.github/workflows/diagrams.yml +++ b/.github/workflows/diagrams.yml @@ -47,6 +47,10 @@ jobs: working-directory: ./hive run: lakos . -i "{test/**,example/**}" | dot -Tsvg -o class-diagram.svg + - name: isar + working-directory: ./isar + run: lakos . -i "{test/**,example/**}" | dot -Tsvg -o class-diagram.svg + # Source: https://stackoverflow.com/a/58035262 - name: Extract branch name shell: bash diff --git a/.github/workflows/dio.yml b/.github/workflows/dio.yml index 064c175698..ec7a54eedc 100644 --- a/.github/workflows/dio.yml +++ b/.github/workflows/dio.yml @@ -13,6 +13,7 @@ on: - "sqflite/**" - "hive/**" - "drift/**" + - "isar/**" jobs: cancel-previous-workflow: diff --git a/.github/workflows/drift.yml b/.github/workflows/drift.yml index cc4da1177e..b5e2c630aa 100644 --- a/.github/workflows/drift.yml +++ b/.github/workflows/drift.yml @@ -12,6 +12,8 @@ on: - "dio/**" - "file/**" - "sqflite/**" + - "hive/**" + - "isar/**" jobs: cancel-previous-workflow: diff --git a/.github/workflows/e2e_dart.yml b/.github/workflows/e2e_dart.yml index 9deb9a3eaf..730d015d8e 100644 --- a/.github/workflows/e2e_dart.yml +++ b/.github/workflows/e2e_dart.yml @@ -14,6 +14,7 @@ on: - "sqflite/**" - "hive/**" - "drift/**" + - "isar/**" env: SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} diff --git a/.github/workflows/file.yml b/.github/workflows/file.yml index 7fed334c62..56e3750fc9 100644 --- a/.github/workflows/file.yml +++ b/.github/workflows/file.yml @@ -13,6 +13,7 @@ on: - "sqflite/**" - "hive/**" - "drift/**" + - "isar/**" jobs: cancel-previous-workflow: diff --git a/.github/workflows/flutter.yml b/.github/workflows/flutter.yml index 7b7a4c8f27..77e02e4fc7 100644 --- a/.github/workflows/flutter.yml +++ b/.github/workflows/flutter.yml @@ -13,6 +13,7 @@ on: - "sqflite/**" - "hive/**" - "drift/**" + - "isar/**" jobs: cancel-previous-workflow: diff --git a/.github/workflows/hive.yml b/.github/workflows/hive.yml index 582f4e36ac..4e710d19fa 100644 --- a/.github/workflows/hive.yml +++ b/.github/workflows/hive.yml @@ -12,6 +12,8 @@ on: - "dio/**" - "file/**" - "sqflite/**" + - "drift/**" + - "isar/**" jobs: cancel-previous-workflow: diff --git a/.github/workflows/isar.yml b/.github/workflows/isar.yml new file mode 100644 index 0000000000..2484fa56bf --- /dev/null +++ b/.github/workflows/isar.yml @@ -0,0 +1,116 @@ +name: sentry-isar +on: + push: + branches: + - main + - release/** + pull_request: + paths-ignore: + - "**/*.md" + - "logging/**" + - "flutter/**" + - "dio/**" + - "file/**" + - "sqflite/**" + - "hive/**" + - "drift/**" + +jobs: + cancel-previous-workflow: + runs-on: ubuntu-latest + steps: + - name: Cancel Previous Runs + uses: styfle/cancel-workflow-action@01ce38bf961b4e243a6342cbade0dbc8ba3f0432 # pin@0.12.0 + with: + access_token: ${{ github.token }} + + build: + name: ${{ matrix.target }} | ${{ matrix.os }} | ${{ matrix.sdk }} + runs-on: ${{ matrix.os }} + timeout-minutes: 30 + defaults: + run: + shell: bash + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + target: ["ios", "android", "macos", "linux", "windows"] + sdk: ["stable", "beta"] + exclude: + - os: ubuntu-latest + target: ios + - os: ubuntu-latest + target: macos + - os: ubuntu-latest + target: windows + - os: windows-latest + target: ios + - os: windows-latest + target: android + - os: windows-latest + target: macos + - os: windows-latest + target: linux + # macos-latest is taking hours due to limited resources + - os: macos-latest + target: android + - os: macos-latest + target: linux + - os: macos-latest + target: windows + # Bad CPU type in executable + - os: macos-latest + sdk: beta + + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-java@v3 + if: ${{ matrix.target == 'android' }} + with: + java-version: "11" + distribution: "adopt" + + # Install required dependencies for Flutter on Linux on Ubuntu + - name: "Setup Linux" + run: | + sudo apt update + sudo apt install -y cmake dbus libblkid-dev libgtk-3-dev liblzma-dev ninja-build pkg-config xvfb + sudo apt install -y network-manager upower + if: matrix.os == 'ubuntu-latest' && matrix.target == 'linux' + + - uses: subosito/flutter-action@48cafc24713cca54bbe03cdc3a423187d413aafa # pin@v2.10.0 + with: + channel: ${{ matrix.sdk }} + + - run: flutter upgrade + + - name: Pub Get + run: | + cd isar + flutter pub get + + - name: Test VM with coverage + run: | + cd isar + flutter test -j 1 --coverage --test-randomize-ordering-seed=random + + - uses: codecov/codecov-action@eaaf4bedf32dbdc6b720b63067d99c4d77d6047d # pin@v3 + if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' + with: + name: sentry_isar + file: ./isar/coverage/lcov.info + functionalities: "search" # remove after https://github.com/codecov/codecov-action/issues/600 + + - uses: VeryGoodOpenSource/very_good_coverage@e5c91bc7ce9843e87c800b3bcafdfb86fbe28491 # pin@v2.1.0 + if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' + with: + path: "./isar/coverage/lcov.info" + min_coverage: 55 + + analyze: + uses: ./.github/workflows/analyze.yml + with: + package: isar + sdk: flutter diff --git a/.github/workflows/logging.yml b/.github/workflows/logging.yml index b489d1be86..d4b6d9898c 100644 --- a/.github/workflows/logging.yml +++ b/.github/workflows/logging.yml @@ -13,6 +13,7 @@ on: - "sqflite/**" - "hive/**" - "drift/**" + - "isar/**" jobs: cancel-previous-workflow: diff --git a/.github/workflows/min_version_test.yml b/.github/workflows/min_version_test.yml index c40c015b16..3d227a1447 100644 --- a/.github/workflows/min_version_test.yml +++ b/.github/workflows/min_version_test.yml @@ -11,6 +11,7 @@ on: - "sqflite/**" - "hive/**" - "drift/**" + - "isar/**" jobs: cancel-previous-workflow: diff --git a/.github/workflows/sqflite.yml b/.github/workflows/sqflite.yml index 7943eb0e92..48bcf380b2 100644 --- a/.github/workflows/sqflite.yml +++ b/.github/workflows/sqflite.yml @@ -13,6 +13,7 @@ on: - "file/**" - "hive/**" - "drift/**" + - "isar/**" jobs: cancel-previous-workflow: diff --git a/.gitignore b/.gitignore index 60bf635a0c..1f40d0ebb1 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,7 @@ flutter/coverage/* sqflite/coverage/* drift/coverage/* hive/coverage/* +isar/coverage/* pubspec.lock Podfile.lock diff --git a/CHANGELOG.md b/CHANGELOG.md index facd194bf6..d9051b9e07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,9 +6,12 @@ - Add `ConnectivityIntegration` for web ([#1765](https://github.com/getsentry/sentry-dart/pull/1765)) - We only get the info if online/offline on web platform. The added breadcrumb is set to either `wifi` or `none`. +- APM for isar ([#1726](https://github.com/getsentry/sentry-dart/pull/1726)) ## 7.14.0 +- Add option to opt out of fatal level for automatically collected errors ([#1738](https://github.com/getsentry/sentry-dart/pull/1738)) + ### Fixes - Add debug_meta to all events ([#1756](https://github.com/getsentry/sentry-dart/pull/1756)) diff --git a/README.md b/README.md index 1a6d03bc41..6159941c4c 100644 --- a/README.md +++ b/README.md @@ -24,10 +24,11 @@ Sentry SDK for Dart and Flutter | sentry_sqflite | [![build](https://github.com/getsentry/sentry-dart/workflows/sentry-sqflite/badge.svg?branch=main)](https://github.com/getsentry/sentry-dart/actions?query=workflow%3Asentry-sqflite) | [![pub package](https://img.shields.io/pub/v/sentry_sqflite.svg)](https://pub.dev/packages/sentry_sqflite) | [![likes](https://img.shields.io/pub/likes/sentry_sqflite)](https://pub.dev/packages/sentry_sqflite/score) | [![popularity](https://img.shields.io/pub/popularity/sentry_sqflite)](https://pub.dev/packages/sentry_sqflite/score) | [![pub points](https://img.shields.io/pub/points/sentry_sqflite)](https://pub.dev/packages/sentry_sqflite/score) | sentry_drift | [![build](https://github.com/getsentry/sentry-dart/actions/workflows/drift.yml/badge.svg?branch=main)](https://github.com/getsentry/sentry-dart/actions?query=workflow%3Asentry-drift) | [![pub package](https://img.shields.io/pub/v/sentry_drift.svg)](https://pub.dev/packages/sentry_drift) | [![likes](https://img.shields.io/pub/likes/sentry_drift)](https://pub.dev/packages/sentry_drift/score) | [![popularity](https://img.shields.io/pub/popularity/sentry_drift)](https://pub.dev/packages/sentry_drift/score) | [![pub points](https://img.shields.io/pub/points/sentry_drift)](https://pub.dev/packages/sentry_drift/score) | sentry_hive | [![build](https://github.com/getsentry/sentry-dart/actions/workflows/hive.yml/badge.svg?branch=main)](https://github.com/getsentry/sentry-dart/actions?query=workflow%3Asentry-hive) | [![pub package](https://img.shields.io/pub/v/sentry_hive.svg)](https://pub.dev/packages/sentry_hive) | [![likes](https://img.shields.io/pub/likes/sentry_hive)](https://pub.dev/packages/sentry_hive/score) | [![popularity](https://img.shields.io/pub/popularity/sentry_hive)](https://pub.dev/packages/sentry_hive/score) | [![pub points](https://img.shields.io/pub/points/sentry_hive)](https://pub.dev/packages/sentry_hive/score) +| sentry_isar | [![build](https://github.com/getsentry/sentry-dart/actions/workflows/isar.yml/badge.svg?branch=main)](https://github.com/getsentry/sentry-dart/actions?query=workflow%3Asentry-isar) | [![pub package](https://img.shields.io/pub/v/sentry_isar.svg)](https://pub.dev/packages/sentry_isar) | [![likes](https://img.shields.io/pub/likes/sentry_isar)](https://pub.dev/packages/sentry_isar/score) | [![popularity](https://img.shields.io/pub/popularity/sentry_isar)](https://pub.dev/packages/sentry_isar/score) | [![pub points](https://img.shields.io/pub/points/sentry_isar)](https://pub.dev/packages/sentry_isar/score) ##### Usage -For detailed usage, check out the inner [dart](https://github.com/getsentry/sentry-dart/tree/main/dart), [flutter](https://github.com/getsentry/sentry-dart/tree/main/flutter), [logging](https://github.com/getsentry/sentry-dart/tree/main/logging), [dio](https://github.com/getsentry/sentry-dart/tree/main/dio), [file](https://github.com/getsentry/sentry-dart/tree/main/file), [sqflite](https://github.com/getsentry/sentry-dart/tree/main/sqflite), [drift](https://github.com/getsentry/sentry-dart/tree/main/drift) and [hive](https://github.com/getsentry/sentry-dart/tree/main/hive) `README's` or our `Resources` section below. +For detailed usage, check out the inner [dart](https://github.com/getsentry/sentry-dart/tree/main/dart), [flutter](https://github.com/getsentry/sentry-dart/tree/main/flutter), [logging](https://github.com/getsentry/sentry-dart/tree/main/logging), [dio](https://github.com/getsentry/sentry-dart/tree/main/dio), [file](https://github.com/getsentry/sentry-dart/tree/main/file), [sqflite](https://github.com/getsentry/sentry-dart/tree/main/sqflite), [drift](https://github.com/getsentry/sentry-dart/tree/main/drift), [hive](https://github.com/getsentry/sentry-dart/tree/main/hive) and [isar](https://github.com/getsentry/sentry-dart/tree/main/isar) `README's` or our `Resources` section below. #### Blog posts diff --git a/dart/lib/src/sentry_trace_origins.dart b/dart/lib/src/sentry_trace_origins.dart index 903348aa19..5a7c49b339 100644 --- a/dart/lib/src/sentry_trace_origins.dart +++ b/dart/lib/src/sentry_trace_origins.dart @@ -18,6 +18,8 @@ class SentryTraceOrigins { 'auto.db.sqflite.database_executor'; static const autoDbSqfliteDatabaseFactory = 'auto.db.sqflite.database_factory'; + static const autoDbIsar = 'auto.db.isar'; + static const autoDbIsarCollection = 'auto.db.isar.collection'; static const autoDbHive = 'auto.db.hive'; static const autoDbHiveBoxBase = 'auto.db.hive.box_base'; static const autoDbHiveLazyBox = 'auto.db.hive.lazy_box'; diff --git a/flutter/example/lib/isar/user.dart b/flutter/example/lib/isar/user.dart new file mode 100644 index 0000000000..f255d2389d --- /dev/null +++ b/flutter/example/lib/isar/user.dart @@ -0,0 +1,12 @@ +import 'package:isar/isar.dart'; + +part 'user.g.dart'; + +@collection +class User { + Id id = Isar.autoIncrement; + + String? name; + + int? age; +} diff --git a/flutter/example/lib/isar/user.g.dart b/flutter/example/lib/isar/user.g.dart new file mode 100644 index 0000000000..c4d7ef985f --- /dev/null +++ b/flutter/example/lib/isar/user.g.dart @@ -0,0 +1,553 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'user.dart'; + +// ************************************************************************** +// IsarCollectionGenerator +// ************************************************************************** + +// coverage:ignore-file +// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types + +extension GetUserCollection on Isar { + IsarCollection get users => this.collection(); +} + +final UserSchema = CollectionSchema( + name: r'User', + id: BigInt.parse("-7838171048429979076").toInt(), + properties: { + r'age': PropertySchema( + id: BigInt.parse("0").toInt(), + name: r'age', + type: IsarType.long, + ), + r'name': PropertySchema( + id: BigInt.parse("1").toInt(), + name: r'name', + type: IsarType.string, + ) + }, + estimateSize: _userEstimateSize, + serialize: _userSerialize, + deserialize: _userDeserialize, + deserializeProp: _userDeserializeProp, + idName: r'id', + indexes: {}, + links: {}, + embeddedSchemas: {}, + getId: _userGetId, + getLinks: _userGetLinks, + attach: _userAttach, + version: '3.1.0', +); + +int _userEstimateSize( + User object, + List offsets, + Map> allOffsets, +) { + var bytesCount = offsets.last; + { + final value = object.name; + if (value != null) { + bytesCount += 3 + value.length * 3; + } + } + return bytesCount; +} + +void _userSerialize( + User object, + IsarWriter writer, + List offsets, + Map> allOffsets, +) { + writer.writeLong(offsets[0], object.age); + writer.writeString(offsets[1], object.name); +} + +User _userDeserialize( + Id id, + IsarReader reader, + List offsets, + Map> allOffsets, +) { + final object = User(); + object.age = reader.readLongOrNull(offsets[0]); + object.id = id; + object.name = reader.readStringOrNull(offsets[1]); + return object; +} + +P _userDeserializeProp

( + IsarReader reader, + int propertyId, + int offset, + Map> allOffsets, +) { + switch (propertyId) { + case 0: + return (reader.readLongOrNull(offset)) as P; + case 1: + return (reader.readStringOrNull(offset)) as P; + default: + throw IsarError('Unknown property with id $propertyId'); + } +} + +Id _userGetId(User object) { + return object.id; +} + +List> _userGetLinks(User object) { + return []; +} + +void _userAttach(IsarCollection col, Id id, User object) { + object.id = id; +} + +extension UserQueryWhereSort on QueryBuilder { + QueryBuilder anyId() { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(const IdWhereClause.any()); + }); + } +} + +extension UserQueryWhere on QueryBuilder { + QueryBuilder idEqualTo(Id id) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(IdWhereClause.between( + lower: id, + upper: id, + )); + }); + } + + QueryBuilder idNotEqualTo(Id id) { + return QueryBuilder.apply(this, (query) { + if (query.whereSort == Sort.asc) { + return query + .addWhereClause( + IdWhereClause.lessThan(upper: id, includeUpper: false), + ) + .addWhereClause( + IdWhereClause.greaterThan(lower: id, includeLower: false), + ); + } else { + return query + .addWhereClause( + IdWhereClause.greaterThan(lower: id, includeLower: false), + ) + .addWhereClause( + IdWhereClause.lessThan(upper: id, includeUpper: false), + ); + } + }); + } + + QueryBuilder idGreaterThan(Id id, + {bool include = false}) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause( + IdWhereClause.greaterThan(lower: id, includeLower: include), + ); + }); + } + + QueryBuilder idLessThan(Id id, + {bool include = false}) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause( + IdWhereClause.lessThan(upper: id, includeUpper: include), + ); + }); + } + + QueryBuilder idBetween( + Id lowerId, + Id upperId, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(IdWhereClause.between( + lower: lowerId, + includeLower: includeLower, + upper: upperId, + includeUpper: includeUpper, + )); + }); + } +} + +extension UserQueryFilter on QueryBuilder { + QueryBuilder ageIsNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNull( + property: r'age', + )); + }); + } + + QueryBuilder ageIsNotNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNotNull( + property: r'age', + )); + }); + } + + QueryBuilder ageEqualTo(int? value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'age', + value: value, + )); + }); + } + + QueryBuilder ageGreaterThan( + int? value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'age', + value: value, + )); + }); + } + + QueryBuilder ageLessThan( + int? value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'age', + value: value, + )); + }); + } + + QueryBuilder ageBetween( + int? lower, + int? upper, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'age', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + )); + }); + } + + QueryBuilder idEqualTo(Id value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'id', + value: value, + )); + }); + } + + QueryBuilder idGreaterThan( + Id value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'id', + value: value, + )); + }); + } + + QueryBuilder idLessThan( + Id value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'id', + value: value, + )); + }); + } + + QueryBuilder idBetween( + Id lower, + Id upper, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'id', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + )); + }); + } + + QueryBuilder nameIsNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNull( + property: r'name', + )); + }); + } + + QueryBuilder nameIsNotNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNotNull( + property: r'name', + )); + }); + } + + QueryBuilder nameEqualTo( + String? value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'name', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder nameGreaterThan( + String? value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'name', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder nameLessThan( + String? value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'name', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder nameBetween( + String? lower, + String? upper, { + bool includeLower = true, + bool includeUpper = true, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'name', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder nameStartsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.startsWith( + property: r'name', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder nameEndsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.endsWith( + property: r'name', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder nameContains(String value, + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.contains( + property: r'name', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder nameMatches(String pattern, + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.matches( + property: r'name', + wildcard: pattern, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder nameIsEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'name', + value: '', + )); + }); + } + + QueryBuilder nameIsNotEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + property: r'name', + value: '', + )); + }); + } +} + +extension UserQueryObject on QueryBuilder {} + +extension UserQueryLinks on QueryBuilder {} + +extension UserQuerySortBy on QueryBuilder { + QueryBuilder sortByAge() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'age', Sort.asc); + }); + } + + QueryBuilder sortByAgeDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'age', Sort.desc); + }); + } + + QueryBuilder sortByName() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'name', Sort.asc); + }); + } + + QueryBuilder sortByNameDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'name', Sort.desc); + }); + } +} + +extension UserQuerySortThenBy on QueryBuilder { + QueryBuilder thenByAge() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'age', Sort.asc); + }); + } + + QueryBuilder thenByAgeDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'age', Sort.desc); + }); + } + + QueryBuilder thenById() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'id', Sort.asc); + }); + } + + QueryBuilder thenByIdDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'id', Sort.desc); + }); + } + + QueryBuilder thenByName() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'name', Sort.asc); + }); + } + + QueryBuilder thenByNameDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'name', Sort.desc); + }); + } +} + +extension UserQueryWhereDistinct on QueryBuilder { + QueryBuilder distinctByAge() { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'age'); + }); + } + + QueryBuilder distinctByName( + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'name', caseSensitive: caseSensitive); + }); + } +} + +extension UserQueryProperty on QueryBuilder { + QueryBuilder idProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'id'); + }); + } + + QueryBuilder ageProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'age'); + }); + } + + QueryBuilder nameProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'name'); + }); + } +} diff --git a/flutter/example/lib/main.dart b/flutter/example/lib/main.dart index 4e39b96db2..4cb5b97942 100644 --- a/flutter/example/lib/main.dart +++ b/flutter/example/lib/main.dart @@ -10,9 +10,9 @@ import 'package:logging/logging.dart'; import 'package:path_provider/path_provider.dart'; import 'package:sentry_drift/sentry_drift.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; +import 'package:sentry_isar/sentry_isar.dart'; import 'package:sentry_sqflite/sentry_sqflite.dart'; import 'package:sqflite/sqflite.dart'; - // import 'package:sqflite_common_ffi/sqflite_ffi.dart'; // import 'package:sqflite_common_ffi_web/sqflite_ffi_web.dart'; import 'package:universal_platform/universal_platform.dart'; @@ -21,6 +21,7 @@ import 'package:provider/provider.dart'; import 'auto_close_screen.dart'; import 'drift/database.dart'; import 'drift/connection/connection.dart'; +import 'isar/user.dart'; import 'user_feedback_dialog.dart'; import 'package:dio/dio.dart'; import 'package:sentry_dio/sentry_dio.dart'; @@ -212,6 +213,13 @@ class MainScaffold extends StatelessWidget { 'Executes CRUD operations on an in-memory with Hive and sends the created transaction to Sentry.', buttonTitle: 'hive', ), + if (!UniversalPlatform.isWeb) + TooltipButton( + onPressed: isarTest, + text: + 'Executes CRUD operations on an in-memory with Isart and sends the created transaction to Sentry.', + buttonTitle: 'isar', + ), TooltipButton( onPressed: sqfliteTest, text: @@ -528,11 +536,38 @@ class MainScaffold extends StatelessWidget { ); } - Future hiveTest() async { - if (kIsWeb) { - return; - } + Future isarTest() async { + final tr = Sentry.startTransaction( + 'isarTest', + 'db', + bindToScope: true, + ); + + final dir = await getApplicationDocumentsDirectory(); + final isar = await SentryIsar.open( + [UserSchema], + directory: dir.path, + ); + + final newUser = User() + ..name = 'Joe Dirt' + ..age = 36; + + await isar.writeTxn(() async { + await isar.users.put(newUser); // insert & update + }); + + final existingUser = await isar.users.get(newUser.id); // get + + await isar.writeTxn(() async { + await isar.users.delete(existingUser!.id); // delete + }); + + await tr.finish(status: const SpanStatus.ok()); + } + + Future hiveTest() async { final tr = Sentry.startTransaction( 'hiveTest', 'db', diff --git a/flutter/example/pubspec.yaml b/flutter/example/pubspec.yaml index cdbbbd0e0d..0f279e8e8f 100644 --- a/flutter/example/pubspec.yaml +++ b/flutter/example/pubspec.yaml @@ -19,6 +19,7 @@ dependencies: sentry_file: sentry_hive: sentry_drift: + sentry_isar: universal_platform: ^1.0.0 feedback: ^2.0.0 provider: ^6.0.0 @@ -26,6 +27,7 @@ dependencies: sqflite: any # This gets constrained by `sentry_sqflite` logging: any # This gets constrained by `sentry_logging` drift: any # This gets constrained by `sentry_drift` + isar: any # This gets constrained by `sentry_isar` package_info_plus: ^4.0.0 path_provider: ^2.0.0 #sqflite_common_ffi: ^2.0.0 @@ -42,6 +44,7 @@ dev_dependencies: flutter_test: sdk: flutter test: ^1.21.1 + build_runner: any flutter: uses-material-design: true diff --git a/flutter/example/pubspec_overrides.yaml b/flutter/example/pubspec_overrides.yaml index 4a3bb3c8cc..a392cc626d 100644 --- a/flutter/example/pubspec_overrides.yaml +++ b/flutter/example/pubspec_overrides.yaml @@ -15,3 +15,5 @@ dependency_overrides: path: ../../hive sentry_drift: path: ../../drift + sentry_isar: + path: ../../isar diff --git a/isar/.gitignore b/isar/.gitignore new file mode 100644 index 0000000000..fdd96ceb43 --- /dev/null +++ b/isar/.gitignore @@ -0,0 +1,17 @@ +# Omit committing pubspec.lock for library packages; see +# https://dart.dev/guides/libraries/private-files#pubspeclock. +pubspec.lock + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.packages +.pub-cache/ +.pub/ +/build/ + +# Downloaded on demand by tests for correct architecture. +libisar.dylib diff --git a/isar/.metadata b/isar/.metadata new file mode 100644 index 0000000000..eea17bc4a0 --- /dev/null +++ b/isar/.metadata @@ -0,0 +1,10 @@ +# 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. + +version: + revision: "2f708eb8396e362e280fac22cf171c2cb467343c" + channel: "stable" + +project_type: package diff --git a/isar/CHANGELOG.md b/isar/CHANGELOG.md new file mode 120000 index 0000000000..04c99a55ca --- /dev/null +++ b/isar/CHANGELOG.md @@ -0,0 +1 @@ +../CHANGELOG.md \ No newline at end of file diff --git a/isar/LICENSE b/isar/LICENSE new file mode 100644 index 0000000000..2a6964d84d --- /dev/null +++ b/isar/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 Sentry + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/isar/README.md b/isar/README.md new file mode 100644 index 0000000000..5405c8e43e --- /dev/null +++ b/isar/README.md @@ -0,0 +1,83 @@ +

+ + + +
+

+ +Sentry integration for `isar` package +=========== + +| package | build | pub | likes | popularity | pub points | +| ------- | ------- | ------- | ------- | ------- | ------- | +| sentry_isar | [![build](https://github.com/getsentry/sentry-dart/actions/workflows/isar.yml/badge.svg?branch=main)](https://github.com/getsentry/sentry-dart/actions?query=workflow%3Asentry-isar) | [![pub package](https://img.shields.io/pub/v/sentry_isar.svg)](https://pub.dev/packages/sentry_isar) | [![likes](https://img.shields.io/pub/likes/sentry_isar)](https://pub.dev/packages/sentry_isar/score) | [![popularity](https://img.shields.io/pub/popularity/sentry_isar)](https://pub.dev/packages/sentry_isar/score) | [![pub points](https://img.shields.io/pub/points/sentry_isar)](https://pub.dev/packages/sentry_isar/score) + +Integration for the [`isar`](https://pub.dev/packages/isar) package. + +#### Usage + +- Sign up for a Sentry.io account and get a DSN at https://sentry.io. + +- Follow the installing instructions on [pub.dev](https://pub.dev/packages/sentry/install). + +- Initialize the Sentry SDK using the DSN issued by Sentry.io. + +- Call... + +```dart +import 'package:path_provider/path_provider.dart'; +import 'package:sentry_flutter/sentry_flutter.dart'; +import 'package:sentry_isar/sentry_isar.dart'; + +import 'user.dart'; + +Future main() async { + await SentryFlutter.init( + (options) { + options.dsn = 'https://example@sentry.io/add-your-dsn-here'; + options.tracesSampleRate = 1.0; + }, + // Init your App. + appRunner: () => runApp(MyApp()), + ); +} + +Future runApp() async { + final tr = Sentry.startTransaction( + 'isarTest', + 'db', + bindToScope: true, + ); + + final dir = await getApplicationDocumentsDirectory(); + + final isar = await SentryIsar.open( + [UserSchema], + directory: dir.path, + ); + + final newUser = User() + ..name = 'Joe Dirt' + ..age = 36; + + await isar.writeTxn(() async { + await isar.users.put(newUser); // insert & update + }); + + final existingUser = await isar.users.get(newUser.id); // get + + await isar.writeTxn(() async { + await isar.users.delete(existingUser!.id); // delete + }); + + await tr.finish(status: const SpanStatus.ok()); +} +``` + +#### Resources + +* [![Documentation](https://img.shields.io/badge/documentation-sentry.io-green.svg)](https://docs.sentry.io/platforms/dart/) +* [![Forum](https://img.shields.io/badge/forum-sentry-green.svg)](https://forum.sentry.io/c/sdks) +* [![Discord](https://img.shields.io/discord/621778831602221064)](https://discord.gg/Ww9hbqr) +* [![Stack Overflow](https://img.shields.io/badge/stack%20overflow-sentry-green.svg)](https://stackoverflow.com/questions/tagged/sentry) +* [![Twitter Follow](https://img.shields.io/twitter/follow/getsentry?label=getsentry&style=social)](https://twitter.com/intent/follow?screen_name=getsentry) diff --git a/isar/analysis_options.yaml b/isar/analysis_options.yaml new file mode 100644 index 0000000000..92c8931384 --- /dev/null +++ b/isar/analysis_options.yaml @@ -0,0 +1,33 @@ +include: package:lints/recommended.yaml + +analyzer: + language: + strict-casts: true + strict-inference: true + strict-raw-types: true + errors: + # treat missing required parameters as a warning (not a hint) + missing_required_param: error + # treat missing returns as a warning (not a hint) + missing_return: error + # allow having TODOs in the code + todo: ignore + # allow self-reference to deprecated members (we do this because otherwise we have + # to annotate every member in every test, assert, etc, when we deprecate something) + deprecated_member_use_from_same_package: warning + # ignore sentry/path on pubspec as we change it on deployment + invalid_dependency: ignore + unnecessary_import: ignore + exclude: + - example/** + +linter: + rules: + - prefer_final_locals + - public_member_api_docs + - prefer_single_quotes + - prefer_relative_imports + - unnecessary_brace_in_string_interps + - implementation_imports + - require_trailing_commas + - unawaited_futures diff --git a/isar/dartdoc_options.yaml b/isar/dartdoc_options.yaml new file mode 120000 index 0000000000..7cbb8c0d74 --- /dev/null +++ b/isar/dartdoc_options.yaml @@ -0,0 +1 @@ +../dart/dartdoc_options.yaml \ No newline at end of file diff --git a/isar/example/main.dart b/isar/example/main.dart new file mode 100644 index 0000000000..7c9972b50d --- /dev/null +++ b/isar/example/main.dart @@ -0,0 +1,47 @@ +import 'package:path_provider/path_provider.dart'; +import 'package:sentry_flutter/sentry_flutter.dart'; +import 'package:sentry_isar/sentry_isar.dart'; + +import 'user.dart'; + +Future main() async { + // ATTENTION: Change the DSN below with your own to see the events in Sentry. Get one at sentry.io + const dsn = + 'https://e85b375ffb9f43cf8bdf9787768149e0@o447951.ingest.sentry.io/5428562'; + + await SentryFlutter.init( + (options) { + options.dsn = dsn; + options.tracesSampleRate = 1.0; + options.debug = true; + }, + appRunner: runApp, // Init your App. + ); +} + +Future runApp() async { + final tr = Sentry.startTransaction('isar', 'db', bindToScope: true); + + final dir = await getApplicationDocumentsDirectory(); + + final isar = await SentryIsar.open( + [UserSchema], + directory: dir.path, + ); + + final newUser = User() + ..name = 'Joe Dirt' + ..age = 36; + + await isar.writeTxn(() async { + await isar.users.put(newUser); // insert & update + }); + + final existingUser = await isar.users.get(newUser.id); // get + + await isar.writeTxn(() async { + await isar.users.delete(existingUser!.id); // delete + }); + + await tr.finish(status: const SpanStatus.ok()); +} diff --git a/isar/example/user.dart b/isar/example/user.dart new file mode 100644 index 0000000000..f255d2389d --- /dev/null +++ b/isar/example/user.dart @@ -0,0 +1,12 @@ +import 'package:isar/isar.dart'; + +part 'user.g.dart'; + +@collection +class User { + Id id = Isar.autoIncrement; + + String? name; + + int? age; +} diff --git a/isar/example/user.g.dart b/isar/example/user.g.dart new file mode 100644 index 0000000000..370c40860f --- /dev/null +++ b/isar/example/user.g.dart @@ -0,0 +1,553 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'user.dart'; + +// ************************************************************************** +// IsarCollectionGenerator +// ************************************************************************** + +// coverage:ignore-file +// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types + +extension GetUserCollection on Isar { + IsarCollection get users => this.collection(); +} + +const UserSchema = CollectionSchema( + name: r'User', + id: -7838171048429979076, + properties: { + r'age': PropertySchema( + id: 0, + name: r'age', + type: IsarType.long, + ), + r'name': PropertySchema( + id: 1, + name: r'name', + type: IsarType.string, + ) + }, + estimateSize: _userEstimateSize, + serialize: _userSerialize, + deserialize: _userDeserialize, + deserializeProp: _userDeserializeProp, + idName: r'id', + indexes: {}, + links: {}, + embeddedSchemas: {}, + getId: _userGetId, + getLinks: _userGetLinks, + attach: _userAttach, + version: '3.1.0+1', +); + +int _userEstimateSize( + User object, + List offsets, + Map> allOffsets, +) { + var bytesCount = offsets.last; + { + final value = object.name; + if (value != null) { + bytesCount += 3 + value.length * 3; + } + } + return bytesCount; +} + +void _userSerialize( + User object, + IsarWriter writer, + List offsets, + Map> allOffsets, +) { + writer.writeLong(offsets[0], object.age); + writer.writeString(offsets[1], object.name); +} + +User _userDeserialize( + Id id, + IsarReader reader, + List offsets, + Map> allOffsets, +) { + final object = User(); + object.age = reader.readLongOrNull(offsets[0]); + object.id = id; + object.name = reader.readStringOrNull(offsets[1]); + return object; +} + +P _userDeserializeProp

( + IsarReader reader, + int propertyId, + int offset, + Map> allOffsets, +) { + switch (propertyId) { + case 0: + return (reader.readLongOrNull(offset)) as P; + case 1: + return (reader.readStringOrNull(offset)) as P; + default: + throw IsarError('Unknown property with id $propertyId'); + } +} + +Id _userGetId(User object) { + return object.id; +} + +List> _userGetLinks(User object) { + return []; +} + +void _userAttach(IsarCollection col, Id id, User object) { + object.id = id; +} + +extension UserQueryWhereSort on QueryBuilder { + QueryBuilder anyId() { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(const IdWhereClause.any()); + }); + } +} + +extension UserQueryWhere on QueryBuilder { + QueryBuilder idEqualTo(Id id) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(IdWhereClause.between( + lower: id, + upper: id, + )); + }); + } + + QueryBuilder idNotEqualTo(Id id) { + return QueryBuilder.apply(this, (query) { + if (query.whereSort == Sort.asc) { + return query + .addWhereClause( + IdWhereClause.lessThan(upper: id, includeUpper: false), + ) + .addWhereClause( + IdWhereClause.greaterThan(lower: id, includeLower: false), + ); + } else { + return query + .addWhereClause( + IdWhereClause.greaterThan(lower: id, includeLower: false), + ) + .addWhereClause( + IdWhereClause.lessThan(upper: id, includeUpper: false), + ); + } + }); + } + + QueryBuilder idGreaterThan(Id id, + {bool include = false}) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause( + IdWhereClause.greaterThan(lower: id, includeLower: include), + ); + }); + } + + QueryBuilder idLessThan(Id id, + {bool include = false}) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause( + IdWhereClause.lessThan(upper: id, includeUpper: include), + ); + }); + } + + QueryBuilder idBetween( + Id lowerId, + Id upperId, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(IdWhereClause.between( + lower: lowerId, + includeLower: includeLower, + upper: upperId, + includeUpper: includeUpper, + )); + }); + } +} + +extension UserQueryFilter on QueryBuilder { + QueryBuilder ageIsNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNull( + property: r'age', + )); + }); + } + + QueryBuilder ageIsNotNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNotNull( + property: r'age', + )); + }); + } + + QueryBuilder ageEqualTo(int? value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'age', + value: value, + )); + }); + } + + QueryBuilder ageGreaterThan( + int? value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'age', + value: value, + )); + }); + } + + QueryBuilder ageLessThan( + int? value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'age', + value: value, + )); + }); + } + + QueryBuilder ageBetween( + int? lower, + int? upper, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'age', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + )); + }); + } + + QueryBuilder idEqualTo(Id value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'id', + value: value, + )); + }); + } + + QueryBuilder idGreaterThan( + Id value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'id', + value: value, + )); + }); + } + + QueryBuilder idLessThan( + Id value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'id', + value: value, + )); + }); + } + + QueryBuilder idBetween( + Id lower, + Id upper, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'id', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + )); + }); + } + + QueryBuilder nameIsNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNull( + property: r'name', + )); + }); + } + + QueryBuilder nameIsNotNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNotNull( + property: r'name', + )); + }); + } + + QueryBuilder nameEqualTo( + String? value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'name', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder nameGreaterThan( + String? value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'name', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder nameLessThan( + String? value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'name', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder nameBetween( + String? lower, + String? upper, { + bool includeLower = true, + bool includeUpper = true, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'name', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder nameStartsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.startsWith( + property: r'name', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder nameEndsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.endsWith( + property: r'name', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder nameContains(String value, + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.contains( + property: r'name', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder nameMatches(String pattern, + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.matches( + property: r'name', + wildcard: pattern, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder nameIsEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'name', + value: '', + )); + }); + } + + QueryBuilder nameIsNotEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + property: r'name', + value: '', + )); + }); + } +} + +extension UserQueryObject on QueryBuilder {} + +extension UserQueryLinks on QueryBuilder {} + +extension UserQuerySortBy on QueryBuilder { + QueryBuilder sortByAge() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'age', Sort.asc); + }); + } + + QueryBuilder sortByAgeDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'age', Sort.desc); + }); + } + + QueryBuilder sortByName() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'name', Sort.asc); + }); + } + + QueryBuilder sortByNameDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'name', Sort.desc); + }); + } +} + +extension UserQuerySortThenBy on QueryBuilder { + QueryBuilder thenByAge() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'age', Sort.asc); + }); + } + + QueryBuilder thenByAgeDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'age', Sort.desc); + }); + } + + QueryBuilder thenById() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'id', Sort.asc); + }); + } + + QueryBuilder thenByIdDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'id', Sort.desc); + }); + } + + QueryBuilder thenByName() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'name', Sort.asc); + }); + } + + QueryBuilder thenByNameDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'name', Sort.desc); + }); + } +} + +extension UserQueryWhereDistinct on QueryBuilder { + QueryBuilder distinctByAge() { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'age'); + }); + } + + QueryBuilder distinctByName( + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'name', caseSensitive: caseSensitive); + }); + } +} + +extension UserQueryProperty on QueryBuilder { + QueryBuilder idProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'id'); + }); + } + + QueryBuilder ageProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'age'); + }); + } + + QueryBuilder nameProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'name'); + }); + } +} diff --git a/isar/lib/sentry_isar.dart b/isar/lib/sentry_isar.dart new file mode 100644 index 0000000000..75e63c47ea --- /dev/null +++ b/isar/lib/sentry_isar.dart @@ -0,0 +1,4 @@ +library sentry_isar; + +export 'src/sentry_isar.dart'; +export 'src/sentry_isar_collection.dart'; diff --git a/isar/lib/src/sentry_isar.dart b/isar/lib/src/sentry_isar.dart new file mode 100644 index 0000000000..e6e174a8eb --- /dev/null +++ b/isar/lib/src/sentry_isar.dart @@ -0,0 +1,253 @@ +import 'package:isar/isar.dart'; +import 'package:meta/meta.dart'; +import 'package:sentry/sentry.dart'; +import 'version.dart'; + +import 'sentry_isar_collection.dart'; +import 'sentry_span_helper.dart'; + +/// A sentry wrapper around the Isar Database +@experimental +class SentryIsar implements Isar { + @internal + // ignore: public_member_api_docs + static const dbOp = 'db'; + + @internal + // ignore: public_member_api_docs + static const dbSystemKey = 'db.system'; + @internal + // ignore: public_member_api_docs + static const dbSystem = 'isar'; + + @internal + // ignore: public_member_api_docs + static const dbNameKey = 'db.name'; + + @internal + // ignore: public_member_api_docs + static const dbCollectionKey = 'db.collection'; + + final Isar _isar; + final Hub _hub; + final _spanHelper = SentrySpanHelper( + // ignore: invalid_use_of_internal_member + SentryTraceOrigins.autoDbIsar, + ); + + /// ctor of SentryIsar + SentryIsar(this._isar, this._hub) { + _spanHelper.setHub(_hub); + + // ignore: invalid_use_of_internal_member + final options = _hub.options; + options.sdk.addIntegration('SentryIsarTracing'); + options.sdk.addPackage(packageName, sdkVersion); + } + + /// Open a new Isar instance, wrapped by SentryIsar + static Future open( + List> schemas, { + required String directory, + String name = Isar.defaultName, + int maxSizeMiB = Isar.defaultMaxSizeMiB, + bool relaxedDurability = true, + CompactCondition? compactOnLaunch, + bool inspector = true, + Hub? hub, + }) async { + final spanHelper = SentrySpanHelper( + // ignore: invalid_use_of_internal_member + SentryTraceOrigins.autoDbIsar, + ); + final hubToUse = hub ?? HubAdapter(); + spanHelper.setHub(hubToUse); + + final isar = await spanHelper.asyncWrapInSpan( + 'open', + () async { + return await Isar.open( + schemas, + directory: directory, + name: name, + maxSizeMiB: maxSizeMiB, + relaxedDurability: relaxedDurability, + compactOnLaunch: compactOnLaunch, + inspector: inspector, + ); + }, + dbName: name, + ); + + return SentryIsar(isar, hubToUse); + } + + /// Open a new Isar instance, wrapped by SentryIsar + static Isar openSync( + List> schemas, { + required String directory, + String name = Isar.defaultName, + int maxSizeMiB = Isar.defaultMaxSizeMiB, + bool relaxedDurability = true, + CompactCondition? compactOnLaunch, + bool inspector = true, + Hub? hub, + }) { + final isar = Isar.openSync( + schemas, + directory: directory, + name: name, + maxSizeMiB: maxSizeMiB, + relaxedDurability: relaxedDurability, + compactOnLaunch: compactOnLaunch, + inspector: inspector, + ); + return SentryIsar(isar, hub ?? HubAdapter()); + } + + @override + void attachCollections(Map> collections) { + _isar.attachCollections(collections); + } + + @override + Future clear() { + return _spanHelper.asyncWrapInSpan( + 'clear', + () { + return _isar.clear(); + }, + dbName: name, + ); + } + + @override + void clearSync() { + _isar.clearSync(); + } + + @override + Future close({bool deleteFromDisk = false}) { + return _spanHelper.asyncWrapInSpan( + 'close', + () { + return _isar.close(deleteFromDisk: deleteFromDisk); + }, + dbName: name, + ); + } + + @override + IsarCollection collection() { + return SentryIsarCollection(_isar.collection(), _hub, name); + } + + @override + Future copyToFile(String targetPath) { + return _spanHelper.asyncWrapInSpan( + 'copyToFile', + () { + return _isar.copyToFile(targetPath); + }, + dbName: name, + ); + } + + @override + String? get directory => _isar.directory; + + @override + IsarCollection? getCollectionByNameInternal(String name) { + final collection = _isar.getCollectionByNameInternal(name); + if (collection != null) { + return SentryIsarCollection(collection, _hub, name); + } else { + return null; + } + } + + @override + Future getSize({ + bool includeIndexes = false, + bool includeLinks = false, + }) { + return _spanHelper.asyncWrapInSpan( + 'getSize', + () { + return _isar.getSize( + includeIndexes: includeIndexes, + includeLinks: includeLinks, + ); + }, + dbName: name, + ); + } + + @override + int getSizeSync({bool includeIndexes = false, bool includeLinks = false}) { + return _isar.getSizeSync( + includeIndexes: includeIndexes, + includeLinks: includeLinks, + ); + } + + @override + bool get isOpen => _isar.isOpen; + + @override + String get name => _isar.name; + + @override + String? get path => _isar.path; + + @override + void requireOpen() { + _isar.requireOpen(); + } + + @override + Future txn(Future Function() callback) { + return _spanHelper.asyncWrapInSpan( + 'txn', + () { + return _isar.txn(callback); + }, + dbName: name, + ); + } + + @override + T txnSync(T Function() callback) { + return _isar.txnSync(callback); + } + + @override + @visibleForTesting + @experimental + Future verify() { + return _spanHelper.asyncWrapInSpan( + 'verify', + () { + // ignore: invalid_use_of_visible_for_testing_member + return _isar.verify(); + }, + dbName: name, + ); + } + + @override + Future writeTxn(Future Function() callback, {bool silent = false}) { + return _spanHelper.asyncWrapInSpan( + 'writeTxn', + () { + return _isar.writeTxn(callback, silent: silent); + }, + dbName: name, + ); + } + + @override + T writeTxnSync(T Function() callback, {bool silent = false}) { + return _isar.writeTxnSync(callback, silent: silent); + } +} diff --git a/isar/lib/src/sentry_isar_collection.dart b/isar/lib/src/sentry_isar_collection.dart new file mode 100644 index 0000000000..3f85242bbe --- /dev/null +++ b/isar/lib/src/sentry_isar_collection.dart @@ -0,0 +1,433 @@ +import 'dart:typed_data'; +import 'package:isar/isar.dart'; +import 'package:meta/meta.dart'; +import 'package:sentry/sentry.dart'; + +import 'sentry_span_helper.dart'; + +/// Sentry wrapper around IsarCollection +@experimental +class SentryIsarCollection implements IsarCollection { + final IsarCollection _isarCollection; + final Hub _hub; + final String _dbName; + + final _spanHelper = SentrySpanHelper( + // ignore: invalid_use_of_internal_member + SentryTraceOrigins.autoDbIsarCollection, + ); + + /// ctor of SentryIsarCollection + SentryIsarCollection(this._isarCollection, this._hub, this._dbName) { + _spanHelper.setHub(_hub); + } + + @override + Query buildQuery({ + List whereClauses = const [], + bool whereDistinct = false, + Sort whereSort = Sort.asc, + FilterOperation? filter, + List sortBy = const [], + List distinctBy = const [], + int? offset, + int? limit, + String? property, + }) { + return _isarCollection.buildQuery( + whereClauses: whereClauses, + whereDistinct: whereDistinct, + whereSort: whereSort, + filter: filter, + sortBy: sortBy, + distinctBy: distinctBy, + offset: offset, + limit: limit, + property: property, + ); + } + + @override + Future clear() { + return _spanHelper.asyncWrapInSpan( + 'clear', + () { + return _isarCollection.clear(); + }, + dbName: _dbName, + collectionName: name, + ); + } + + @override + void clearSync() { + _isarCollection.clearSync(); + } + + @override + Future count() { + return _spanHelper.asyncWrapInSpan( + 'count', + () { + return _isarCollection.count(); + }, + dbName: _dbName, + collectionName: name, + ); + } + + @override + int countSync() { + return _isarCollection.countSync(); + } + + @override + Future delete(Id id) { + return _spanHelper.asyncWrapInSpan( + 'delete', + () { + return _isarCollection.delete(id); + }, + dbName: _dbName, + collectionName: name, + ); + } + + @override + Future deleteAll(List ids) { + return _spanHelper.asyncWrapInSpan( + 'deleteAll', + () { + return _isarCollection.deleteAll(ids); + }, + dbName: _dbName, + collectionName: name, + ); + } + + @override + Future deleteAllByIndex(String indexName, List keys) { + return _spanHelper.asyncWrapInSpan( + 'deleteAllByIndex', + () { + return _isarCollection.deleteAllByIndex(indexName, keys); + }, + dbName: _dbName, + collectionName: name, + ); + } + + @override + int deleteAllByIndexSync(String indexName, List keys) { + return _isarCollection.deleteAllByIndexSync(indexName, keys); + } + + @override + int deleteAllSync(List ids) { + return _isarCollection.deleteAllSync(ids); + } + + @override + Future deleteByIndex(String indexName, IndexKey key) { + return _spanHelper.asyncWrapInSpan( + 'deleteByIndex', + () { + return _isarCollection.deleteByIndex(indexName, key); + }, + dbName: _dbName, + collectionName: name, + ); + } + + @override + bool deleteByIndexSync(String indexName, IndexKey key) { + return _isarCollection.deleteByIndexSync(indexName, key); + } + + @override + bool deleteSync(Id id) { + return _isarCollection.deleteSync(id); + } + + @override + QueryBuilder filter() { + return _isarCollection.filter(); + } + + @override + Future get(Id id) { + return _spanHelper.asyncWrapInSpan( + 'get', + () { + return _isarCollection.get(id); + }, + dbName: _dbName, + collectionName: name, + ); + } + + @override + Future> getAll(List ids) { + return _spanHelper.asyncWrapInSpan( + 'getAll', + () { + return _isarCollection.getAll(ids); + }, + dbName: _dbName, + collectionName: name, + ); + } + + @override + Future> getAllByIndex(String indexName, List keys) { + return _spanHelper.asyncWrapInSpan( + 'getAllByIndex', + () { + return _isarCollection.getAllByIndex(indexName, keys); + }, + dbName: _dbName, + collectionName: name, + ); + } + + @override + List getAllByIndexSync(String indexName, List keys) { + return _isarCollection.getAllByIndexSync(indexName, keys); + } + + @override + List getAllSync(List ids) { + return _isarCollection.getAllSync(ids); + } + + @override + Future getByIndex(String indexName, IndexKey key) { + return _spanHelper.asyncWrapInSpan( + 'getByIndex', + () { + return _isarCollection.getByIndex(indexName, key); + }, + dbName: _dbName, + collectionName: name, + ); + } + + @override + OBJ? getByIndexSync(String indexName, IndexKey key) { + return _isarCollection.getByIndexSync(indexName, key); + } + + @override + Future getSize({ + bool includeIndexes = false, + bool includeLinks = false, + }) { + return _spanHelper.asyncWrapInSpan( + 'getSize', + () { + return _isarCollection.getSize( + includeIndexes: includeIndexes, + includeLinks: includeLinks, + ); + }, + dbName: _dbName, + collectionName: name, + ); + } + + @override + int getSizeSync({bool includeIndexes = false, bool includeLinks = false}) { + return _isarCollection.getSizeSync( + includeIndexes: includeIndexes, + includeLinks: includeLinks, + ); + } + + @override + OBJ? getSync(Id id) { + return _isarCollection.getSync(id); + } + + @override + Future importJson(List> json) { + return _spanHelper.asyncWrapInSpan( + 'importJson', + () { + return _isarCollection.importJson(json); + }, + dbName: _dbName, + collectionName: name, + ); + } + + @override + Future importJsonRaw(Uint8List jsonBytes) { + return _spanHelper.asyncWrapInSpan( + 'importJsonRaw', + () { + return _isarCollection.importJsonRaw(jsonBytes); + }, + dbName: _dbName, + collectionName: name, + ); + } + + @override + void importJsonRawSync(Uint8List jsonBytes) { + _isarCollection.importJsonRawSync(jsonBytes); + } + + @override + void importJsonSync(List> json) { + _isarCollection.importJsonSync(json); + } + + @override + Isar get isar => _isarCollection.isar; + + @override + String get name => _isarCollection.name; + + @override + Future put(OBJ object) { + return _spanHelper.asyncWrapInSpan( + 'put', + () { + return _isarCollection.put(object); + }, + dbName: _dbName, + collectionName: name, + ); + } + + @override + Future> putAll(List objects) { + return _spanHelper.asyncWrapInSpan( + 'putAll', + () { + return _isarCollection.putAll(objects); + }, + dbName: _dbName, + collectionName: name, + ); + } + + @override + Future> putAllByIndex(String indexName, List objects) { + return _spanHelper.asyncWrapInSpan( + 'putAllByIndex', + () { + return _isarCollection.putAllByIndex(indexName, objects); + }, + dbName: _dbName, + collectionName: name, + ); + } + + @override + List putAllByIndexSync( + String indexName, + List objects, { + bool saveLinks = true, + }) { + return _isarCollection.putAllByIndexSync( + indexName, + objects, + saveLinks: saveLinks, + ); + } + + @override + List putAllSync(List objects, {bool saveLinks = true}) { + return _isarCollection.putAllSync(objects, saveLinks: saveLinks); + } + + @override + Future putByIndex(String indexName, OBJ object) { + return _spanHelper.asyncWrapInSpan( + 'putByIndex', + () { + return _isarCollection.putByIndex(indexName, object); + }, + dbName: _dbName, + collectionName: name, + ); + } + + @override + Id putByIndexSync(String indexName, OBJ object, {bool saveLinks = true}) { + return _isarCollection.putByIndexSync( + indexName, + object, + saveLinks: saveLinks, + ); + } + + @override + Id putSync(OBJ object, {bool saveLinks = true}) { + return _isarCollection.putSync(object, saveLinks: saveLinks); + } + + @override + CollectionSchema get schema => _isarCollection.schema; + + @override + @visibleForTesting + @experimental + Future verify(List objects) { + return _spanHelper.asyncWrapInSpan( + 'verify', + () { + // ignore: invalid_use_of_visible_for_testing_member + return _isarCollection.verify(objects); + }, + dbName: _dbName, + collectionName: name, + ); + } + + @override + @visibleForTesting + @experimental + Future verifyLink( + String linkName, + List sourceIds, + List targetIds, + ) { + return _spanHelper.asyncWrapInSpan( + 'verifyLink', + () { + // ignore: invalid_use_of_visible_for_testing_member + return _isarCollection.verifyLink(linkName, sourceIds, targetIds); + }, + dbName: _dbName, + collectionName: name, + ); + } + + @override + Stream watchLazy({bool fireImmediately = false}) { + return _isarCollection.watchLazy(fireImmediately: fireImmediately); + } + + @override + Stream watchObject(Id id, {bool fireImmediately = false}) { + return _isarCollection.watchObject(id, fireImmediately: fireImmediately); + } + + @override + Stream watchObjectLazy(Id id, {bool fireImmediately = false}) { + return _isarCollection.watchObjectLazy( + id, + fireImmediately: fireImmediately, + ); + } + + @override + QueryBuilder where({ + bool distinct = false, + Sort sort = Sort.asc, + }) { + return _isarCollection.where(distinct: distinct, sort: sort); + } +} diff --git a/isar/lib/src/sentry_span_helper.dart b/isar/lib/src/sentry_span_helper.dart new file mode 100644 index 0000000000..69fc6e5c39 --- /dev/null +++ b/isar/lib/src/sentry_span_helper.dart @@ -0,0 +1,65 @@ +// ignore_for_file: invalid_internal_annotation + +import 'package:meta/meta.dart'; +import 'package:sentry/sentry.dart'; +import 'sentry_isar.dart'; + +/// @nodoc +@internal +class SentrySpanHelper { + /// @nodoc + Hub _hub = HubAdapter(); + + /// @nodoc + final String _origin; + + /// @nodoc + SentrySpanHelper(this._origin); + + /// @nodoc + void setHub(Hub hub) { + _hub = hub; + } + + /// @nodoc + @internal + Future asyncWrapInSpan( + String description, + Future Function() execute, { + String? dbName, + String? collectionName, + }) async { + final currentSpan = _hub.getSpan(); + final span = currentSpan?.startChild( + SentryIsar.dbOp, + description: description, + ); + + // ignore: invalid_use_of_internal_member + span?.origin = _origin; + + span?.setData(SentryIsar.dbSystemKey, SentryIsar.dbSystem); + + if (dbName != null) { + span?.setData(SentryIsar.dbNameKey, dbName); + } + + if (collectionName != null) { + span?.setData(SentryIsar.dbCollectionKey, collectionName); + } + + try { + final result = await execute(); + span?.status = SpanStatus.ok(); + + return result; + } catch (exception) { + span?.throwable = exception; + span?.status = SpanStatus.internalError(); + + rethrow; + } finally { + await span?.finish(); + } + } +} diff --git a/isar/lib/src/version.dart b/isar/lib/src/version.dart new file mode 100644 index 0000000000..7c1a7d4031 --- /dev/null +++ b/isar/lib/src/version.dart @@ -0,0 +1,5 @@ +/// The SDK version reported to Sentry.io in the submitted events. +const String sdkVersion = '7.13.1'; + +/// The package name reported to Sentry.io in the submitted events. +const String packageName = 'pub:sentry_isar'; diff --git a/isar/pubspec.yaml b/isar/pubspec.yaml new file mode 100644 index 0000000000..43c0907472 --- /dev/null +++ b/isar/pubspec.yaml @@ -0,0 +1,28 @@ +name: sentry_isar +description: An integration which adds support for performance tracing for the isar package. +version: 7.13.1 +homepage: https://docs.sentry.io/platforms/flutter/ +repository: https://github.com/getsentry/sentry-dart +issue_tracker: https://github.com/getsentry/sentry-dart/issues + +environment: + sdk: '>=2.17.0 <4.0.0' + flutter: '>=3.3.0' + +dependencies: + isar: ^3.1.0 + isar_flutter_libs: ^3.1.0 # contains Isar Core + sentry: 7.12.0 + meta: ^1.3.0 + path: ^1.8.3 + +dev_dependencies: + isar_generator: ^3.1.0 + build_runner: ^2.4.2 + lints: ^3.0.0 + flutter_test: + sdk: flutter + coverage: ^1.3.0 + mockito: ^5.1.0 + yaml: ^3.1.0 # needed for version match (code and pubspec) + path_provider: ^2.1.1 diff --git a/isar/pubspec_overrides.yaml b/isar/pubspec_overrides.yaml new file mode 100644 index 0000000000..16e71d16f0 --- /dev/null +++ b/isar/pubspec_overrides.yaml @@ -0,0 +1,3 @@ +dependency_overrides: + sentry: + path: ../dart diff --git a/isar/test/mocks/mocks.dart b/isar/test/mocks/mocks.dart new file mode 100644 index 0000000000..55f59b6de3 --- /dev/null +++ b/isar/test/mocks/mocks.dart @@ -0,0 +1,10 @@ +import 'package:isar/isar.dart'; +import 'package:mockito/annotations.dart'; +import 'package:sentry/sentry.dart'; + +@GenerateMocks([ + Hub, + Isar, + IsarCollection, +]) +void main() {} diff --git a/isar/test/mocks/mocks.mocks.dart b/isar/test/mocks/mocks.mocks.dart new file mode 100644 index 0000000000..4f7adfed86 --- /dev/null +++ b/isar/test/mocks/mocks.mocks.dart @@ -0,0 +1,1340 @@ +// Mocks generated by Mockito 5.4.2 from annotations +// in sentry_isar/test/mocks/mocks.dart. +// Do not manually edit this file. + +// ignore_for_file: no_leading_underscores_for_library_prefixes, invalid_use_of_internal_member +import 'dart:async' as _i3; +import 'dart:typed_data' as _i7; + +import 'package:isar/isar.dart' as _i4; +import 'package:mockito/mockito.dart' as _i1; +import 'package:mockito/src/dummies.dart' as _i6; +import 'package:sentry/sentry.dart' as _i2; +import 'package:sentry/src/profiling.dart' as _i5; + +// ignore_for_file: type=lint +// ignore_for_file: avoid_redundant_argument_values +// ignore_for_file: avoid_setters_without_getters +// ignore_for_file: comment_references +// ignore_for_file: implementation_imports +// ignore_for_file: invalid_use_of_visible_for_testing_member +// ignore_for_file: prefer_const_constructors +// ignore_for_file: unnecessary_parenthesis +// ignore_for_file: camel_case_types +// ignore_for_file: subtype_of_sealed_class + +class _FakeSentryOptions_0 extends _i1.SmartFake implements _i2.SentryOptions { + _FakeSentryOptions_0( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeSentryId_1 extends _i1.SmartFake implements _i2.SentryId { + _FakeSentryId_1( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeScope_2 extends _i1.SmartFake implements _i2.Scope { + _FakeScope_2( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeHub_3 extends _i1.SmartFake implements _i2.Hub { + _FakeHub_3( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeISentrySpan_4 extends _i1.SmartFake implements _i2.ISentrySpan { + _FakeISentrySpan_4( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeFuture_5 extends _i1.SmartFake implements _i3.Future { + _FakeFuture_5( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeIsarCollection_6 extends _i1.SmartFake + implements _i4.IsarCollection { + _FakeIsarCollection_6( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeIsar_7 extends _i1.SmartFake implements _i4.Isar { + _FakeIsar_7( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeCollectionSchema_8 extends _i1.SmartFake + implements _i4.CollectionSchema { + _FakeCollectionSchema_8( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeQueryBuilder_9 extends _i1.SmartFake + implements _i4.QueryBuilder { + _FakeQueryBuilder_9( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeQuery_10 extends _i1.SmartFake implements _i4.Query { + _FakeQuery_10( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +/// A class which mocks [Hub]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockHub extends _i1.Mock implements _i2.Hub { + MockHub() { + _i1.throwOnMissingStub(this); + } + + @override + _i2.SentryOptions get options => (super.noSuchMethod( + Invocation.getter(#options), + returnValue: _FakeSentryOptions_0( + this, + Invocation.getter(#options), + ), + ) as _i2.SentryOptions); + + @override + bool get isEnabled => (super.noSuchMethod( + Invocation.getter(#isEnabled), + returnValue: false, + ) as bool); + + @override + _i2.SentryId get lastEventId => (super.noSuchMethod( + Invocation.getter(#lastEventId), + returnValue: _FakeSentryId_1( + this, + Invocation.getter(#lastEventId), + ), + ) as _i2.SentryId); + + @override + _i2.Scope get scope => (super.noSuchMethod( + Invocation.getter(#scope), + returnValue: _FakeScope_2( + this, + Invocation.getter(#scope), + ), + ) as _i2.Scope); + + @override + set profilerFactory(_i5.SentryProfilerFactory? value) => super.noSuchMethod( + Invocation.setter( + #profilerFactory, + value, + ), + returnValueForMissingStub: null, + ); + + @override + _i3.Future<_i2.SentryId> captureEvent( + _i2.SentryEvent? event, { + dynamic stackTrace, + _i2.Hint? hint, + _i2.ScopeCallback? withScope, + }) => + (super.noSuchMethod( + Invocation.method( + #captureEvent, + [event], + { + #stackTrace: stackTrace, + #hint: hint, + #withScope: withScope, + }, + ), + returnValue: _i3.Future<_i2.SentryId>.value(_FakeSentryId_1( + this, + Invocation.method( + #captureEvent, + [event], + { + #stackTrace: stackTrace, + #hint: hint, + #withScope: withScope, + }, + ), + )), + ) as _i3.Future<_i2.SentryId>); + + @override + _i3.Future<_i2.SentryId> captureException( + dynamic throwable, { + dynamic stackTrace, + _i2.Hint? hint, + _i2.ScopeCallback? withScope, + }) => + (super.noSuchMethod( + Invocation.method( + #captureException, + [throwable], + { + #stackTrace: stackTrace, + #hint: hint, + #withScope: withScope, + }, + ), + returnValue: _i3.Future<_i2.SentryId>.value(_FakeSentryId_1( + this, + Invocation.method( + #captureException, + [throwable], + { + #stackTrace: stackTrace, + #hint: hint, + #withScope: withScope, + }, + ), + )), + ) as _i3.Future<_i2.SentryId>); + + @override + _i3.Future<_i2.SentryId> captureMessage( + String? message, { + _i2.SentryLevel? level, + String? template, + List? params, + _i2.Hint? hint, + _i2.ScopeCallback? withScope, + }) => + (super.noSuchMethod( + Invocation.method( + #captureMessage, + [message], + { + #level: level, + #template: template, + #params: params, + #hint: hint, + #withScope: withScope, + }, + ), + returnValue: _i3.Future<_i2.SentryId>.value(_FakeSentryId_1( + this, + Invocation.method( + #captureMessage, + [message], + { + #level: level, + #template: template, + #params: params, + #hint: hint, + #withScope: withScope, + }, + ), + )), + ) as _i3.Future<_i2.SentryId>); + + @override + _i3.Future captureUserFeedback(_i2.SentryUserFeedback? userFeedback) => + (super.noSuchMethod( + Invocation.method( + #captureUserFeedback, + [userFeedback], + ), + returnValue: _i3.Future.value(), + returnValueForMissingStub: _i3.Future.value(), + ) as _i3.Future); + + @override + _i3.Future addBreadcrumb( + _i2.Breadcrumb? crumb, { + _i2.Hint? hint, + }) => + (super.noSuchMethod( + Invocation.method( + #addBreadcrumb, + [crumb], + {#hint: hint}, + ), + returnValue: _i3.Future.value(), + returnValueForMissingStub: _i3.Future.value(), + ) as _i3.Future); + + @override + void bindClient(_i2.SentryClient? client) => super.noSuchMethod( + Invocation.method( + #bindClient, + [client], + ), + returnValueForMissingStub: null, + ); + + @override + _i2.Hub clone() => (super.noSuchMethod( + Invocation.method( + #clone, + [], + ), + returnValue: _FakeHub_3( + this, + Invocation.method( + #clone, + [], + ), + ), + ) as _i2.Hub); + + @override + _i3.Future close() => (super.noSuchMethod( + Invocation.method( + #close, + [], + ), + returnValue: _i3.Future.value(), + returnValueForMissingStub: _i3.Future.value(), + ) as _i3.Future); + + @override + _i3.FutureOr configureScope(_i2.ScopeCallback? callback) => + (super.noSuchMethod(Invocation.method( + #configureScope, + [callback], + )) as _i3.FutureOr); + + @override + _i2.ISentrySpan startTransaction( + String? name, + String? operation, { + String? description, + DateTime? startTimestamp, + bool? bindToScope, + bool? waitForChildren, + Duration? autoFinishAfter, + bool? trimEnd, + _i2.OnTransactionFinish? onFinish, + Map? customSamplingContext, + }) => + (super.noSuchMethod( + Invocation.method( + #startTransaction, + [ + name, + operation, + ], + { + #description: description, + #startTimestamp: startTimestamp, + #bindToScope: bindToScope, + #waitForChildren: waitForChildren, + #autoFinishAfter: autoFinishAfter, + #trimEnd: trimEnd, + #onFinish: onFinish, + #customSamplingContext: customSamplingContext, + }, + ), + returnValue: _FakeISentrySpan_4( + this, + Invocation.method( + #startTransaction, + [ + name, + operation, + ], + { + #description: description, + #startTimestamp: startTimestamp, + #bindToScope: bindToScope, + #waitForChildren: waitForChildren, + #autoFinishAfter: autoFinishAfter, + #trimEnd: trimEnd, + #onFinish: onFinish, + #customSamplingContext: customSamplingContext, + }, + ), + ), + ) as _i2.ISentrySpan); + + @override + _i2.ISentrySpan startTransactionWithContext( + _i2.SentryTransactionContext? transactionContext, { + Map? customSamplingContext, + DateTime? startTimestamp, + bool? bindToScope, + bool? waitForChildren, + Duration? autoFinishAfter, + bool? trimEnd, + _i2.OnTransactionFinish? onFinish, + }) => + (super.noSuchMethod( + Invocation.method( + #startTransactionWithContext, + [transactionContext], + { + #customSamplingContext: customSamplingContext, + #startTimestamp: startTimestamp, + #bindToScope: bindToScope, + #waitForChildren: waitForChildren, + #autoFinishAfter: autoFinishAfter, + #trimEnd: trimEnd, + #onFinish: onFinish, + }, + ), + returnValue: _FakeISentrySpan_4( + this, + Invocation.method( + #startTransactionWithContext, + [transactionContext], + { + #customSamplingContext: customSamplingContext, + #startTimestamp: startTimestamp, + #bindToScope: bindToScope, + #waitForChildren: waitForChildren, + #autoFinishAfter: autoFinishAfter, + #trimEnd: trimEnd, + #onFinish: onFinish, + }, + ), + ), + ) as _i2.ISentrySpan); + + @override + _i3.Future<_i2.SentryId> captureTransaction( + _i2.SentryTransaction? transaction, { + _i2.SentryTraceContextHeader? traceContext, + }) => + (super.noSuchMethod( + Invocation.method( + #captureTransaction, + [transaction], + {#traceContext: traceContext}, + ), + returnValue: _i3.Future<_i2.SentryId>.value(_FakeSentryId_1( + this, + Invocation.method( + #captureTransaction, + [transaction], + {#traceContext: traceContext}, + ), + )), + ) as _i3.Future<_i2.SentryId>); + + @override + void setSpanContext( + dynamic throwable, + _i2.ISentrySpan? span, + String? transaction, + ) => + super.noSuchMethod( + Invocation.method( + #setSpanContext, + [ + throwable, + span, + transaction, + ], + ), + returnValueForMissingStub: null, + ); +} + +/// A class which mocks [Isar]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockIsar extends _i1.Mock implements _i4.Isar { + MockIsar() { + _i1.throwOnMissingStub(this); + } + + @override + String get name => (super.noSuchMethod( + Invocation.getter(#name), + returnValue: '', + ) as String); + + @override + bool get isOpen => (super.noSuchMethod( + Invocation.getter(#isOpen), + returnValue: false, + ) as bool); + + @override + void requireOpen() => super.noSuchMethod( + Invocation.method( + #requireOpen, + [], + ), + returnValueForMissingStub: null, + ); + + @override + _i3.Future txn(_i3.Future Function()? callback) => + (super.noSuchMethod( + Invocation.method( + #txn, + [callback], + ), + returnValue: _i6.ifNotNull( + _i6.dummyValueOrNull( + this, + Invocation.method( + #txn, + [callback], + ), + ), + (T v) => _i3.Future.value(v), + ) ?? + _FakeFuture_5( + this, + Invocation.method( + #txn, + [callback], + ), + ), + ) as _i3.Future); + + @override + _i3.Future writeTxn( + _i3.Future Function()? callback, { + bool? silent = false, + }) => + (super.noSuchMethod( + Invocation.method( + #writeTxn, + [callback], + {#silent: silent}, + ), + returnValue: _i6.ifNotNull( + _i6.dummyValueOrNull( + this, + Invocation.method( + #writeTxn, + [callback], + {#silent: silent}, + ), + ), + (T v) => _i3.Future.value(v), + ) ?? + _FakeFuture_5( + this, + Invocation.method( + #writeTxn, + [callback], + {#silent: silent}, + ), + ), + ) as _i3.Future); + + @override + T txnSync(T Function()? callback) => (super.noSuchMethod( + Invocation.method( + #txnSync, + [callback], + ), + returnValue: _i6.dummyValue( + this, + Invocation.method( + #txnSync, + [callback], + ), + ), + ) as T); + + @override + T writeTxnSync( + T Function()? callback, { + bool? silent = false, + }) => + (super.noSuchMethod( + Invocation.method( + #writeTxnSync, + [callback], + {#silent: silent}, + ), + returnValue: _i6.dummyValue( + this, + Invocation.method( + #writeTxnSync, + [callback], + {#silent: silent}, + ), + ), + ) as T); + + @override + void attachCollections(Map>? collections) => + super.noSuchMethod( + Invocation.method( + #attachCollections, + [collections], + ), + returnValueForMissingStub: null, + ); + + @override + _i4.IsarCollection collection() => (super.noSuchMethod( + Invocation.method( + #collection, + [], + ), + returnValue: _FakeIsarCollection_6( + this, + Invocation.method( + #collection, + [], + ), + ), + ) as _i4.IsarCollection); + + @override + _i4.IsarCollection? getCollectionByNameInternal(String? name) => + (super.noSuchMethod(Invocation.method( + #getCollectionByNameInternal, + [name], + )) as _i4.IsarCollection?); + + @override + _i3.Future clear() => (super.noSuchMethod( + Invocation.method( + #clear, + [], + ), + returnValue: _i3.Future.value(), + returnValueForMissingStub: _i3.Future.value(), + ) as _i3.Future); + + @override + void clearSync() => super.noSuchMethod( + Invocation.method( + #clearSync, + [], + ), + returnValueForMissingStub: null, + ); + + @override + _i3.Future getSize({ + bool? includeIndexes = false, + bool? includeLinks = false, + }) => + (super.noSuchMethod( + Invocation.method( + #getSize, + [], + { + #includeIndexes: includeIndexes, + #includeLinks: includeLinks, + }, + ), + returnValue: _i3.Future.value(0), + ) as _i3.Future); + + @override + int getSizeSync({ + bool? includeIndexes = false, + bool? includeLinks = false, + }) => + (super.noSuchMethod( + Invocation.method( + #getSizeSync, + [], + { + #includeIndexes: includeIndexes, + #includeLinks: includeLinks, + }, + ), + returnValue: 0, + ) as int); + + @override + _i3.Future copyToFile(String? targetPath) => (super.noSuchMethod( + Invocation.method( + #copyToFile, + [targetPath], + ), + returnValue: _i3.Future.value(), + returnValueForMissingStub: _i3.Future.value(), + ) as _i3.Future); + + @override + _i3.Future close({bool? deleteFromDisk = false}) => (super.noSuchMethod( + Invocation.method( + #close, + [], + {#deleteFromDisk: deleteFromDisk}, + ), + returnValue: _i3.Future.value(false), + ) as _i3.Future); + + @override + _i3.Future verify() => (super.noSuchMethod( + Invocation.method( + #verify, + [], + ), + returnValue: _i3.Future.value(), + returnValueForMissingStub: _i3.Future.value(), + ) as _i3.Future); +} + +/// A class which mocks [IsarCollection]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockIsarCollection extends _i1.Mock + implements _i4.IsarCollection { + MockIsarCollection() { + _i1.throwOnMissingStub(this); + } + + @override + _i4.Isar get isar => (super.noSuchMethod( + Invocation.getter(#isar), + returnValue: _FakeIsar_7( + this, + Invocation.getter(#isar), + ), + ) as _i4.Isar); + + @override + _i4.CollectionSchema get schema => (super.noSuchMethod( + Invocation.getter(#schema), + returnValue: _FakeCollectionSchema_8( + this, + Invocation.getter(#schema), + ), + ) as _i4.CollectionSchema); + + @override + String get name => (super.noSuchMethod( + Invocation.getter(#name), + returnValue: '', + ) as String); + + @override + _i3.Future get(int? id) => (super.noSuchMethod( + Invocation.method( + #get, + [id], + ), + returnValue: _i3.Future.value(), + ) as _i3.Future); + + @override + OBJ? getSync(int? id) => (super.noSuchMethod(Invocation.method( + #getSync, + [id], + )) as OBJ?); + + @override + _i3.Future> getAll(List? ids) => (super.noSuchMethod( + Invocation.method( + #getAll, + [ids], + ), + returnValue: _i3.Future>.value([]), + ) as _i3.Future>); + + @override + List getAllSync(List? ids) => (super.noSuchMethod( + Invocation.method( + #getAllSync, + [ids], + ), + returnValue: [], + ) as List); + + @override + _i3.Future getByIndex( + String? indexName, + List? key, + ) => + (super.noSuchMethod( + Invocation.method( + #getByIndex, + [ + indexName, + key, + ], + ), + returnValue: _i3.Future.value(), + ) as _i3.Future); + + @override + OBJ? getByIndexSync( + String? indexName, + List? key, + ) => + (super.noSuchMethod(Invocation.method( + #getByIndexSync, + [ + indexName, + key, + ], + )) as OBJ?); + + @override + _i3.Future> getAllByIndex( + String? indexName, + List>? keys, + ) => + (super.noSuchMethod( + Invocation.method( + #getAllByIndex, + [ + indexName, + keys, + ], + ), + returnValue: _i3.Future>.value([]), + ) as _i3.Future>); + + @override + List getAllByIndexSync( + String? indexName, + List>? keys, + ) => + (super.noSuchMethod( + Invocation.method( + #getAllByIndexSync, + [ + indexName, + keys, + ], + ), + returnValue: [], + ) as List); + + @override + _i3.Future put(OBJ? object) => (super.noSuchMethod( + Invocation.method( + #put, + [object], + ), + returnValue: _i3.Future.value(0), + ) as _i3.Future); + + @override + int putSync( + OBJ? object, { + bool? saveLinks = true, + }) => + (super.noSuchMethod( + Invocation.method( + #putSync, + [object], + {#saveLinks: saveLinks}, + ), + returnValue: 0, + ) as int); + + @override + _i3.Future> putAll(List? objects) => (super.noSuchMethod( + Invocation.method( + #putAll, + [objects], + ), + returnValue: _i3.Future>.value([]), + ) as _i3.Future>); + + @override + List putAllSync( + List? objects, { + bool? saveLinks = true, + }) => + (super.noSuchMethod( + Invocation.method( + #putAllSync, + [objects], + {#saveLinks: saveLinks}, + ), + returnValue: [], + ) as List); + + @override + _i3.Future putByIndex( + String? indexName, + OBJ? object, + ) => + (super.noSuchMethod( + Invocation.method( + #putByIndex, + [ + indexName, + object, + ], + ), + returnValue: _i3.Future.value(0), + ) as _i3.Future); + + @override + int putByIndexSync( + String? indexName, + OBJ? object, { + bool? saveLinks = true, + }) => + (super.noSuchMethod( + Invocation.method( + #putByIndexSync, + [ + indexName, + object, + ], + {#saveLinks: saveLinks}, + ), + returnValue: 0, + ) as int); + + @override + _i3.Future> putAllByIndex( + String? indexName, + List? objects, + ) => + (super.noSuchMethod( + Invocation.method( + #putAllByIndex, + [ + indexName, + objects, + ], + ), + returnValue: _i3.Future>.value([]), + ) as _i3.Future>); + + @override + List putAllByIndexSync( + String? indexName, + List? objects, { + bool? saveLinks = true, + }) => + (super.noSuchMethod( + Invocation.method( + #putAllByIndexSync, + [ + indexName, + objects, + ], + {#saveLinks: saveLinks}, + ), + returnValue: [], + ) as List); + + @override + _i3.Future delete(int? id) => (super.noSuchMethod( + Invocation.method( + #delete, + [id], + ), + returnValue: _i3.Future.value(false), + ) as _i3.Future); + + @override + bool deleteSync(int? id) => (super.noSuchMethod( + Invocation.method( + #deleteSync, + [id], + ), + returnValue: false, + ) as bool); + + @override + _i3.Future deleteAll(List? ids) => (super.noSuchMethod( + Invocation.method( + #deleteAll, + [ids], + ), + returnValue: _i3.Future.value(0), + ) as _i3.Future); + + @override + int deleteAllSync(List? ids) => (super.noSuchMethod( + Invocation.method( + #deleteAllSync, + [ids], + ), + returnValue: 0, + ) as int); + + @override + _i3.Future deleteByIndex( + String? indexName, + List? key, + ) => + (super.noSuchMethod( + Invocation.method( + #deleteByIndex, + [ + indexName, + key, + ], + ), + returnValue: _i3.Future.value(false), + ) as _i3.Future); + + @override + bool deleteByIndexSync( + String? indexName, + List? key, + ) => + (super.noSuchMethod( + Invocation.method( + #deleteByIndexSync, + [ + indexName, + key, + ], + ), + returnValue: false, + ) as bool); + + @override + _i3.Future deleteAllByIndex( + String? indexName, + List>? keys, + ) => + (super.noSuchMethod( + Invocation.method( + #deleteAllByIndex, + [ + indexName, + keys, + ], + ), + returnValue: _i3.Future.value(0), + ) as _i3.Future); + + @override + int deleteAllByIndexSync( + String? indexName, + List>? keys, + ) => + (super.noSuchMethod( + Invocation.method( + #deleteAllByIndexSync, + [ + indexName, + keys, + ], + ), + returnValue: 0, + ) as int); + + @override + _i3.Future clear() => (super.noSuchMethod( + Invocation.method( + #clear, + [], + ), + returnValue: _i3.Future.value(), + returnValueForMissingStub: _i3.Future.value(), + ) as _i3.Future); + + @override + void clearSync() => super.noSuchMethod( + Invocation.method( + #clearSync, + [], + ), + returnValueForMissingStub: null, + ); + + @override + _i3.Future importJsonRaw(_i7.Uint8List? jsonBytes) => + (super.noSuchMethod( + Invocation.method( + #importJsonRaw, + [jsonBytes], + ), + returnValue: _i3.Future.value(), + returnValueForMissingStub: _i3.Future.value(), + ) as _i3.Future); + + @override + void importJsonRawSync(_i7.Uint8List? jsonBytes) => super.noSuchMethod( + Invocation.method( + #importJsonRawSync, + [jsonBytes], + ), + returnValueForMissingStub: null, + ); + + @override + _i3.Future importJson(List>? json) => + (super.noSuchMethod( + Invocation.method( + #importJson, + [json], + ), + returnValue: _i3.Future.value(), + returnValueForMissingStub: _i3.Future.value(), + ) as _i3.Future); + + @override + void importJsonSync(List>? json) => super.noSuchMethod( + Invocation.method( + #importJsonSync, + [json], + ), + returnValueForMissingStub: null, + ); + + @override + _i4.QueryBuilder where({ + bool? distinct = false, + _i4.Sort? sort = _i4.Sort.asc, + }) => + (super.noSuchMethod( + Invocation.method( + #where, + [], + { + #distinct: distinct, + #sort: sort, + }, + ), + returnValue: _FakeQueryBuilder_9( + this, + Invocation.method( + #where, + [], + { + #distinct: distinct, + #sort: sort, + }, + ), + ), + ) as _i4.QueryBuilder); + + @override + _i4.QueryBuilder filter() => + (super.noSuchMethod( + Invocation.method( + #filter, + [], + ), + returnValue: _FakeQueryBuilder_9( + this, + Invocation.method( + #filter, + [], + ), + ), + ) as _i4.QueryBuilder); + + @override + _i4.Query buildQuery({ + List<_i4.WhereClause>? whereClauses = const [], + bool? whereDistinct = false, + _i4.Sort? whereSort = _i4.Sort.asc, + _i4.FilterOperation? filter, + List<_i4.SortProperty>? sortBy = const [], + List<_i4.DistinctProperty>? distinctBy = const [], + int? offset, + int? limit, + String? property, + }) => + (super.noSuchMethod( + Invocation.method( + #buildQuery, + [], + { + #whereClauses: whereClauses, + #whereDistinct: whereDistinct, + #whereSort: whereSort, + #filter: filter, + #sortBy: sortBy, + #distinctBy: distinctBy, + #offset: offset, + #limit: limit, + #property: property, + }, + ), + returnValue: _FakeQuery_10( + this, + Invocation.method( + #buildQuery, + [], + { + #whereClauses: whereClauses, + #whereDistinct: whereDistinct, + #whereSort: whereSort, + #filter: filter, + #sortBy: sortBy, + #distinctBy: distinctBy, + #offset: offset, + #limit: limit, + #property: property, + }, + ), + ), + ) as _i4.Query); + + @override + _i3.Future count() => (super.noSuchMethod( + Invocation.method( + #count, + [], + ), + returnValue: _i3.Future.value(0), + ) as _i3.Future); + + @override + int countSync() => (super.noSuchMethod( + Invocation.method( + #countSync, + [], + ), + returnValue: 0, + ) as int); + + @override + _i3.Future getSize({ + bool? includeIndexes = false, + bool? includeLinks = false, + }) => + (super.noSuchMethod( + Invocation.method( + #getSize, + [], + { + #includeIndexes: includeIndexes, + #includeLinks: includeLinks, + }, + ), + returnValue: _i3.Future.value(0), + ) as _i3.Future); + + @override + int getSizeSync({ + bool? includeIndexes = false, + bool? includeLinks = false, + }) => + (super.noSuchMethod( + Invocation.method( + #getSizeSync, + [], + { + #includeIndexes: includeIndexes, + #includeLinks: includeLinks, + }, + ), + returnValue: 0, + ) as int); + + @override + _i3.Stream watchLazy({bool? fireImmediately = false}) => + (super.noSuchMethod( + Invocation.method( + #watchLazy, + [], + {#fireImmediately: fireImmediately}, + ), + returnValue: _i3.Stream.empty(), + ) as _i3.Stream); + + @override + _i3.Stream watchObject( + int? id, { + bool? fireImmediately = false, + }) => + (super.noSuchMethod( + Invocation.method( + #watchObject, + [id], + {#fireImmediately: fireImmediately}, + ), + returnValue: _i3.Stream.empty(), + ) as _i3.Stream); + + @override + _i3.Stream watchObjectLazy( + int? id, { + bool? fireImmediately = false, + }) => + (super.noSuchMethod( + Invocation.method( + #watchObjectLazy, + [id], + {#fireImmediately: fireImmediately}, + ), + returnValue: _i3.Stream.empty(), + ) as _i3.Stream); + + @override + _i3.Future verify(List? objects) => (super.noSuchMethod( + Invocation.method( + #verify, + [objects], + ), + returnValue: _i3.Future.value(), + returnValueForMissingStub: _i3.Future.value(), + ) as _i3.Future); + + @override + _i3.Future verifyLink( + String? linkName, + List? sourceIds, + List? targetIds, + ) => + (super.noSuchMethod( + Invocation.method( + #verifyLink, + [ + linkName, + sourceIds, + targetIds, + ], + ), + returnValue: _i3.Future.value(), + returnValueForMissingStub: _i3.Future.value(), + ) as _i3.Future); +} diff --git a/isar/test/person.dart b/isar/test/person.dart new file mode 100644 index 0000000000..385ae69e04 --- /dev/null +++ b/isar/test/person.dart @@ -0,0 +1,11 @@ +import 'package:isar/isar.dart'; + +part 'person.g.dart'; + +@collection +class Person { + Id id = Isar.autoIncrement; + + @Index() + String? name; +} diff --git a/isar/test/person.g.dart b/isar/test/person.g.dart new file mode 100644 index 0000000000..cbd85e6fe5 --- /dev/null +++ b/isar/test/person.g.dart @@ -0,0 +1,518 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'person.dart'; + +// ************************************************************************** +// IsarCollectionGenerator +// ************************************************************************** + +// coverage:ignore-file +// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types + +extension GetPersonCollection on Isar { + IsarCollection get persons => this.collection(); +} + +const PersonSchema = CollectionSchema( + name: r'Person', + id: 7854610480646705599, + properties: { + r'name': PropertySchema( + id: 0, + name: r'name', + type: IsarType.string, + ) + }, + estimateSize: _personEstimateSize, + serialize: _personSerialize, + deserialize: _personDeserialize, + deserializeProp: _personDeserializeProp, + idName: r'id', + indexes: { + r'name': IndexSchema( + id: 879695947855722453, + name: r'name', + unique: false, + replace: false, + properties: [ + IndexPropertySchema( + name: r'name', + type: IndexType.hash, + caseSensitive: true, + ) + ], + ) + }, + links: {}, + embeddedSchemas: {}, + getId: _personGetId, + getLinks: _personGetLinks, + attach: _personAttach, + version: '3.1.0+1', +); + +int _personEstimateSize( + Person object, + List offsets, + Map> allOffsets, +) { + var bytesCount = offsets.last; + { + final value = object.name; + if (value != null) { + bytesCount += 3 + value.length * 3; + } + } + return bytesCount; +} + +void _personSerialize( + Person object, + IsarWriter writer, + List offsets, + Map> allOffsets, +) { + writer.writeString(offsets[0], object.name); +} + +Person _personDeserialize( + Id id, + IsarReader reader, + List offsets, + Map> allOffsets, +) { + final object = Person(); + object.id = id; + object.name = reader.readStringOrNull(offsets[0]); + return object; +} + +P _personDeserializeProp

( + IsarReader reader, + int propertyId, + int offset, + Map> allOffsets, +) { + switch (propertyId) { + case 0: + return (reader.readStringOrNull(offset)) as P; + default: + throw IsarError('Unknown property with id $propertyId'); + } +} + +Id _personGetId(Person object) { + return object.id; +} + +List> _personGetLinks(Person object) { + return []; +} + +void _personAttach(IsarCollection col, Id id, Person object) { + object.id = id; +} + +extension PersonQueryWhereSort on QueryBuilder { + QueryBuilder anyId() { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(const IdWhereClause.any()); + }); + } +} + +extension PersonQueryWhere on QueryBuilder { + QueryBuilder idEqualTo(Id id) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(IdWhereClause.between( + lower: id, + upper: id, + )); + }); + } + + QueryBuilder idNotEqualTo(Id id) { + return QueryBuilder.apply(this, (query) { + if (query.whereSort == Sort.asc) { + return query + .addWhereClause( + IdWhereClause.lessThan(upper: id, includeUpper: false), + ) + .addWhereClause( + IdWhereClause.greaterThan(lower: id, includeLower: false), + ); + } else { + return query + .addWhereClause( + IdWhereClause.greaterThan(lower: id, includeLower: false), + ) + .addWhereClause( + IdWhereClause.lessThan(upper: id, includeUpper: false), + ); + } + }); + } + + QueryBuilder idGreaterThan(Id id, + {bool include = false}) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause( + IdWhereClause.greaterThan(lower: id, includeLower: include), + ); + }); + } + + QueryBuilder idLessThan(Id id, + {bool include = false}) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause( + IdWhereClause.lessThan(upper: id, includeUpper: include), + ); + }); + } + + QueryBuilder idBetween( + Id lowerId, + Id upperId, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(IdWhereClause.between( + lower: lowerId, + includeLower: includeLower, + upper: upperId, + includeUpper: includeUpper, + )); + }); + } + + QueryBuilder nameIsNull() { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(IndexWhereClause.equalTo( + indexName: r'name', + value: [null], + )); + }); + } + + QueryBuilder nameIsNotNull() { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(IndexWhereClause.between( + indexName: r'name', + lower: [null], + includeLower: false, + upper: [], + )); + }); + } + + QueryBuilder nameEqualTo(String? name) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(IndexWhereClause.equalTo( + indexName: r'name', + value: [name], + )); + }); + } + + QueryBuilder nameNotEqualTo(String? name) { + return QueryBuilder.apply(this, (query) { + if (query.whereSort == Sort.asc) { + return query + .addWhereClause(IndexWhereClause.between( + indexName: r'name', + lower: [], + upper: [name], + includeUpper: false, + )) + .addWhereClause(IndexWhereClause.between( + indexName: r'name', + lower: [name], + includeLower: false, + upper: [], + )); + } else { + return query + .addWhereClause(IndexWhereClause.between( + indexName: r'name', + lower: [name], + includeLower: false, + upper: [], + )) + .addWhereClause(IndexWhereClause.between( + indexName: r'name', + lower: [], + upper: [name], + includeUpper: false, + )); + } + }); + } +} + +extension PersonQueryFilter on QueryBuilder { + QueryBuilder idEqualTo(Id value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'id', + value: value, + )); + }); + } + + QueryBuilder idGreaterThan( + Id value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'id', + value: value, + )); + }); + } + + QueryBuilder idLessThan( + Id value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'id', + value: value, + )); + }); + } + + QueryBuilder idBetween( + Id lower, + Id upper, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'id', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + )); + }); + } + + QueryBuilder nameIsNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNull( + property: r'name', + )); + }); + } + + QueryBuilder nameIsNotNull() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(const FilterCondition.isNotNull( + property: r'name', + )); + }); + } + + QueryBuilder nameEqualTo( + String? value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'name', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder nameGreaterThan( + String? value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'name', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder nameLessThan( + String? value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'name', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder nameBetween( + String? lower, + String? upper, { + bool includeLower = true, + bool includeUpper = true, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'name', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder nameStartsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.startsWith( + property: r'name', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder nameEndsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.endsWith( + property: r'name', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder nameContains(String value, + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.contains( + property: r'name', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder nameMatches( + String pattern, + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.matches( + property: r'name', + wildcard: pattern, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder nameIsEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'name', + value: '', + )); + }); + } + + QueryBuilder nameIsNotEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + property: r'name', + value: '', + )); + }); + } +} + +extension PersonQueryObject on QueryBuilder {} + +extension PersonQueryLinks on QueryBuilder {} + +extension PersonQuerySortBy on QueryBuilder { + QueryBuilder sortByName() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'name', Sort.asc); + }); + } + + QueryBuilder sortByNameDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'name', Sort.desc); + }); + } +} + +extension PersonQuerySortThenBy on QueryBuilder { + QueryBuilder thenById() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'id', Sort.asc); + }); + } + + QueryBuilder thenByIdDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'id', Sort.desc); + }); + } + + QueryBuilder thenByName() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'name', Sort.asc); + }); + } + + QueryBuilder thenByNameDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'name', Sort.desc); + }); + } +} + +extension PersonQueryWhereDistinct on QueryBuilder { + QueryBuilder distinctByName( + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'name', caseSensitive: caseSensitive); + }); + } +} + +extension PersonQueryProperty on QueryBuilder { + QueryBuilder idProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'id'); + }); + } + + QueryBuilder nameProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'name'); + }); + } +} diff --git a/isar/test/sentry_isar_collection_test.dart b/isar/test/sentry_isar_collection_test.dart new file mode 100644 index 0000000000..c3286a2971 --- /dev/null +++ b/isar/test/sentry_isar_collection_test.dart @@ -0,0 +1,476 @@ +import 'dart:io'; +import 'dart:typed_data'; + +import 'package:flutter_test/flutter_test.dart'; +import 'package:isar/isar.dart'; +import 'package:mockito/mockito.dart'; +import 'package:sentry/sentry.dart'; +import 'package:sentry_isar/sentry_isar.dart'; +import 'package:sentry_isar/src/sentry_isar.dart'; + +import 'package:sentry/src/sentry_tracer.dart'; + +import 'mocks/mocks.mocks.dart'; +import 'person.dart'; + +void main() { + void verifySpan( + String description, + SentrySpan? span, + ) { + expect(span?.context.operation, SentryIsar.dbOp); + expect(span?.context.description, description); + expect(span?.status, SpanStatus.ok()); + // ignore: invalid_use_of_internal_member + expect(span?.origin, SentryTraceOrigins.autoDbIsarCollection); + expect(span?.data[SentryIsar.dbNameKey], Fixture.dbName); + expect(span?.data[SentryIsar.dbCollectionKey], 'Person'); + } + + void verifyErrorSpan(String description, SentrySpan? span, Exception error) { + expect(span?.context.operation, SentryIsar.dbOp); + expect(span?.context.description, description); + expect(span?.status, SpanStatus.internalError()); + // ignore: invalid_use_of_internal_member + expect(span?.origin, SentryTraceOrigins.autoDbIsarCollection); + expect(span?.throwable, error); + } + + group('add spans', () { + late Fixture fixture; + + setUp(() async { + fixture = Fixture(); + + when(fixture.hub.options).thenReturn(fixture.options); + when(fixture.hub.getSpan()).thenReturn(fixture.tracer); + + await fixture.setUp(); + }); + + tearDown(() async { + await fixture.tearDown(); + }); + + test('clear adds span', () async { + await fixture.sentryIsar.writeTxn(() async { + await fixture.getSut().clear(); + }); + final span = fixture.getCreatedSpan(); + verifySpan('clear', span); + }); + + test('count adds span', () async { + await fixture.sentryIsar.writeTxn(() async { + await fixture.getSut().count(); + }); + final span = fixture.getCreatedSpan(); + verifySpan('count', span); + }); + + test('delete adds span', () async { + await fixture.sentryIsar.writeTxn(() async { + await fixture.getSut().delete(0); + }); + final span = fixture.getCreatedSpan(); + verifySpan('delete', span); + }); + + test('deleteAll adds span', () async { + await fixture.sentryIsar.writeTxn(() async { + await fixture.getSut().deleteAll([0]); + }); + final span = fixture.getCreatedSpan(); + verifySpan('deleteAll', span); + }); + + test('deleteAllByIndex adds span', () async { + await fixture.sentryIsar.writeTxn(() async { + await fixture.getSut().putByIndex('name', Person()..name = 'Joe'); + await fixture.getSut().deleteAllByIndex('name', []); + }); + final span = fixture.getCreatedSpan(); + verifySpan('deleteAllByIndex', span); + }); + + test('deleteByIndex adds span', () async { + await fixture.sentryIsar.writeTxn(() async { + await fixture.getSut().putByIndex('name', Person()..name = 'Joe'); + await fixture.getSut().deleteByIndex('name', []); + }); + final span = fixture.getCreatedSpan(); + verifySpan('deleteByIndex', span); + }); + + test('get adds span', () async { + await fixture.sentryIsar.writeTxn(() async { + await fixture.getSut().get(1); + }); + final span = fixture.getCreatedSpan(); + verifySpan('get', span); + }); + + test('getAll adds span', () async { + await fixture.sentryIsar.writeTxn(() async { + await fixture.getSut().getAll([1]); + }); + final span = fixture.getCreatedSpan(); + verifySpan('getAll', span); + }); + + test('getAllByIndex adds span', () async { + await fixture.sentryIsar.writeTxn(() async { + await fixture.getSut().getAllByIndex('name', []); + }); + final span = fixture.getCreatedSpan(); + verifySpan('getAllByIndex', span); + }); + + test('getByIndex adds span', () async { + await fixture.sentryIsar.writeTxn(() async { + await fixture.getSut().getByIndex('name', []); + }); + final span = fixture.getCreatedSpan(); + verifySpan('getByIndex', span); + }); + + test('getSize adds span', () async { + await fixture.sentryIsar.writeTxn(() async { + await fixture.getSut().getSize(); + }); + final span = fixture.getCreatedSpan(); + verifySpan('getSize', span); + }); + + test('importJson adds span', () async { + await fixture.sentryIsar.writeTxn(() async { + await fixture.getSut().importJson([]); + }); + final span = fixture.getCreatedSpan(); + verifySpan('importJson', span); + }); + + test('importJsonRaw adds span', () async { + await fixture.sentryIsar.writeTxn(() async { + final query = fixture.getSut().buildQuery(); + Uint8List jsonRaw = Uint8List.fromList([]); + await query.exportJsonRaw((raw) { + jsonRaw = Uint8List.fromList(raw); + }); + await fixture.getSut().importJsonRaw(jsonRaw); + }); + final span = fixture.getCreatedSpan(); + verifySpan('importJsonRaw', span); + }); + + test('put adds span', () async { + await fixture.sentryIsar.writeTxn(() async { + await fixture.getSut().put(Person()); + }); + final span = fixture.getCreatedSpan(); + verifySpan('put', span); + }); + + test('putAll adds span', () async { + await fixture.sentryIsar.writeTxn(() async { + await fixture.getSut().putAll([Person()]); + }); + final span = fixture.getCreatedSpan(); + verifySpan('putAll', span); + }); + + test('putAllByIndex adds span', () async { + await fixture.sentryIsar.writeTxn(() async { + await fixture.getSut().putAllByIndex('name', [Person()]); + }); + final span = fixture.getCreatedSpan(); + verifySpan('putAllByIndex', span); + }); + + test('putByIndex adds span', () async { + await fixture.sentryIsar.writeTxn(() async { + await fixture.getSut().putByIndex('name', Person()); + }); + final span = fixture.getCreatedSpan(); + verifySpan('putByIndex', span); + }); + }); + + group('add error spans', () { + late Fixture fixture; + + setUp(() async { + fixture = Fixture(); + + when(fixture.hub.options).thenReturn(fixture.options); + when(fixture.hub.getSpan()).thenReturn(fixture.tracer); + when(fixture.isarCollection.name).thenReturn(Fixture.dbCollection); + + await fixture.setUp(); + }); + + tearDown(() async { + await fixture.tearDown(); + }); + + test('throwing clear adds error span', () async { + when(fixture.isarCollection.clear()).thenThrow(fixture.exception); + try { + await fixture.getSut(injectMock: true).clear(); + } catch (error) { + expect(error, fixture.exception); + } + verifyErrorSpan('clear', fixture.getCreatedSpan(), fixture.exception); + }); + + test('throwing count adds error span', () async { + when(fixture.isarCollection.count()).thenThrow(fixture.exception); + try { + await fixture.getSut(injectMock: true).count(); + } catch (error) { + expect(error, fixture.exception); + } + verifyErrorSpan('count', fixture.getCreatedSpan(), fixture.exception); + }); + + test('throwing delete adds error span', () async { + when(fixture.isarCollection.delete(any)).thenThrow(fixture.exception); + try { + await fixture.getSut(injectMock: true).delete(0); + } catch (error) { + expect(error, fixture.exception); + } + verifyErrorSpan('delete', fixture.getCreatedSpan(), fixture.exception); + }); + + test('throwing deleteAll adds error span', () async { + when(fixture.isarCollection.deleteAll(any)).thenThrow(fixture.exception); + try { + await fixture.getSut(injectMock: true).deleteAll([0]); + } catch (error) { + expect(error, fixture.exception); + } + verifyErrorSpan('deleteAll', fixture.getCreatedSpan(), fixture.exception); + }); + + test('throwing deleteAllByIndex adds error span', () async { + when(fixture.isarCollection.deleteAllByIndex(any, any)) + .thenThrow(fixture.exception); + try { + await fixture.getSut(injectMock: true).deleteAllByIndex('name', []); + } catch (error) { + expect(error, fixture.exception); + } + verifyErrorSpan( + 'deleteAllByIndex', + fixture.getCreatedSpan(), + fixture.exception, + ); + }); + + test('throwing deleteByIndex adds error span', () async { + when(fixture.isarCollection.deleteByIndex(any, any)) + .thenThrow(fixture.exception); + try { + await fixture.getSut(injectMock: true).deleteByIndex('name', []); + } catch (error) { + expect(error, fixture.exception); + } + verifyErrorSpan( + 'deleteByIndex', + fixture.getCreatedSpan(), + fixture.exception, + ); + }); + + test('throwing get adds error span', () async { + when(fixture.isarCollection.get(any)).thenThrow(fixture.exception); + try { + await fixture.getSut(injectMock: true).get(1); + } catch (error) { + expect(error, fixture.exception); + } + verifyErrorSpan('get', fixture.getCreatedSpan(), fixture.exception); + }); + + test('throwing getAll adds error span', () async { + when(fixture.isarCollection.getAll(any)).thenThrow(fixture.exception); + try { + await fixture.getSut(injectMock: true).getAll([1]); + } catch (error) { + expect(error, fixture.exception); + } + verifyErrorSpan('getAll', fixture.getCreatedSpan(), fixture.exception); + }); + + test('throwing getAllByIndex adds error span', () async { + when(fixture.isarCollection.getAllByIndex(any, any)) + .thenThrow(fixture.exception); + try { + await fixture.getSut(injectMock: true).getAllByIndex('name', []); + } catch (error) { + expect(error, fixture.exception); + } + verifyErrorSpan( + 'getAllByIndex', + fixture.getCreatedSpan(), + fixture.exception, + ); + }); + + test('throwing getByIndex adds error span', () async { + when(fixture.isarCollection.getByIndex(any, any)) + .thenThrow(fixture.exception); + try { + await fixture.getSut(injectMock: true).getByIndex('name', []); + } catch (error) { + expect(error, fixture.exception); + } + verifyErrorSpan( + 'getByIndex', + fixture.getCreatedSpan(), + fixture.exception, + ); + }); + + test('throwing getSize adds error span', () async { + when(fixture.isarCollection.getSize()).thenThrow(fixture.exception); + try { + await fixture.getSut(injectMock: true).getSize(); + } catch (error) { + expect(error, fixture.exception); + } + verifyErrorSpan('getSize', fixture.getCreatedSpan(), fixture.exception); + }); + + test('throwing importJson adds error span', () async { + when(fixture.isarCollection.importJson(any)).thenThrow(fixture.exception); + try { + await fixture.getSut(injectMock: true).importJson([]); + } catch (error) { + expect(error, fixture.exception); + } + verifyErrorSpan( + 'importJson', + fixture.getCreatedSpan(), + fixture.exception, + ); + }); + + test('throwing importJsonRaw adds error span', () async { + when(fixture.isarCollection.importJsonRaw(any)) + .thenThrow(fixture.exception); + try { + await fixture + .getSut(injectMock: true) + .importJsonRaw(Uint8List.fromList([])); + } catch (error) { + expect(error, fixture.exception); + } + verifyErrorSpan( + 'importJsonRaw', + fixture.getCreatedSpan(), + fixture.exception, + ); + }); + + test('throwing put adds error span', () async { + when(fixture.isarCollection.put(any)).thenThrow(fixture.exception); + try { + await fixture.getSut(injectMock: true).put(Person()); + } catch (error) { + expect(error, fixture.exception); + } + verifyErrorSpan('put', fixture.getCreatedSpan(), fixture.exception); + }); + + test('throwing putAll adds error span', () async { + when(fixture.isarCollection.putAll(any)).thenThrow(fixture.exception); + try { + await fixture.getSut(injectMock: true).putAll([Person()]); + } catch (error) { + expect(error, fixture.exception); + } + verifyErrorSpan('putAll', fixture.getCreatedSpan(), fixture.exception); + }); + + test('throwing putAllByIndex adds error span', () async { + when(fixture.isarCollection.putAllByIndex(any, any)) + .thenThrow(fixture.exception); + try { + await fixture + .getSut(injectMock: true) + .putAllByIndex('name', [Person()]); + } catch (error) { + expect(error, fixture.exception); + } + verifyErrorSpan( + 'putAllByIndex', + fixture.getCreatedSpan(), + fixture.exception, + ); + }); + + test('throwing putByIndex adds error span', () async { + when(fixture.isarCollection.putByIndex(any, any)) + .thenThrow(fixture.exception); + try { + await fixture.getSut(injectMock: true).putByIndex('name', Person()); + } catch (error) { + expect(error, fixture.exception); + } + verifyErrorSpan( + 'putByIndex', + fixture.getCreatedSpan(), + fixture.exception, + ); + }); + }); +} + +class Fixture { + final options = SentryOptions(); + final hub = MockHub(); + final isarCollection = MockIsarCollection(); + + static final dbName = 'people-isar'; + static final dbCollection = 'Person'; + final exception = Exception('fixture-exception'); + + final _context = SentryTransactionContext('name', 'operation'); + late final tracer = SentryTracer(_context, hub); + late Isar sentryIsar; + + Future setUp() async { + // Make sure to use flutter test -j 1 to avoid tests running in parallel. This would break the automatic download. + await Isar.initializeIsarCore(download: true); + sentryIsar = await SentryIsar.open( + [PersonSchema], + directory: Directory.systemTemp.path, + name: dbName, + hub: hub, + ); + } + + Future tearDown() async { + try { + // ignore: invalid_use_of_protected_member + sentryIsar.requireOpen(); + await sentryIsar.close(); + } catch (_) { + // Don't close multiple times + } + } + + IsarCollection getSut({bool injectMock = false}) { + if (injectMock) { + return SentryIsarCollection(isarCollection, hub, sentryIsar.name); + } else { + return sentryIsar.collection(); + } + } + + SentrySpan? getCreatedSpan() { + return tracer.children.last; + } +} diff --git a/isar/test/sentry_isar_test.dart b/isar/test/sentry_isar_test.dart new file mode 100644 index 0000000000..70cc23c832 --- /dev/null +++ b/isar/test/sentry_isar_test.dart @@ -0,0 +1,277 @@ +@TestOn('vm') + +import 'dart:io'; + +import 'package:flutter_test/flutter_test.dart'; +import 'package:isar/isar.dart'; +import 'package:mockito/mockito.dart'; +import 'package:sentry/sentry.dart'; +import 'package:sentry_isar/src/sentry_isar.dart'; + +import 'package:sentry/src/sentry_tracer.dart'; +import 'package:sentry_isar/src/version.dart'; + +import 'mocks/mocks.mocks.dart'; +import 'person.dart'; + +void main() { + void verifySpan( + String description, + SentrySpan? span, { + bool checkName = false, + }) { + expect(span?.context.operation, SentryIsar.dbOp); + expect(span?.context.description, description); + expect(span?.status, SpanStatus.ok()); + // ignore: invalid_use_of_internal_member + expect(span?.origin, SentryTraceOrigins.autoDbIsar); + if (checkName) { + expect(span?.data[SentryIsar.dbNameKey], Fixture.dbName); + } + } + + void verifyErrorSpan(String description, SentrySpan? span, Exception error) { + expect(span?.context.operation, SentryIsar.dbOp); + expect(span?.context.description, description); + expect(span?.status, SpanStatus.internalError()); + // ignore: invalid_use_of_internal_member + expect(span?.origin, SentryTraceOrigins.autoDbIsar); + expect(span?.throwable, error); + } + + group('add spans', () { + late Fixture fixture; + + setUp(() async { + fixture = Fixture(); + + when(fixture.hub.options).thenReturn(fixture.options); + when(fixture.hub.getSpan()).thenReturn(fixture.tracer); + + await fixture.setUp(); + }); + + tearDown(() async { + await fixture.tearDown(); + }); + + test('open adds span', () async { + final span = fixture.getCreatedSpan(); + verifySpan('open', span, checkName: true); + }); + + test('clear adds span', () async { + await fixture.sut.writeTxn(() async { + await fixture.sut.clear(); + }); + final span = fixture.getCreatedSpan(); + verifySpan('clear', span, checkName: true); + }); + + test('close adds span', () async { + await fixture.sut.close(); + final span = fixture.getCreatedSpan(); + verifySpan('close', span, checkName: true); + }); + + test('copyToFile adds span', () async { + await fixture.sut.copyToFile(fixture.copyPath); + final span = fixture.getCreatedSpan(); + verifySpan('copyToFile', span, checkName: true); + }); + + test('getSize adds span', () async { + await fixture.sut.getSize(); + final span = fixture.getCreatedSpan(); + verifySpan('getSize', span, checkName: true); + }); + + test('txn adds span', () async { + await fixture.sut.txn(() async {}); + final span = fixture.getCreatedSpan(); + verifySpan('txn', span, checkName: true); + }); + + test('writeTxn adds span', () async { + await fixture.sut.writeTxn(() async {}); + final span = fixture.getCreatedSpan(); + verifySpan('writeTxn', span, checkName: true); + }); + }); + + group('add error spans', () { + late Fixture fixture; + + setUp(() async { + fixture = Fixture(); + + when(fixture.hub.options).thenReturn(fixture.options); + when(fixture.hub.getSpan()).thenReturn(fixture.tracer); + when(fixture.isar.close()).thenAnswer((_) async { + return true; + }); + when(fixture.isar.name).thenReturn(Fixture.dbName); + + await fixture.setUp(injectMock: true); + }); + + tearDown(() async { + await fixture.tearDown(); + }); + + test('throwing close adds error span', () async { + when(fixture.isar.close()).thenThrow(fixture.exception); + try { + await fixture.sut.close(); + } catch (error) { + expect(error, fixture.exception); + } + verifyErrorSpan('close', fixture.getCreatedSpan(), fixture.exception); + }); + + test('throwing clear adds error span', () async { + when(fixture.isar.clear()).thenThrow(fixture.exception); + try { + await fixture.sut.clear(); + } catch (error) { + expect(error, fixture.exception); + } + verifyErrorSpan('clear', fixture.getCreatedSpan(), fixture.exception); + }); + + test('throwing copyToFile adds error span', () async { + when(fixture.isar.copyToFile(any)).thenThrow(fixture.exception); + try { + await fixture.sut.copyToFile(fixture.copyPath); + } catch (error) { + expect(error, fixture.exception); + } + verifyErrorSpan( + 'copyToFile', + fixture.getCreatedSpan(), + fixture.exception, + ); + }); + + test('throwing getSize adds error span', () async { + when(fixture.isar.getSize()).thenThrow(fixture.exception); + try { + await fixture.sut.getSize(); + } catch (error) { + expect(error, fixture.exception); + } + verifyErrorSpan('getSize', fixture.getCreatedSpan(), fixture.exception); + }); + + test('throwing txn adds error span', () async { + param() async {} + when(fixture.isar.txn(param)).thenThrow(fixture.exception); + try { + await fixture.sut.txn(param); + } catch (error) { + expect(error, fixture.exception); + } + verifyErrorSpan('txn', fixture.getCreatedSpan(), fixture.exception); + }); + + test('throwing writeTxn adds error span', () async { + param() async {} + when(fixture.isar.writeTxn(param)).thenThrow(fixture.exception); + try { + await fixture.sut.writeTxn(param); + } catch (error) { + expect(error, fixture.exception); + } + verifyErrorSpan('writeTxn', fixture.getCreatedSpan(), fixture.exception); + }); + }); + + group('integrations', () { + late Fixture fixture; + + setUp(() async { + fixture = Fixture(); + + when(fixture.hub.options).thenReturn(fixture.options); + when(fixture.hub.getSpan()).thenReturn(fixture.tracer); + + await fixture.setUp(); + }); + + tearDown(() async { + await fixture.tearDown(); + }); + + test('adds integration', () { + expect( + fixture.options.sdk.integrations.contains('SentryIsarTracing'), + true, + ); + }); + + test('adds package', () { + expect( + fixture.options.sdk.packages.any( + (element) => + element.name == packageName && element.version == sdkVersion, + ), + true, + ); + }); + }); +} + +class Fixture { + final options = SentryOptions(); + final hub = MockHub(); + final isar = MockIsar(); + + static final dbName = 'people-isar'; + final exception = Exception('fixture-exception'); + final copyPath = '${Directory.systemTemp.path}/copy'; + + final _context = SentryTransactionContext('name', 'operation'); + late final tracer = SentryTracer(_context, hub); + late Isar sut; + + Future setUp({bool injectMock = false}) async { + if (injectMock) { + sut = SentryIsar(isar, hub); + } else { + // Make sure to use flutter test -j 1 to avoid tests running in parallel. This would break the automatic download. + await Isar.initializeIsarCore(download: true); + sut = await SentryIsar.open( + [PersonSchema], + directory: Directory.systemTemp.path, + name: dbName, + hub: hub, + ); + } + await deleteCopyPath(); + } + + Future tearDown() async { + try { + // ignore: invalid_use_of_protected_member + sut.requireOpen(); + await sut.close(); + } catch (_) { + // Don't close multiple times + } + } + + Isar getSut() { + return sut; + } + + SentrySpan? getCreatedSpan() { + return tracer.children.last; + } + + Future deleteCopyPath() async { + final file = File(copyPath); + if (await file.exists()) { + await file.delete(recursive: true); + } + } +} diff --git a/scripts/bump-version.sh b/scripts/bump-version.sh index d3e8fae081..dedd3e1b66 100755 --- a/scripts/bump-version.sh +++ b/scripts/bump-version.sh @@ -10,7 +10,7 @@ NEW_VERSION="${2}" echo "Current version: ${OLD_VERSION}" echo "Bumping version: ${NEW_VERSION}" -for pkg in {dart,flutter,logging,dio,file,sqflite,drift,hive}; do +for pkg in {dart,flutter,logging,dio,file,sqflite,drift,hive,isar}; do # Bump version in pubspec.yaml perl -pi -e "s/^version: .*/version: $NEW_VERSION/" $pkg/pubspec.yaml # Bump sentry dependency version in pubspec.yaml From 3ad66e4789a5212fa687083e41baaaecb74bac9c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 21 Dec 2023 12:18:23 +0100 Subject: [PATCH 035/237] Bump flutter_lints from 2.0.3 to 3.0.0 in /flutter (#1698) * Bump flutter_lints from 2.0.3 to 3.0.0 in /flutter Bumps [flutter_lints](https://github.com/flutter/packages/tree/main/packages) from 2.0.3 to 3.0.0. - [Release notes](https://github.com/flutter/packages/releases) - [Commits](https://github.com/flutter/packages/commits/pigeon-v3.0.0/packages) --- updated-dependencies: - dependency-name: flutter_lints dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] * Satisfy analyzer * Satisfy dart analyzer --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor --- flutter/lib/sentry_flutter.dart | 4 +++- flutter/lib/src/flutter_sentry_attachment.dart | 6 ++---- flutter/lib/src/navigation/sentry_navigator_observer.dart | 6 ++---- flutter/lib/src/screenshot/sentry_screenshot_widget.dart | 3 +-- flutter/lib/src/sentry_flutter_options.dart | 3 +-- .../user_interaction/sentry_user_interaction_widget.dart | 4 ++-- flutter/pubspec.yaml | 2 +- .../sentry_user_interaction_widget_test.dart | 6 +++--- flutter/test/view_hierarchy/sentry_tree_walker_test.dart | 2 +- .../view_hierarchy/view_hierarchy_event_processor_test.dart | 2 +- 10 files changed, 17 insertions(+), 21 deletions(-) diff --git a/flutter/lib/sentry_flutter.dart b/flutter/lib/sentry_flutter.dart index c30ca1f5ad..6760e99efb 100644 --- a/flutter/lib/sentry_flutter.dart +++ b/flutter/lib/sentry_flutter.dart @@ -1,5 +1,7 @@ -// ignore: invalid_export_of_internal_element /// A Flutter client for Sentry.io crash reporting. +library sentry_flutter; + +// ignore: invalid_export_of_internal_element export 'package:sentry/sentry.dart'; export 'src/integrations/load_release_integration.dart'; diff --git a/flutter/lib/src/flutter_sentry_attachment.dart b/flutter/lib/src/flutter_sentry_attachment.dart index 83b75c20bd..2e8d57927a 100644 --- a/flutter/lib/src/flutter_sentry_attachment.dart +++ b/flutter/lib/src/flutter_sentry_attachment.dart @@ -16,8 +16,8 @@ class FlutterSentryAttachment extends SentryAttachment { String? filename, AssetBundle? bundle, String? type, - String? contentType, - bool? addToTransactions, + super.contentType, + super.addToTransactions, }) : super.fromLoader( loader: () async { final data = await (bundle ?? rootBundle).load(key); @@ -28,7 +28,5 @@ class FlutterSentryAttachment extends SentryAttachment { ? Uri.parse(key).pathSegments.last : 'unknown'), attachmentType: type, - contentType: contentType, - addToTransactions: addToTransactions, ); } diff --git a/flutter/lib/src/navigation/sentry_navigator_observer.dart b/flutter/lib/src/navigation/sentry_navigator_observer.dart index bfe1c0c6a2..6893d47aca 100644 --- a/flutter/lib/src/navigation/sentry_navigator_observer.dart +++ b/flutter/lib/src/navigation/sentry_navigator_observer.dart @@ -283,14 +283,12 @@ class RouteObserverBreadcrumb extends Breadcrumb { dynamic fromArgs, String? to, dynamic toArgs, - SentryLevel? level, - DateTime? timestamp, + super.level, + super.timestamp, Map? data, }) : super( category: _navigationKey, type: _navigationKey, - level: level, - timestamp: timestamp, data: { 'state': navigationType, if (from != null) 'from': from, diff --git a/flutter/lib/src/screenshot/sentry_screenshot_widget.dart b/flutter/lib/src/screenshot/sentry_screenshot_widget.dart index b11b511bb3..b7273b8979 100644 --- a/flutter/lib/src/screenshot/sentry_screenshot_widget.dart +++ b/flutter/lib/src/screenshot/sentry_screenshot_widget.dart @@ -22,8 +22,7 @@ final sentryScreenshotWidgetGlobalKey = /// - You can only have one [SentryScreenshotWidget] widget in your widget tree at all /// times. class SentryScreenshotWidget extends StatefulWidget { - const SentryScreenshotWidget({Key? key, required this.child}) - : super(key: key); + const SentryScreenshotWidget({super.key, required this.child}); final Widget child; diff --git a/flutter/lib/src/sentry_flutter_options.dart b/flutter/lib/src/sentry_flutter_options.dart index 1a71a0d37e..3806397465 100644 --- a/flutter/lib/src/sentry_flutter_options.dart +++ b/flutter/lib/src/sentry_flutter_options.dart @@ -10,8 +10,7 @@ import 'screenshot/sentry_screenshot_quality.dart'; /// Note that some of these options require native Sentry integration, which is /// not available on all platforms. class SentryFlutterOptions extends SentryOptions { - SentryFlutterOptions({String? dsn, PlatformChecker? checker}) - : super(dsn: dsn, checker: checker) { + SentryFlutterOptions({super.dsn, super.checker}) { enableBreadcrumbTrackingForCurrentPlatform(); } diff --git a/flutter/lib/src/user_interaction/sentry_user_interaction_widget.dart b/flutter/lib/src/user_interaction/sentry_user_interaction_widget.dart index f98a919065..94d364899e 100644 --- a/flutter/lib/src/user_interaction/sentry_user_interaction_widget.dart +++ b/flutter/lib/src/user_interaction/sentry_user_interaction_widget.dart @@ -234,10 +234,10 @@ Element? _clickTrackerElement; /// [SentryUserInteractionWidget] as a child of [SentryScreenshotWidget]. class SentryUserInteractionWidget extends StatefulWidget { SentryUserInteractionWidget({ - Key? key, + super.key, required this.child, @internal Hub? hub, - }) : super(key: key) { + }) { _hub = hub ?? HubAdapter(); if (_options?.enableUserInteractionTracing ?? false) { diff --git a/flutter/pubspec.yaml b/flutter/pubspec.yaml index 0e321ab82f..d06f95e31e 100644 --- a/flutter/pubspec.yaml +++ b/flutter/pubspec.yaml @@ -26,7 +26,7 @@ dev_dependencies: sdk: flutter mockito: ^5.1.0 yaml: ^3.1.0 # needed for version match (code and pubspec) - flutter_lints: ^2.0.0 + flutter_lints: ^3.0.0 collection: ^1.16.0 remove_from_coverage: ^2.0.0 flutter_localizations: diff --git a/flutter/test/user_interaction/sentry_user_interaction_widget_test.dart b/flutter/test/user_interaction/sentry_user_interaction_widget_test.dart index 02d1022157..a814bd0b54 100644 --- a/flutter/test/user_interaction/sentry_user_interaction_widget_test.dart +++ b/flutter/test/user_interaction/sentry_user_interaction_widget_test.dart @@ -327,7 +327,7 @@ class Fixture { } class MyApp extends StatelessWidget { - const MyApp({Key? key}) : super(key: key); + const MyApp({super.key}); @override Widget build(BuildContext context) { @@ -340,7 +340,7 @@ class MyApp extends StatelessWidget { } class Page1 extends StatelessWidget { - const Page1({Key? key}) : super(key: key); + const Page1({super.key}); @override Widget build(BuildContext context) { @@ -416,7 +416,7 @@ class Page1 extends StatelessWidget { } class Page2 extends StatelessWidget { - const Page2({Key? key}) : super(key: key); + const Page2({super.key}); @override Widget build(BuildContext context) { diff --git a/flutter/test/view_hierarchy/sentry_tree_walker_test.dart b/flutter/test/view_hierarchy/sentry_tree_walker_test.dart index c2048c3492..52d775529b 100644 --- a/flutter/test/view_hierarchy/sentry_tree_walker_test.dart +++ b/flutter/test/view_hierarchy/sentry_tree_walker_test.dart @@ -172,7 +172,7 @@ bool _findWidget( } class MyApp extends StatelessWidget { - const MyApp({Key? key}) : super(key: key); + const MyApp({super.key}); @override Widget build(BuildContext context) { diff --git a/flutter/test/view_hierarchy/view_hierarchy_event_processor_test.dart b/flutter/test/view_hierarchy/view_hierarchy_event_processor_test.dart index 537b2cd9c4..6900ba5589 100644 --- a/flutter/test/view_hierarchy/view_hierarchy_event_processor_test.dart +++ b/flutter/test/view_hierarchy/view_hierarchy_event_processor_test.dart @@ -107,7 +107,7 @@ class Fixture { } class MyApp extends StatelessWidget { - const MyApp({Key? key}) : super(key: key); + const MyApp({super.key}); @override Widget build(BuildContext context) { From 011829598b3e6eaa26f901a3fedccfd0de06cb87 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 21 Dec 2023 13:08:41 +0100 Subject: [PATCH 036/237] chore: update metrics/flutter.properties to 3.16.5 (#1793) Co-authored-by: GitHub --- metrics/flutter.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/metrics/flutter.properties b/metrics/flutter.properties index a0e5a0f324..8ec4606076 100644 --- a/metrics/flutter.properties +++ b/metrics/flutter.properties @@ -1,2 +1,2 @@ -version = 3.16.2 +version = 3.16.5 repo = https://github.com/flutter/flutter From bc2976867b4472f1f1135d60b70bcca7d4d4eb39 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 21 Dec 2023 13:37:12 +0100 Subject: [PATCH 037/237] Bump lints from 2.1.1 to 3.0.0 in /dart (#1695) * Bump lints from 2.1.1 to 3.0.0 in /dart Bumps [lints](https://github.com/dart-lang/lints) from 2.1.1 to 3.0.0. - [Release notes](https://github.com/dart-lang/lints/releases) - [Changelog](https://github.com/dart-lang/lints/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/lints/compare/v2.1.1...v3.0.0) --- updated-dependencies: - dependency-name: lints dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] * update --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: GIancarlo Buenaflor --- dart/lib/sentry.dart | 2 ++ dart/lib/src/protocol/sentry_transaction.dart | 35 +++++++------------ .../io_sentry_attachment.dart | 6 ++-- dart/lib/src/sentry_transaction_context.dart | 15 +++----- dart/lib/src/utils/sample_rate_format.dart | 1 + dart/pubspec.yaml | 2 +- 6 files changed, 23 insertions(+), 38 deletions(-) diff --git a/dart/lib/sentry.dart b/dart/lib/sentry.dart index 9d06bb7e2a..987e1f014a 100644 --- a/dart/lib/sentry.dart +++ b/dart/lib/sentry.dart @@ -3,6 +3,8 @@ // found in the LICENSE file. /// A pure Dart client for Sentry.io crash reporting. +library sentry_dart; + export 'src/run_zoned_guarded_integration.dart'; export 'src/hub.dart'; // useful for tests diff --git a/dart/lib/src/protocol/sentry_transaction.dart b/dart/lib/src/protocol/sentry_transaction.dart index 986169ce46..e00fa23355 100644 --- a/dart/lib/src/protocol/sentry_transaction.dart +++ b/dart/lib/src/protocol/sentry_transaction.dart @@ -17,45 +17,34 @@ class SentryTransaction extends SentryEvent { SentryTransaction( this.tracer, { - SentryId? eventId, + super.eventId, DateTime? timestamp, - String? platform, - String? serverName, - String? release, - String? dist, - String? environment, + super.platform, + super.serverName, + super.release, + super.dist, + super.environment, String? transaction, dynamic throwable, Map? tags, @Deprecated( 'Additional Data is deprecated in favor of structured [Contexts] and should be avoided when possible') Map? extra, - SentryUser? user, - Contexts? contexts, - List? breadcrumbs, - SdkVersion? sdk, - SentryRequest? request, + super.user, + super.contexts, + super.breadcrumbs, + super.sdk, + super.request, String? type, Map? measurements, SentryTransactionInfo? transactionInfo, }) : super( - eventId: eventId, timestamp: timestamp ?? tracer.endTimestamp, - platform: platform, - serverName: serverName, - release: release, - dist: dist, - environment: environment, transaction: transaction ?? tracer.name, throwable: throwable ?? tracer.throwable, tags: tags ?? tracer.tags, // ignore: deprecated_member_use_from_same_package extra: extra ?? tracer.data, - user: user, - contexts: contexts, - breadcrumbs: breadcrumbs, - sdk: sdk, - request: request, type: _type, ) { startTimestamp = tracer.startTimestamp; @@ -64,7 +53,7 @@ class SentryTransaction extends SentryEvent { spans = tracer.children; this.measurements = measurements ?? {}; - this.contexts.trace = spanContext.toTraceContext( + contexts.trace = spanContext.toTraceContext( sampled: tracer.samplingDecision?.sampled, status: tracer.status, ); diff --git a/dart/lib/src/sentry_attachment/io_sentry_attachment.dart b/dart/lib/src/sentry_attachment/io_sentry_attachment.dart index a1e2585556..ae07b51508 100644 --- a/dart/lib/src/sentry_attachment/io_sentry_attachment.dart +++ b/dart/lib/src/sentry_attachment/io_sentry_attachment.dart @@ -24,12 +24,10 @@ class IoSentryAttachment extends SentryAttachment { IoSentryAttachment.fromFile( File file, { String? filename, - String? attachmentType, - String? contentType, + super.attachmentType, + super.contentType, }) : super.fromLoader( loader: () => file.readAsBytes(), filename: filename ?? file.uri.pathSegments.last, - attachmentType: attachmentType, - contentType: contentType, ); } diff --git a/dart/lib/src/sentry_transaction_context.dart b/dart/lib/src/sentry_transaction_context.dart index 66024459f5..32ab0324b7 100644 --- a/dart/lib/src/sentry_transaction_context.dart +++ b/dart/lib/src/sentry_transaction_context.dart @@ -15,21 +15,16 @@ class SentryTransactionContext extends SentrySpanContext { SentryTransactionContext( this.name, String operation, { - String? description, + super.description, this.parentSamplingDecision, - SentryId? traceId, - SpanId? spanId, - SpanId? parentSpanId, + super.traceId, + super.spanId, + super.parentSpanId, this.transactionNameSource, this.samplingDecision, - String? origin, + super.origin, }) : super( operation: operation, - description: description, - traceId: traceId, - spanId: spanId, - parentSpanId: parentSpanId, - origin: origin, ); factory SentryTransactionContext.fromSentryTrace( diff --git a/dart/lib/src/utils/sample_rate_format.dart b/dart/lib/src/utils/sample_rate_format.dart index 4abb79edd8..e69163f30b 100644 --- a/dart/lib/src/utils/sample_rate_format.dart +++ b/dart/lib/src/utils/sample_rate_format.dart @@ -1,3 +1,4 @@ +// ignore: dangling_library_doc_comments /// Code ported & adapted from `intl` package /// https://pub.dev/packages/intl /// diff --git a/dart/pubspec.yaml b/dart/pubspec.yaml index e3207ffda2..2580a618d3 100644 --- a/dart/pubspec.yaml +++ b/dart/pubspec.yaml @@ -20,7 +20,7 @@ dependencies: dev_dependencies: build_runner: ^2.4.2 mockito: ^5.1.0 - lints: ^2.0.0 + lints: ^3.0.0 test: ^1.21.1 yaml: ^3.1.0 # needed for version match (code and pubspec) collection: ^1.16.0 From 7ea39312b849fbdd14d0f2e50e957624a562b45d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 21 Dec 2023 15:35:56 +0100 Subject: [PATCH 038/237] build(deps): bump reactivecircus/android-emulator-runner (#1779) Bumps [reactivecircus/android-emulator-runner](https://github.com/reactivecircus/android-emulator-runner) from 2.28.0 to 2.29.0. - [Release notes](https://github.com/reactivecircus/android-emulator-runner/releases) - [Changelog](https://github.com/ReactiveCircus/android-emulator-runner/blob/main/CHANGELOG.md) - [Commits](https://github.com/reactivecircus/android-emulator-runner/compare/d94c3fbe4fe6a29e4a5ba47c12fb47677c73656b...99a4aac18b4df9b3af66c4a1f04c1f23fa10c270) --- updated-dependencies: - dependency-name: reactivecircus/android-emulator-runner dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor --- .github/workflows/flutter_test.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/flutter_test.yml b/.github/workflows/flutter_test.yml index 3b9e2e3839..29b05e9821 100644 --- a/.github/workflows/flutter_test.yml +++ b/.github/workflows/flutter_test.yml @@ -64,7 +64,7 @@ jobs: - name: create AVD and generate snapshot for caching if: steps.avd-cache.outputs.cache-hit != 'true' - uses: reactivecircus/android-emulator-runner@d94c3fbe4fe6a29e4a5ba47c12fb47677c73656b #pin@v2.28.0 + uses: reactivecircus/android-emulator-runner@99a4aac18b4df9b3af66c4a1f04c1f23fa10c270 #pin@v2.29.0 with: working-directory: ./flutter/example api-level: 31 @@ -81,7 +81,7 @@ jobs: run: flutter build apk --debug - name: launch android emulator & run android native test - uses: reactivecircus/android-emulator-runner@d94c3fbe4fe6a29e4a5ba47c12fb47677c73656b #pin@v2.28.0 + uses: reactivecircus/android-emulator-runner@99a4aac18b4df9b3af66c4a1f04c1f23fa10c270 #pin@v2.29.0 with: working-directory: ./flutter/example/android api-level: 31 @@ -94,7 +94,7 @@ jobs: script: ./gradlew testDebugUnitTest - name: launch android emulator & run android integration test - uses: reactivecircus/android-emulator-runner@d94c3fbe4fe6a29e4a5ba47c12fb47677c73656b #pin@v2.28.0 + uses: reactivecircus/android-emulator-runner@99a4aac18b4df9b3af66c4a1f04c1f23fa10c270 #pin@v2.29.0 with: working-directory: ./flutter/example api-level: 31 From 4be7ec8d5b7076810f84142eb7f6b3b09f562f26 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 27 Dec 2023 12:06:49 +0100 Subject: [PATCH 039/237] build(deps): bump subosito/flutter-action from 2.10.0 to 2.12.0 (#1796) Bumps [subosito/flutter-action](https://github.com/subosito/flutter-action) from 2.10.0 to 2.12.0. - [Release notes](https://github.com/subosito/flutter-action/releases) - [Commits](https://github.com/subosito/flutter-action/compare/v2.10.0...2783a3f08e1baf891508463f8c6653c258246225) --- updated-dependencies: - dependency-name: subosito/flutter-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/isar.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/isar.yml b/.github/workflows/isar.yml index 2484fa56bf..cad3e861c3 100644 --- a/.github/workflows/isar.yml +++ b/.github/workflows/isar.yml @@ -80,7 +80,7 @@ jobs: sudo apt install -y network-manager upower if: matrix.os == 'ubuntu-latest' && matrix.target == 'linux' - - uses: subosito/flutter-action@48cafc24713cca54bbe03cdc3a423187d413aafa # pin@v2.10.0 + - uses: subosito/flutter-action@2783a3f08e1baf891508463f8c6653c258246225 # pin@v2.12.0 with: channel: ${{ matrix.sdk }} From be08ed1118c3890fabac3197bcc4e9650145c8a8 Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Wed, 27 Dec 2023 12:12:14 +0100 Subject: [PATCH 040/237] feat: spotlight support (#1786) * Implement spotlight support (screenshots are currently disabled and removed from the envelope) --- CHANGELOG.md | 2 + dart/lib/sentry.dart | 2 + dart/lib/src/sentry_client.dart | 4 + dart/lib/src/sentry_options.dart | 7 + dart/lib/src/spotlight.dart | 21 +++ dart/lib/src/transport/http_transport.dart | 135 +++--------------- .../http_transport_request_handler.dart | 98 +++++++++++++ .../transport/spotlight_http_transport.dart | 52 +++++++ dart/lib/src/utils/transport_utils.dart | 30 ++++ dart/test/environment_test.dart | 4 +- dart/test/sentry_client_test.dart | 9 ++ dart/test/sentry_options_test.dart | 6 + .../spotlight_http_transport_test.dart | 70 +++++++++ 13 files changed, 322 insertions(+), 118 deletions(-) create mode 100644 dart/lib/src/spotlight.dart create mode 100644 dart/lib/src/transport/http_transport_request_handler.dart create mode 100644 dart/lib/src/transport/spotlight_http_transport.dart create mode 100644 dart/lib/src/utils/transport_utils.dart create mode 100644 dart/test/transport/spotlight_http_transport_test.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index d9051b9e07..71483dab8e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ ### Features +- Add [Spotlight](https://spotlightjs.com/about/) support ([#1786](https://github.com/getsentry/sentry-dart/pull/1786)) + - Set `options.spotlight = Spotlight(enabled: true)` to enable Spotlight - Add `ConnectivityIntegration` for web ([#1765](https://github.com/getsentry/sentry-dart/pull/1765)) - We only get the info if online/offline on web platform. The added breadcrumb is set to either `wifi` or `none`. - APM for isar ([#1726](https://github.com/getsentry/sentry-dart/pull/1726)) diff --git a/dart/lib/sentry.dart b/dart/lib/sentry.dart index 987e1f014a..5419aa45b8 100644 --- a/dart/lib/sentry.dart +++ b/dart/lib/sentry.dart @@ -50,3 +50,5 @@ export 'src/utils/http_header_utils.dart'; export 'src/sentry_trace_origins.dart'; // ignore: invalid_export_of_internal_element export 'src/utils.dart'; +// spotlight debugging +export 'src/spotlight.dart'; diff --git a/dart/lib/src/sentry_client.dart b/dart/lib/src/sentry_client.dart index 62d2072b85..709bda104f 100644 --- a/dart/lib/src/sentry_client.dart +++ b/dart/lib/src/sentry_client.dart @@ -16,6 +16,7 @@ import 'sentry_options.dart'; import 'sentry_stack_trace_factory.dart'; import 'transport/http_transport.dart'; import 'transport/noop_transport.dart'; +import 'transport/spotlight_http_transport.dart'; import 'utils/isolate_utils.dart'; import 'version.dart'; import 'sentry_envelope.dart'; @@ -49,6 +50,9 @@ class SentryClient { final rateLimiter = RateLimiter(options); options.transport = HttpTransport(options, rateLimiter); } + if (options.spotlight.enabled) { + options.transport = SpotlightHttpTransport(options, options.transport); + } return SentryClient._(options); } diff --git a/dart/lib/src/sentry_options.dart b/dart/lib/src/sentry_options.dart index 7d0d18622a..918a5d5758 100644 --- a/dart/lib/src/sentry_options.dart +++ b/dart/lib/src/sentry_options.dart @@ -374,6 +374,13 @@ class SentryOptions { /// Settings this to `false` will set the `level` to [SentryLevel.error]. bool markAutomaticallyCollectedErrorsAsFatal = true; + /// The Spotlight configuration. + /// Disabled by default. + /// ```dart + /// spotlight = Spotlight(enabled: true) + /// ``` + Spotlight spotlight = Spotlight(enabled: false); + SentryOptions({this.dsn, PlatformChecker? checker}) { if (checker != null) { platformChecker = checker; diff --git a/dart/lib/src/spotlight.dart b/dart/lib/src/spotlight.dart new file mode 100644 index 0000000000..b106ed3547 --- /dev/null +++ b/dart/lib/src/spotlight.dart @@ -0,0 +1,21 @@ +import 'platform_checker.dart'; + +/// Spotlight configuration class. +class Spotlight { + /// Whether to enable Spotlight for local development. + bool enabled; + + /// The Spotlight Sidecar URL. + /// Defaults to http://10.0.2.2:8969/stream due to Emulator on Android. + /// Otherwise defaults to http://localhost:8969/stream. + String url; + + Spotlight({required this.enabled, String? url}) + : url = url ?? _defaultSpotlightUrl(); +} + +String _defaultSpotlightUrl() { + return (PlatformChecker().platform.isAndroid + ? 'http://10.0.2.2:8969/stream' + : 'http://localhost:8969/stream'); +} diff --git a/dart/lib/src/transport/http_transport.dart b/dart/lib/src/transport/http_transport.dart index acf0e6cf64..90dd8949ce 100644 --- a/dart/lib/src/transport/http_transport.dart +++ b/dart/lib/src/transport/http_transport.dart @@ -2,11 +2,9 @@ import 'dart:async'; import 'dart:convert'; import 'package:http/http.dart'; +import '../utils/transport_utils.dart'; +import 'http_transport_request_handler.dart'; -import '../client_reports/client_report_recorder.dart'; -import '../client_reports/discard_reason.dart'; -import 'data_category.dart'; -import 'noop_encode.dart' if (dart.library.io) 'encode.dart'; import '../noop_client.dart'; import '../protocol.dart'; import '../sentry_options.dart'; @@ -18,15 +16,9 @@ import 'rate_limiter.dart'; class HttpTransport implements Transport { final SentryOptions _options; - final Dsn _dsn; - final RateLimiter _rateLimiter; - final ClientReportRecorder _recorder; - - late _CredentialBuilder _credentialBuilder; - - final Map _headers; + final HttpTransportRequestHandler _requestHandler; factory HttpTransport(SentryOptions options, RateLimiter rateLimiter) { if (options.httpClient is NoOpClient) { @@ -37,17 +29,8 @@ class HttpTransport implements Transport { } HttpTransport._(this._options, this._rateLimiter) - : _dsn = Dsn.parse(_options.dsn!), - _recorder = _options.recorder, - _headers = _buildHeaders( - _options.platformChecker.isWeb, - _options.sentryClientName, - ) { - _credentialBuilder = _CredentialBuilder( - _dsn, - _options.sentryClientName, - ); - } + : _requestHandler = HttpTransportRequestHandler( + _options, Dsn.parse(_options.dsn!).postUri); @override Future send(SentryEnvelope envelope) async { @@ -57,63 +40,31 @@ class HttpTransport implements Transport { } filteredEnvelope.header.sentAt = _options.clock(); - final streamedRequest = await _createStreamedRequest(filteredEnvelope); + final streamedRequest = + await _requestHandler.createRequest(filteredEnvelope); + final response = await _options.httpClient .send(streamedRequest) .then(Response.fromStream); _updateRetryAfterLimits(response); - if (response.statusCode != 200) { - // body guard to not log the error as it has performance impact to allocate - // the body String. - if (_options.debug) { - _options.logger( - SentryLevel.error, - 'API returned an error, statusCode = ${response.statusCode}, ' - 'body = ${response.body}', - ); - } - - if (response.statusCode >= 400 && response.statusCode != 429) { - _recorder.recordLostEvent( - DiscardReason.networkError, DataCategory.error); - } - - return SentryId.empty(); - } else { - _options.logger( - SentryLevel.debug, - 'Envelope ${envelope.header.eventId ?? "--"} was sent successfully.', - ); - } + TransportUtils.logResponse(_options, envelope, response, target: 'Sentry'); - final eventId = json.decode(response.body)['id']; - if (eventId == null) { - return null; + if (response.statusCode == 200) { + return _parseEventId(response); } - return SentryId.fromId(eventId); + return SentryId.empty(); } - Future _createStreamedRequest( - SentryEnvelope envelope) async { - final streamedRequest = StreamedRequest('POST', _dsn.postUri); - - if (_options.compressPayload) { - final compressionSink = compressInSink(streamedRequest.sink, _headers); - envelope - .envelopeStream(_options) - .listen(compressionSink.add) - .onDone(compressionSink.close); - } else { - envelope - .envelopeStream(_options) - .listen(streamedRequest.sink.add) - .onDone(streamedRequest.sink.close); + SentryId? _parseEventId(Response response) { + try { + final eventId = json.decode(response.body)['id']; + return eventId != null ? SentryId.fromId(eventId) : null; + } catch (e) { + _options.logger(SentryLevel.error, 'Error parsing response: $e'); + return null; } - streamedRequest.headers.addAll(_credentialBuilder.configure(_headers)); - - return streamedRequest; } void _updateRetryAfterLimits(Response response) { @@ -131,51 +82,3 @@ class HttpTransport implements Transport { sentryRateLimitHeader, retryAfterHeader, response.statusCode); } } - -class _CredentialBuilder { - final String _authHeader; - - _CredentialBuilder._(String authHeader) : _authHeader = authHeader; - - factory _CredentialBuilder(Dsn dsn, String sdkIdentifier) { - final authHeader = _buildAuthHeader( - publicKey: dsn.publicKey, - secretKey: dsn.secretKey, - sdkIdentifier: sdkIdentifier, - ); - - return _CredentialBuilder._(authHeader); - } - - static String _buildAuthHeader({ - required String publicKey, - String? secretKey, - required String sdkIdentifier, - }) { - var header = 'Sentry sentry_version=7, sentry_client=$sdkIdentifier, ' - 'sentry_key=$publicKey'; - - if (secretKey != null) { - header += ', sentry_secret=$secretKey'; - } - - return header; - } - - Map configure(Map headers) { - return headers - ..addAll( - {'X-Sentry-Auth': _authHeader}, - ); - } -} - -Map _buildHeaders(bool isWeb, String sdkIdentifier) { - final headers = {'Content-Type': 'application/x-sentry-envelope'}; - // NOTE(lejard_h) overriding user agent on VM and Flutter not sure why - // for web it use browser user agent - if (!isWeb) { - headers['User-Agent'] = sdkIdentifier; - } - return headers; -} diff --git a/dart/lib/src/transport/http_transport_request_handler.dart b/dart/lib/src/transport/http_transport_request_handler.dart new file mode 100644 index 0000000000..4aa50898c5 --- /dev/null +++ b/dart/lib/src/transport/http_transport_request_handler.dart @@ -0,0 +1,98 @@ +import 'dart:async'; + +import 'package:http/http.dart'; +import 'package:meta/meta.dart'; + +import 'noop_encode.dart' if (dart.library.io) 'encode.dart'; +import '../protocol.dart'; +import '../sentry_options.dart'; +import '../sentry_envelope.dart'; + +@internal +class HttpTransportRequestHandler { + final SentryOptions _options; + final Dsn _dsn; + final Map _headers; + final Uri _requestUri; + late _CredentialBuilder _credentialBuilder; + + HttpTransportRequestHandler(this._options, this._requestUri) + : _dsn = Dsn.parse(_options.dsn!), + _headers = _buildHeaders( + _options.platformChecker.isWeb, + _options.sentryClientName, + ) { + _credentialBuilder = _CredentialBuilder( + _dsn, + _options.sentryClientName, + ); + } + + Future createRequest(SentryEnvelope envelope) async { + final streamedRequest = StreamedRequest('POST', _requestUri); + + if (_options.compressPayload) { + final compressionSink = compressInSink(streamedRequest.sink, _headers); + envelope + .envelopeStream(_options) + .listen(compressionSink.add) + .onDone(compressionSink.close); + } else { + envelope + .envelopeStream(_options) + .listen(streamedRequest.sink.add) + .onDone(streamedRequest.sink.close); + } + + streamedRequest.headers.addAll(_credentialBuilder.configure(_headers)); + return streamedRequest; + } +} + +Map _buildHeaders(bool isWeb, String sdkIdentifier) { + final headers = {'Content-Type': 'application/x-sentry-envelope'}; + // NOTE(lejard_h) overriding user agent on VM and Flutter not sure why + // for web it use browser user agent + if (!isWeb) { + headers['User-Agent'] = sdkIdentifier; + } + return headers; +} + +class _CredentialBuilder { + final String _authHeader; + + _CredentialBuilder._(String authHeader) : _authHeader = authHeader; + + factory _CredentialBuilder(Dsn dsn, String sdkIdentifier) { + final authHeader = _buildAuthHeader( + publicKey: dsn.publicKey, + secretKey: dsn.secretKey, + sdkIdentifier: sdkIdentifier, + ); + + return _CredentialBuilder._(authHeader); + } + + static String _buildAuthHeader({ + required String publicKey, + String? secretKey, + required String sdkIdentifier, + }) { + var header = 'Sentry sentry_version=7, sentry_client=$sdkIdentifier, ' + 'sentry_key=$publicKey'; + + if (secretKey != null) { + header += ', sentry_secret=$secretKey'; + } + + return header; + } + + Map configure(Map headers) { + return headers + ..addAll( + {'X-Sentry-Auth': _authHeader}, + ); + } +} diff --git a/dart/lib/src/transport/spotlight_http_transport.dart b/dart/lib/src/transport/spotlight_http_transport.dart new file mode 100644 index 0000000000..f51e77d478 --- /dev/null +++ b/dart/lib/src/transport/spotlight_http_transport.dart @@ -0,0 +1,52 @@ +import 'package:http/http.dart'; +import '../utils/transport_utils.dart'; +import 'http_transport_request_handler.dart'; + +import '../../sentry.dart'; +import '../noop_client.dart'; + +/// Spotlight HTTP transport decorator that sends Sentry envelopes to both Sentry and Spotlight. +class SpotlightHttpTransport extends Transport { + final SentryOptions _options; + final Transport _transport; + final HttpTransportRequestHandler _requestHandler; + + factory SpotlightHttpTransport(SentryOptions options, Transport transport) { + if (options.httpClient is NoOpClient) { + options.httpClient = Client(); + } + return SpotlightHttpTransport._(options, transport); + } + + SpotlightHttpTransport._(this._options, this._transport) + : _requestHandler = HttpTransportRequestHandler( + _options, Uri.parse(_options.spotlight.url)); + + @override + Future send(SentryEnvelope envelope) async { + try { + await _sendToSpotlight(envelope); + } catch (e) { + _options.logger( + SentryLevel.warning, 'Failed to send envelope to Spotlight: $e'); + } + return _transport.send(envelope); + } + + Future _sendToSpotlight(SentryEnvelope envelope) async { + envelope.header.sentAt = _options.clock(); + + // Screenshots do not work currently https://github.com/getsentry/spotlight/issues/274 + envelope.items + .removeWhere((element) => element.header.contentType == 'image/png'); + + final spotlightRequest = await _requestHandler.createRequest(envelope); + + final response = await _options.httpClient + .send(spotlightRequest) + .then(Response.fromStream); + + TransportUtils.logResponse(_options, envelope, response, + target: 'Spotlight'); + } +} diff --git a/dart/lib/src/utils/transport_utils.dart b/dart/lib/src/utils/transport_utils.dart new file mode 100644 index 0000000000..388db8e8d5 --- /dev/null +++ b/dart/lib/src/utils/transport_utils.dart @@ -0,0 +1,30 @@ +import 'package:http/http.dart'; + +import '../../sentry_io.dart'; +import '../client_reports/discard_reason.dart'; +import '../transport/data_category.dart'; + +class TransportUtils { + static void logResponse( + SentryOptions options, SentryEnvelope envelope, Response response, + {required String target}) { + if (response.statusCode != 200) { + if (options.debug) { + options.logger( + SentryLevel.error, + 'Error, statusCode = ${response.statusCode}, body = ${response.body}', + ); + } + + if (response.statusCode >= 400 && response.statusCode != 429) { + options.recorder + .recordLostEvent(DiscardReason.networkError, DataCategory.error); + } + } else { + options.logger( + SentryLevel.debug, + 'Envelope ${envelope.header.eventId ?? "--"} was sent successfully to $target.', + ); + } + } +} diff --git a/dart/test/environment_test.dart b/dart/test/environment_test.dart index e4bf97fea7..b16225d1dd 100644 --- a/dart/test/environment_test.dart +++ b/dart/test/environment_test.dart @@ -39,7 +39,7 @@ void main() { test('SentryOptions are overriden by environment', () async { final options = SentryOptions(); options.environmentVariables = MockEnvironmentVariables( - dsn: 'foo-bar', + dsn: fakeDsn, environment: 'staging', release: 'release-9.8.7', dist: 'bar', @@ -51,7 +51,7 @@ void main() { options: options, ); - expect(options.dsn, 'foo-bar'); + expect(options.dsn, fakeDsn); expect(options.environment, 'staging'); expect(options.release, 'release-9.8.7'); expect(options.dist, 'bar'); diff --git a/dart/test/sentry_client_test.dart b/dart/test/sentry_client_test.dart index cdbbd73950..63c83a321f 100644 --- a/dart/test/sentry_client_test.dart +++ b/dart/test/sentry_client_test.dart @@ -12,6 +12,7 @@ import 'package:sentry/src/sentry_item_type.dart'; import 'package:sentry/src/sentry_stack_trace_factory.dart'; import 'package:sentry/src/sentry_tracer.dart'; import 'package:sentry/src/transport/data_category.dart'; +import 'package:sentry/src/transport/spotlight_http_transport.dart'; import 'package:test/test.dart'; import 'mocks.dart'; @@ -1706,6 +1707,14 @@ void main() { expect(capturedEnvelope.header.dsn, fixture.options.dsn); }); + + test('Spotlight enabled should set transport to SpotlightHttpTransport', + () async { + fixture.options.spotlight = Spotlight(enabled: true); + fixture.getSut(); + + expect(fixture.options.transport is SpotlightHttpTransport, true); + }); }); } diff --git a/dart/test/sentry_options_test.dart b/dart/test/sentry_options_test.dart index f6dec29e90..e921c87b32 100644 --- a/dart/test/sentry_options_test.dart +++ b/dart/test/sentry_options_test.dart @@ -127,4 +127,10 @@ void main() { expect(options.isTracingEnabled(), false); }); + + test('Spotlight is disabled by default', () { + final options = SentryOptions(dsn: fakeDsn); + + expect(options.spotlight.enabled, false); + }); } diff --git a/dart/test/transport/spotlight_http_transport_test.dart b/dart/test/transport/spotlight_http_transport_test.dart new file mode 100644 index 0000000000..b23f1fd87f --- /dev/null +++ b/dart/test/transport/spotlight_http_transport_test.dart @@ -0,0 +1,70 @@ +import 'package:http/http.dart' as http; +import 'package:http/testing.dart'; +import 'package:sentry/sentry.dart'; +import 'package:sentry/src/transport/http_transport.dart'; +import 'package:sentry/src/transport/rate_limiter.dart'; +import 'package:sentry/src/transport/spotlight_http_transport.dart'; +import 'package:test/expect.dart'; +import 'package:test/scaffolding.dart'; + +import '../mocks.dart'; +import '../mocks/mock_client_report_recorder.dart'; + +void main() { + group('send to Sentry', () { + late Fixture fixture; + + setUp(() { + fixture = Fixture(); + }); + + test('send event to Sentry even if Spotlight fails', () async { + List? body; + + final httpMock = MockClient((http.Request request) async { + body = request.bodyBytes; + if (request.url.toString() == fixture.options.spotlight.url) { + return http.Response('{}', 500); + } + return http.Response('{}', 200); + }); + + fixture.options.compressPayload = false; + final mockRateLimiter = MockRateLimiter(); + final sut = fixture.getSut(httpMock, mockRateLimiter); + + final sentryEvent = SentryEvent(); + final envelope = SentryEnvelope.fromEvent( + sentryEvent, + fixture.options.sdk, + dsn: fixture.options.dsn, + ); + await sut.send(envelope); + + final envelopeData = []; + await envelope + .envelopeStream(fixture.options) + .forEach(envelopeData.addAll); + + expect(body, envelopeData); + }); + }); +} + +class Fixture { + final options = SentryOptions( + dsn: 'https://public:secret@sentry.example.com/1', + ); + + late var clientReportRecorder = MockClientReportRecorder(); + + Transport getSut(http.Client client, RateLimiter rateLimiter) { + options.httpClient = client; + options.recorder = clientReportRecorder; + options.clock = () { + return DateTime.utc(2019); + }; + final httpTransport = HttpTransport(options, rateLimiter); + return SpotlightHttpTransport(options, httpTransport); + } +} From 33ed16d14ca2c2de08d112d2870ce79993c6c8e8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 27 Dec 2023 12:13:39 +0100 Subject: [PATCH 041/237] build(deps): bump VeryGoodOpenSource/very_good_coverage (#1795) Bumps [VeryGoodOpenSource/very_good_coverage](https://github.com/verygoodopensource/very_good_coverage) from 2.1.0 to 2.2.0. - [Release notes](https://github.com/verygoodopensource/very_good_coverage/releases) - [Changelog](https://github.com/VeryGoodOpenSource/very_good_coverage/blob/main/CHANGELOG.md) - [Commits](https://github.com/verygoodopensource/very_good_coverage/compare/v2.1.0...3b475421464c564c0714d92ce02742bd81fa9eda) --- updated-dependencies: - dependency-name: VeryGoodOpenSource/very_good_coverage dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/isar.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/isar.yml b/.github/workflows/isar.yml index cad3e861c3..4b0ae60121 100644 --- a/.github/workflows/isar.yml +++ b/.github/workflows/isar.yml @@ -103,7 +103,7 @@ jobs: file: ./isar/coverage/lcov.info functionalities: "search" # remove after https://github.com/codecov/codecov-action/issues/600 - - uses: VeryGoodOpenSource/very_good_coverage@e5c91bc7ce9843e87c800b3bcafdfb86fbe28491 # pin@v2.1.0 + - uses: VeryGoodOpenSource/very_good_coverage@3b475421464c564c0714d92ce02742bd81fa9eda # pin@v2.2.0 if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' with: path: "./isar/coverage/lcov.info" From 730365e15633a21afed127dc0f7d36dfe68f68fe Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 27 Dec 2023 12:22:36 +0100 Subject: [PATCH 042/237] build(deps): bump actions/setup-java from 3 to 4 (#1797) Bumps [actions/setup-java](https://github.com/actions/setup-java) from 3 to 4. - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/setup-java dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/isar.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/isar.yml b/.github/workflows/isar.yml index 4b0ae60121..b57722fb50 100644 --- a/.github/workflows/isar.yml +++ b/.github/workflows/isar.yml @@ -66,7 +66,7 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: actions/setup-java@v3 + - uses: actions/setup-java@v4 if: ${{ matrix.target == 'android' }} with: java-version: "11" From 404d19fe32b509c84d6654aff8432e5b225939e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20Andra=C5=A1ec?= Date: Wed, 27 Dec 2023 15:56:19 +0000 Subject: [PATCH 043/237] Update Path Filters (#1763) --- .github/workflows/dart.yml | 14 +++++--------- .github/workflows/dio.yml | 15 ++++++--------- .github/workflows/drift.yml | 15 ++++++--------- .github/workflows/e2e_dart.yml | 16 ++++++---------- .github/workflows/file.yml | 14 ++++++-------- .github/workflows/flutter.yml | 15 ++++++--------- .github/workflows/flutter_test.yml | 9 ++++++--- .github/workflows/hive.yml | 15 ++++++--------- .github/workflows/isar.yml | 15 ++++++--------- .github/workflows/logging.yml | 15 ++++++--------- .github/workflows/min_version_test.yml | 14 +++++++------- .github/workflows/sqflite.yml | 15 ++++++--------- 12 files changed, 72 insertions(+), 100 deletions(-) diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml index 3d6e4229fd..779cf5ea90 100644 --- a/.github/workflows/dart.yml +++ b/.github/workflows/dart.yml @@ -5,15 +5,11 @@ on: - main - release/** pull_request: - paths-ignore: - - "**/*.md" - - "logging/**" - - "dio/**" - - "file/**" - - "sqflite/**" - - "hive/**" - - "drift/**" - - "isar/**" + paths: + - "!**/*.md" + - "!**/class-diagram.svg" + - ".github/workflows/dart.yml" + - "dart/**" jobs: cancel-previous-workflow: diff --git a/.github/workflows/dio.yml b/.github/workflows/dio.yml index ec7a54eedc..c85ab43a1a 100644 --- a/.github/workflows/dio.yml +++ b/.github/workflows/dio.yml @@ -5,15 +5,12 @@ on: - main - release/** pull_request: - paths-ignore: - - "**/*.md" - - "logging/**" - - "flutter/**" - - "file/**" - - "sqflite/**" - - "hive/**" - - "drift/**" - - "isar/**" + paths: + - "!**/*.md" + - "!**/class-diagram.svg" + - ".github/workflows/dio.yml" + - "dart/**" + - "dio/**" jobs: cancel-previous-workflow: diff --git a/.github/workflows/drift.yml b/.github/workflows/drift.yml index b5e2c630aa..f13f6d22f6 100644 --- a/.github/workflows/drift.yml +++ b/.github/workflows/drift.yml @@ -5,15 +5,12 @@ on: - main - release/** pull_request: - paths-ignore: - - "**/*.md" - - "logging/**" - - "flutter/**" - - "dio/**" - - "file/**" - - "sqflite/**" - - "hive/**" - - "isar/**" + paths: + - "!**/*.md" + - "!**/class-diagram.svg" + - ".github/workflows/drift.yml" + - "dart/**" + - "drift/**" jobs: cancel-previous-workflow: diff --git a/.github/workflows/e2e_dart.yml b/.github/workflows/e2e_dart.yml index 730d015d8e..2d66eaf9e2 100644 --- a/.github/workflows/e2e_dart.yml +++ b/.github/workflows/e2e_dart.yml @@ -5,16 +5,12 @@ on: - main - release/** pull_request: - paths-ignore: - - "**/*.md" - - "logging/**" - - "dio/**" - - "flutter/**" - - "file/**" - - "sqflite/**" - - "hive/**" - - "drift/**" - - "isar/**" + paths: + - "!**/*.md" + - "!**/class-diagram.svg" + - ".github/workflows/e2e_dart.yml" + - "dart/**" + - "e2e_test/**" env: SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} diff --git a/.github/workflows/file.yml b/.github/workflows/file.yml index 56e3750fc9..322c24b22e 100644 --- a/.github/workflows/file.yml +++ b/.github/workflows/file.yml @@ -5,15 +5,13 @@ on: - main - release/** pull_request: - paths-ignore: - - "**/*.md" - - "logging/**" + paths: + - "!**/*.md" + - "!**/class-diagram.svg" + - ".github/workflows/file.yml" + - "dart/**" - "flutter/**" - - "dio/**" - - "sqflite/**" - - "hive/**" - - "drift/**" - - "isar/**" + - "file/**" jobs: cancel-previous-workflow: diff --git a/.github/workflows/flutter.yml b/.github/workflows/flutter.yml index 77e02e4fc7..e21b884a01 100644 --- a/.github/workflows/flutter.yml +++ b/.github/workflows/flutter.yml @@ -5,15 +5,12 @@ on: - main - release/** pull_request: - paths-ignore: - - "**/*.md" - - "logging/**" - - "dio/**" - - "file/**" - - "sqflite/**" - - "hive/**" - - "drift/**" - - "isar/**" + paths: + - ".github/workflows/flutter.yml" + - "!**/*.md" + - "!**/class-diagram.svg" + - "dart/**" + - "flutter/**" jobs: cancel-previous-workflow: diff --git a/.github/workflows/flutter_test.yml b/.github/workflows/flutter_test.yml index 29b05e9821..d1ce043f54 100644 --- a/.github/workflows/flutter_test.yml +++ b/.github/workflows/flutter_test.yml @@ -5,9 +5,12 @@ on: - main - release/** pull_request: - paths-ignore: - - "**/*.md" - - "file/**" + paths: + - "!**/*.md" + - "!**/class-diagram.svg" + - ".github/workflows/flutter_test.yml" + - "dart/**" + - "flutter/**" env: SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} diff --git a/.github/workflows/hive.yml b/.github/workflows/hive.yml index 4e710d19fa..1ff1a8483e 100644 --- a/.github/workflows/hive.yml +++ b/.github/workflows/hive.yml @@ -5,15 +5,12 @@ on: - main - release/** pull_request: - paths-ignore: - - "**/*.md" - - "logging/**" - - "flutter/**" - - "dio/**" - - "file/**" - - "sqflite/**" - - "drift/**" - - "isar/**" + paths: + - "!**/*.md" + - "!**/class-diagram.svg" + - ".github/workflows/hive.yml" + - "dart/**" + - "hive/**" jobs: cancel-previous-workflow: diff --git a/.github/workflows/isar.yml b/.github/workflows/isar.yml index b57722fb50..4e090f6307 100644 --- a/.github/workflows/isar.yml +++ b/.github/workflows/isar.yml @@ -5,15 +5,12 @@ on: - main - release/** pull_request: - paths-ignore: - - "**/*.md" - - "logging/**" - - "flutter/**" - - "dio/**" - - "file/**" - - "sqflite/**" - - "hive/**" - - "drift/**" + paths: + - "!**/*.md" + - "!**/class-diagram.svg" + - ".github/workflows/isar.yml" + - "dart/**" + - "isar/**" jobs: cancel-previous-workflow: diff --git a/.github/workflows/logging.yml b/.github/workflows/logging.yml index d4b6d9898c..d6af6538bd 100644 --- a/.github/workflows/logging.yml +++ b/.github/workflows/logging.yml @@ -5,15 +5,12 @@ on: - main - release/** pull_request: - paths-ignore: - - "**/*.md" - - "dio/**" - - "flutter/**" - - "file/**" - - "sqflite/**" - - "hive/**" - - "drift/**" - - "isar/**" + paths: + - "!**/*.md" + - "!**/class-diagram.svg" + - ".github/workflows/logging.yml" + - "dart/**" + - "logging/**" jobs: cancel-previous-workflow: diff --git a/.github/workflows/min_version_test.yml b/.github/workflows/min_version_test.yml index 3d227a1447..6b08e3ca95 100644 --- a/.github/workflows/min_version_test.yml +++ b/.github/workflows/min_version_test.yml @@ -5,13 +5,13 @@ on: - main - release/** pull_request: - paths-ignore: - - "**/*.md" - - "file/**" - - "sqflite/**" - - "hive/**" - - "drift/**" - - "isar/**" + paths: + - "!**/*.md" + - "!**/class-diagram.svg" + - ".github/workflows/min_version_test.yml" + - "dart/**" + - "flutter/**" + - "min_version_test/**" jobs: cancel-previous-workflow: diff --git a/.github/workflows/sqflite.yml b/.github/workflows/sqflite.yml index 48bcf380b2..1168c4561e 100644 --- a/.github/workflows/sqflite.yml +++ b/.github/workflows/sqflite.yml @@ -5,15 +5,12 @@ on: - main - release/** pull_request: - paths-ignore: - - "**/*.md" - - "logging/**" - - "flutter/**" - - "dio/**" - - "file/**" - - "hive/**" - - "drift/**" - - "isar/**" + paths: + - "!**/*.md" + - "!**/class-diagram.svg" + - ".github/workflows/logging.yml" + - "dart/**" + - "sqflite/**" jobs: cancel-previous-workflow: From bde5f6b1cb1762d9a377a5c57399a5bd1d9b06b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Uek=C3=B6tter?= Date: Wed, 3 Jan 2024 11:58:40 +0100 Subject: [PATCH 044/237] Add app flavor to `flutter_context` (#1799) * Add app flavor * fix changelog --- CHANGELOG.md | 1 + .../event_processor/flutter_enricher_event_processor.dart | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 71483dab8e..55773a0b75 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ - Add `ConnectivityIntegration` for web ([#1765](https://github.com/getsentry/sentry-dart/pull/1765)) - We only get the info if online/offline on web platform. The added breadcrumb is set to either `wifi` or `none`. - APM for isar ([#1726](https://github.com/getsentry/sentry-dart/pull/1726)) +- Starting with Flutter 3.16, Sentry adds the [`appFlavor`](https://api.flutter.dev/flutter/services/appFlavor-constant.html) to the `flutter_context` ([#1799](https://github.com/getsentry/sentry-dart/pull/1799)) ## 7.14.0 diff --git a/flutter/lib/src/event_processor/flutter_enricher_event_processor.dart b/flutter/lib/src/event_processor/flutter_enricher_event_processor.dart index a4d04573a6..615c7a4974 100644 --- a/flutter/lib/src/event_processor/flutter_enricher_event_processor.dart +++ b/flutter/lib/src/event_processor/flutter_enricher_event_processor.dart @@ -153,6 +153,7 @@ class FlutterEnricherEventProcessor implements EventProcessor { // See https://github.com/flutter/flutter/issues/83919 // 'window_is_visible': _window.viewConfiguration.visible, if (renderer != null) 'renderer': renderer, + if (_appFlavor != null) 'appFlavor': _appFlavor!, }; } @@ -266,3 +267,10 @@ class FlutterEnricherEventProcessor implements EventProcessor { return null; } } + +/// Copied from https://api.flutter.dev/flutter/services/appFlavor-constant.html +/// As soon as Flutter 3.16 is the minimal supported version of Sentry, this +/// can be replaced with the property from the link above. +const String? _appFlavor = String.fromEnvironment('FLUTTER_APP_FLAVOR') != '' + ? String.fromEnvironment('FLUTTER_APP_FLAVOR') + : null; From ca7f531d8ef46d53d71b084884c27cae425de945 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 3 Jan 2024 12:01:13 +0100 Subject: [PATCH 045/237] chore(deps): update Android SDK to v7.1.0 (#1788) * chore: update flutter/scripts/update-android.sh to 7.1.0 * Fix app start * format --------- Co-authored-by: GitHub Co-authored-by: GIancarlo Buenaflor --- CHANGELOG.md | 6 ++++++ flutter/android/build.gradle | 2 +- .../main/kotlin/io/sentry/flutter/SentryFlutterPlugin.kt | 7 ++++--- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 55773a0b75..8154a73e70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,12 @@ - APM for isar ([#1726](https://github.com/getsentry/sentry-dart/pull/1726)) - Starting with Flutter 3.16, Sentry adds the [`appFlavor`](https://api.flutter.dev/flutter/services/appFlavor-constant.html) to the `flutter_context` ([#1799](https://github.com/getsentry/sentry-dart/pull/1799)) +### Dependencies + +- Bump Android SDK from v7.0.0 to v7.1.0 ([#1788](https://github.com/getsentry/sentry-dart/pull/1788)) + - [changelog](https://github.com/getsentry/sentry-java/blob/main/CHANGELOG.md#710) + - [diff](https://github.com/getsentry/sentry-java/compare/7.0.0...7.1.0) + ## 7.14.0 - Add option to opt out of fatal level for automatically collected errors ([#1738](https://github.com/getsentry/sentry-dart/pull/1738)) diff --git a/flutter/android/build.gradle b/flutter/android/build.gradle index 859103b80f..e594b017ea 100644 --- a/flutter/android/build.gradle +++ b/flutter/android/build.gradle @@ -60,7 +60,7 @@ android { } dependencies { - api 'io.sentry:sentry-android:7.0.0' + api 'io.sentry:sentry-android:7.1.0' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" // Required -- JUnit 4 framework diff --git a/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutterPlugin.kt b/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutterPlugin.kt index 2ae6a673cb..b908ff823f 100644 --- a/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutterPlugin.kt +++ b/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutterPlugin.kt @@ -19,11 +19,11 @@ import io.sentry.SentryEvent import io.sentry.SentryLevel import io.sentry.SentryOptions import io.sentry.android.core.ActivityFramesTracker -import io.sentry.android.core.AppStartState import io.sentry.android.core.BuildConfig.VERSION_NAME import io.sentry.android.core.LoadClass import io.sentry.android.core.SentryAndroid import io.sentry.android.core.SentryAndroidOptions +import io.sentry.android.core.performance.AppStartMetrics import io.sentry.protocol.DebugImage import io.sentry.protocol.SdkVersion import io.sentry.protocol.SentryId @@ -140,8 +140,9 @@ class SentryFlutterPlugin : FlutterPlugin, MethodCallHandler, ActivityAware { result.success(null) return } - val appStartTime = AppStartState.getInstance().appStartTime - val isColdStart = AppStartState.getInstance().isColdStart + + val appStartTime = AppStartMetrics.getInstance().appStartTimeSpan.startTimestamp + val isColdStart = AppStartMetrics.getInstance().appStartType == AppStartMetrics.AppStartType.COLD if (appStartTime == null) { Log.w("Sentry", "App start won't be sent due to missing appStartTime") From f12d09db045001829805941d7d2f050867de7409 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20Andra=C5=A1ec?= Date: Mon, 8 Jan 2024 10:14:47 +0000 Subject: [PATCH 046/237] Add isar breadcrumbs (#1800) --- CHANGELOG.md | 1 + isar/lib/src/sentry_span_helper.dart | 18 + isar/pubspec.yaml | 4 +- isar/test/sentry_isar_collection_test.dart | 452 +++++++++++++++++++++ isar/test/sentry_isar_test.dart | 229 ++++++++++- 5 files changed, 687 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8154a73e70..a099b054d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ - Add `ConnectivityIntegration` for web ([#1765](https://github.com/getsentry/sentry-dart/pull/1765)) - We only get the info if online/offline on web platform. The added breadcrumb is set to either `wifi` or `none`. - APM for isar ([#1726](https://github.com/getsentry/sentry-dart/pull/1726)) +- Add isar breadcrumbs ([#1800](https://github.com/getsentry/sentry-dart/pull/1800)) - Starting with Flutter 3.16, Sentry adds the [`appFlavor`](https://api.flutter.dev/flutter/services/appFlavor-constant.html) to the `flutter_context` ([#1799](https://github.com/getsentry/sentry-dart/pull/1799)) ### Dependencies diff --git a/isar/lib/src/sentry_span_helper.dart b/isar/lib/src/sentry_span_helper.dart index 69fc6e5c39..ec1823c7ca 100644 --- a/isar/lib/src/sentry_span_helper.dart +++ b/isar/lib/src/sentry_span_helper.dart @@ -38,28 +38,46 @@ class SentrySpanHelper { // ignore: invalid_use_of_internal_member span?.origin = _origin; + var breadcrumb = Breadcrumb( + message: description, + data: {}, + type: 'query', + ); + span?.setData(SentryIsar.dbSystemKey, SentryIsar.dbSystem); if (dbName != null) { span?.setData(SentryIsar.dbNameKey, dbName); + breadcrumb.data?[SentryIsar.dbNameKey] = dbName; } if (collectionName != null) { span?.setData(SentryIsar.dbCollectionKey, collectionName); + breadcrumb.data?[SentryIsar.dbCollectionKey] = collectionName; } try { final result = await execute(); + span?.status = SpanStatus.ok(); + breadcrumb.data?['status'] = 'ok'; return result; } catch (exception) { span?.throwable = exception; span?.status = SpanStatus.internalError(); + breadcrumb.data?['status'] = 'internal_error'; + breadcrumb = breadcrumb.copyWith( + level: SentryLevel.warning, + ); + rethrow; } finally { await span?.finish(); + + // ignore: invalid_use_of_internal_member + await _hub.scope.addBreadcrumb(breadcrumb); } } } diff --git a/isar/pubspec.yaml b/isar/pubspec.yaml index 43c0907472..df066786f8 100644 --- a/isar/pubspec.yaml +++ b/isar/pubspec.yaml @@ -12,13 +12,13 @@ environment: dependencies: isar: ^3.1.0 isar_flutter_libs: ^3.1.0 # contains Isar Core - sentry: 7.12.0 + sentry: 7.14.0 meta: ^1.3.0 path: ^1.8.3 dev_dependencies: isar_generator: ^3.1.0 - build_runner: ^2.4.2 + build_runner: ^2.4.6 lints: ^3.0.0 flutter_test: sdk: flutter diff --git a/isar/test/sentry_isar_collection_test.dart b/isar/test/sentry_isar_collection_test.dart index c3286a2971..de55ac5989 100644 --- a/isar/test/sentry_isar_collection_test.dart +++ b/isar/test/sentry_isar_collection_test.dart @@ -36,6 +36,22 @@ void main() { expect(span?.throwable, error); } + void verifyBreadcrumb( + String message, + Breadcrumb? crumb, { + String status = 'ok', + }) { + expect( + crumb?.message, + message, + ); + expect(crumb?.type, 'query'); + expect(crumb?.data?['status'], status); + if (status != 'ok') { + expect(crumb?.level, SentryLevel.warning); + } + } + group('add spans', () { late Fixture fixture; @@ -44,6 +60,7 @@ void main() { when(fixture.hub.options).thenReturn(fixture.options); when(fixture.hub.getSpan()).thenReturn(fixture.tracer); + when(fixture.hub.scope).thenReturn(fixture.scope); await fixture.setUp(); }); @@ -204,6 +221,7 @@ void main() { when(fixture.hub.options).thenReturn(fixture.options); when(fixture.hub.getSpan()).thenReturn(fixture.tracer); + when(fixture.hub.scope).thenReturn(fixture.scope); when(fixture.isarCollection.name).thenReturn(Fixture.dbCollection); await fixture.setUp(); @@ -426,6 +444,435 @@ void main() { ); }); }); + + group('add breadcrumbs', () { + late Fixture fixture; + + setUp(() async { + fixture = Fixture(); + + when(fixture.hub.options).thenReturn(fixture.options); + when(fixture.hub.getSpan()).thenReturn(fixture.tracer); + when(fixture.hub.scope).thenReturn(fixture.scope); + + await fixture.setUp(); + }); + + tearDown(() async { + await fixture.tearDown(); + }); + + test('clear adds breadcrumb', () async { + await fixture.sentryIsar.writeTxn(() async { + await fixture.getSut().clear(); + }); + final breadcrumb = fixture.hub.scope.breadcrumbs[1]; + verifyBreadcrumb('clear', breadcrumb); + }); + + test('count adds breadcrumb', () async { + await fixture.sentryIsar.writeTxn(() async { + await fixture.getSut().count(); + }); + final breadcrumb = fixture.hub.scope.breadcrumbs[1]; + verifyBreadcrumb('count', breadcrumb); + }); + + test('delete adds breadcrumb', () async { + await fixture.sentryIsar.writeTxn(() async { + await fixture.getSut().delete(0); + }); + final breadcrumb = fixture.hub.scope.breadcrumbs[1]; + verifyBreadcrumb('delete', breadcrumb); + }); + + test('deleteAll adds breadcrumb', () async { + await fixture.sentryIsar.writeTxn(() async { + await fixture.getSut().deleteAll([0]); + }); + final breadcrumb = fixture.hub.scope.breadcrumbs[1]; + verifyBreadcrumb('deleteAll', breadcrumb); + }); + + test('deleteAllByIndex adds breadcrumb', () async { + await fixture.sentryIsar.writeTxn(() async { + await fixture.getSut().putByIndex('name', Person()..name = 'Joe'); + await fixture.getSut().deleteAllByIndex('name', []); + }); + final breadcrumb = fixture.hub.scope.breadcrumbs[2]; + verifyBreadcrumb('deleteAllByIndex', breadcrumb); + }); + + test('deleteByIndex adds breadcrumb', () async { + await fixture.sentryIsar.writeTxn(() async { + await fixture.getSut().putByIndex('name', Person()..name = 'Joe'); + await fixture.getSut().deleteByIndex('name', []); + }); + final breadcrumb = fixture.hub.scope.breadcrumbs[2]; + verifyBreadcrumb('deleteByIndex', breadcrumb); + }); + + test('get adds breadcrumb', () async { + await fixture.sentryIsar.writeTxn(() async { + await fixture.getSut().get(1); + }); + final breadcrumb = fixture.hub.scope.breadcrumbs[1]; + verifyBreadcrumb('get', breadcrumb); + }); + + test('getAll adds breadcrumb', () async { + await fixture.sentryIsar.writeTxn(() async { + await fixture.getSut().getAll([1]); + }); + final breadcrumb = fixture.hub.scope.breadcrumbs[1]; + verifyBreadcrumb('getAll', breadcrumb); + }); + + test('getAllByIndex adds breadcrumb', () async { + await fixture.sentryIsar.writeTxn(() async { + await fixture.getSut().getAllByIndex('name', []); + }); + final breadcrumb = fixture.hub.scope.breadcrumbs[1]; + verifyBreadcrumb('getAllByIndex', breadcrumb); + }); + + test('getByIndex adds breadcrumb', () async { + await fixture.sentryIsar.writeTxn(() async { + await fixture.getSut().getByIndex('name', []); + }); + final breadcrumb = fixture.hub.scope.breadcrumbs[1]; + verifyBreadcrumb('getByIndex', breadcrumb); + }); + + test('getSize adds breadcrumb', () async { + await fixture.sentryIsar.writeTxn(() async { + await fixture.getSut().getSize(); + }); + final breadcrumb = fixture.hub.scope.breadcrumbs[1]; + verifyBreadcrumb('getSize', breadcrumb); + }); + + test('importJson adds breadcrumb', () async { + await fixture.sentryIsar.writeTxn(() async { + await fixture.getSut().importJson([]); + }); + final breadcrumb = fixture.hub.scope.breadcrumbs[1]; + verifyBreadcrumb('importJson', breadcrumb); + }); + + test('importJsonRaw adds breadcrumb', () async { + await fixture.sentryIsar.writeTxn(() async { + final query = fixture.getSut().buildQuery(); + Uint8List jsonRaw = Uint8List.fromList([]); + await query.exportJsonRaw((raw) { + jsonRaw = Uint8List.fromList(raw); + }); + await fixture.getSut().importJsonRaw(jsonRaw); + }); + final breadcrumb = fixture.hub.scope.breadcrumbs[1]; + verifyBreadcrumb('importJsonRaw', breadcrumb); + }); + + test('put adds breadcrumb', () async { + await fixture.sentryIsar.writeTxn(() async { + await fixture.getSut().put(Person()); + }); + final breadcrumb = fixture.hub.scope.breadcrumbs[1]; + verifyBreadcrumb('put', breadcrumb); + }); + + test('putAll adds breadcrumb', () async { + await fixture.sentryIsar.writeTxn(() async { + await fixture.getSut().putAll([Person()]); + }); + final breadcrumb = fixture.hub.scope.breadcrumbs[1]; + verifyBreadcrumb('putAll', breadcrumb); + }); + + test('putAllByIndex adds breadcrumb', () async { + await fixture.sentryIsar.writeTxn(() async { + await fixture.getSut().putAllByIndex('name', [Person()]); + }); + final breadcrumb = fixture.hub.scope.breadcrumbs[1]; + verifyBreadcrumb('putAllByIndex', breadcrumb); + }); + + test('putByIndex adds breadcrumb', () async { + await fixture.sentryIsar.writeTxn(() async { + await fixture.getSut().putByIndex('name', Person()); + }); + final breadcrumb = fixture.hub.scope.breadcrumbs[1]; + verifyBreadcrumb('putByIndex', breadcrumb); + }); + }); + + group('add error breadcrumbs', () { + late Fixture fixture; + + setUp(() async { + fixture = Fixture(); + + when(fixture.hub.options).thenReturn(fixture.options); + when(fixture.hub.getSpan()).thenReturn(fixture.tracer); + when(fixture.hub.scope).thenReturn(fixture.scope); + when(fixture.isarCollection.name).thenReturn(Fixture.dbCollection); + + await fixture.setUp(); + }); + + tearDown(() async { + await fixture.tearDown(); + }); + + test('throwing clear adds error breadcrumb', () async { + when(fixture.isarCollection.clear()).thenThrow(fixture.exception); + try { + await fixture.getSut(injectMock: true).clear(); + } catch (error) { + expect(error, fixture.exception); + } + verifyBreadcrumb( + 'clear', + fixture.getCreatedBreadcrumb(), + status: 'internal_error', + ); + }); + + test('throwing count adds error breadcrumb', () async { + when(fixture.isarCollection.count()).thenThrow(fixture.exception); + try { + await fixture.getSut(injectMock: true).count(); + } catch (error) { + expect(error, fixture.exception); + } + verifyBreadcrumb( + 'count', + fixture.getCreatedBreadcrumb(), + status: 'internal_error', + ); + }); + + test('throwing delete adds error breadcrumb', () async { + when(fixture.isarCollection.delete(any)).thenThrow(fixture.exception); + try { + await fixture.getSut(injectMock: true).delete(0); + } catch (error) { + expect(error, fixture.exception); + } + verifyBreadcrumb( + 'delete', + fixture.getCreatedBreadcrumb(), + status: 'internal_error', + ); + }); + + test('throwing deleteAll adds error breadcrumb', () async { + when(fixture.isarCollection.deleteAll(any)).thenThrow(fixture.exception); + try { + await fixture.getSut(injectMock: true).deleteAll([0]); + } catch (error) { + expect(error, fixture.exception); + } + verifyBreadcrumb( + 'deleteAll', + fixture.getCreatedBreadcrumb(), + status: 'internal_error', + ); + }); + + test('throwing deleteAllByIndex adds error breadcrumb', () async { + when(fixture.isarCollection.deleteAllByIndex(any, any)) + .thenThrow(fixture.exception); + try { + await fixture.getSut(injectMock: true).deleteAllByIndex('name', []); + } catch (error) { + expect(error, fixture.exception); + } + verifyBreadcrumb( + 'deleteAllByIndex', + fixture.getCreatedBreadcrumb(), + status: 'internal_error', + ); + }); + + test('throwing deleteByIndex adds error breadcrumb', () async { + when(fixture.isarCollection.deleteByIndex(any, any)) + .thenThrow(fixture.exception); + try { + await fixture.getSut(injectMock: true).deleteByIndex('name', []); + } catch (error) { + expect(error, fixture.exception); + } + verifyBreadcrumb( + 'deleteByIndex', + fixture.getCreatedBreadcrumb(), + status: 'internal_error', + ); + }); + + test('throwing get adds error breadcrumb', () async { + when(fixture.isarCollection.get(any)).thenThrow(fixture.exception); + try { + await fixture.getSut(injectMock: true).get(1); + } catch (error) { + expect(error, fixture.exception); + } + verifyBreadcrumb( + 'get', + fixture.getCreatedBreadcrumb(), + status: 'internal_error', + ); + }); + + test('throwing getAll adds error breadcrumb', () async { + when(fixture.isarCollection.getAll(any)).thenThrow(fixture.exception); + try { + await fixture.getSut(injectMock: true).getAll([1]); + } catch (error) { + expect(error, fixture.exception); + } + verifyBreadcrumb( + 'getAll', + fixture.getCreatedBreadcrumb(), + status: 'internal_error', + ); + }); + + test('throwing getAllByIndex adds error breadcrumb', () async { + when(fixture.isarCollection.getAllByIndex(any, any)) + .thenThrow(fixture.exception); + try { + await fixture.getSut(injectMock: true).getAllByIndex('name', []); + } catch (error) { + expect(error, fixture.exception); + } + verifyBreadcrumb( + 'getAllByIndex', + fixture.getCreatedBreadcrumb(), + status: 'internal_error', + ); + }); + + test('throwing getByIndex adds error breadcrumb', () async { + when(fixture.isarCollection.getByIndex(any, any)) + .thenThrow(fixture.exception); + try { + await fixture.getSut(injectMock: true).getByIndex('name', []); + } catch (error) { + expect(error, fixture.exception); + } + verifyBreadcrumb( + 'getByIndex', + fixture.getCreatedBreadcrumb(), + status: 'internal_error', + ); + }); + + test('throwing getSize adds error breadcrumb', () async { + when(fixture.isarCollection.getSize()).thenThrow(fixture.exception); + try { + await fixture.getSut(injectMock: true).getSize(); + } catch (error) { + expect(error, fixture.exception); + } + verifyBreadcrumb( + 'getSize', + fixture.getCreatedBreadcrumb(), + status: 'internal_error', + ); + }); + + test('throwing importJson adds error breadcrumb', () async { + when(fixture.isarCollection.importJson(any)).thenThrow(fixture.exception); + try { + await fixture.getSut(injectMock: true).importJson([]); + } catch (error) { + expect(error, fixture.exception); + } + verifyBreadcrumb( + 'importJson', + fixture.getCreatedBreadcrumb(), + status: 'internal_error', + ); + }); + + test('throwing importJsonRaw adds error breadcrumb', () async { + when(fixture.isarCollection.importJsonRaw(any)) + .thenThrow(fixture.exception); + try { + await fixture + .getSut(injectMock: true) + .importJsonRaw(Uint8List.fromList([])); + } catch (error) { + expect(error, fixture.exception); + } + verifyBreadcrumb( + 'importJsonRaw', + fixture.getCreatedBreadcrumb(), + status: 'internal_error', + ); + }); + + test('throwing put adds error breadcrumb', () async { + when(fixture.isarCollection.put(any)).thenThrow(fixture.exception); + try { + await fixture.getSut(injectMock: true).put(Person()); + } catch (error) { + expect(error, fixture.exception); + } + verifyBreadcrumb( + 'put', + fixture.getCreatedBreadcrumb(), + status: 'internal_error', + ); + }); + + test('throwing putAll adds error breadcrumb', () async { + when(fixture.isarCollection.putAll(any)).thenThrow(fixture.exception); + try { + await fixture.getSut(injectMock: true).putAll([Person()]); + } catch (error) { + expect(error, fixture.exception); + } + verifyBreadcrumb( + 'putAll', + fixture.getCreatedBreadcrumb(), + status: 'internal_error', + ); + }); + + test('throwing putAllByIndex adds error breadcrumb', () async { + when(fixture.isarCollection.putAllByIndex(any, any)) + .thenThrow(fixture.exception); + try { + await fixture + .getSut(injectMock: true) + .putAllByIndex('name', [Person()]); + } catch (error) { + expect(error, fixture.exception); + } + verifyBreadcrumb( + 'putAllByIndex', + fixture.getCreatedBreadcrumb(), + status: 'internal_error', + ); + }); + + test('throwing putByIndex adds error breadcrumb', () async { + when(fixture.isarCollection.putByIndex(any, any)) + .thenThrow(fixture.exception); + try { + await fixture.getSut(injectMock: true).putByIndex('name', Person()); + } catch (error) { + expect(error, fixture.exception); + } + verifyBreadcrumb( + 'putByIndex', + fixture.getCreatedBreadcrumb(), + status: 'internal_error', + ); + }); + }); } class Fixture { @@ -440,6 +887,7 @@ class Fixture { final _context = SentryTransactionContext('name', 'operation'); late final tracer = SentryTracer(_context, hub); late Isar sentryIsar; + late final scope = Scope(options); Future setUp() async { // Make sure to use flutter test -j 1 to avoid tests running in parallel. This would break the automatic download. @@ -473,4 +921,8 @@ class Fixture { SentrySpan? getCreatedSpan() { return tracer.children.last; } + + Breadcrumb? getCreatedBreadcrumb() { + return hub.scope.breadcrumbs.last; + } } diff --git a/isar/test/sentry_isar_test.dart b/isar/test/sentry_isar_test.dart index 70cc23c832..222226fa53 100644 --- a/isar/test/sentry_isar_test.dart +++ b/isar/test/sentry_isar_test.dart @@ -15,19 +15,13 @@ import 'mocks/mocks.mocks.dart'; import 'person.dart'; void main() { - void verifySpan( - String description, - SentrySpan? span, { - bool checkName = false, - }) { + void verifySpan(String description, SentrySpan? span) { expect(span?.context.operation, SentryIsar.dbOp); expect(span?.context.description, description); expect(span?.status, SpanStatus.ok()); // ignore: invalid_use_of_internal_member expect(span?.origin, SentryTraceOrigins.autoDbIsar); - if (checkName) { - expect(span?.data[SentryIsar.dbNameKey], Fixture.dbName); - } + expect(span?.data[SentryIsar.dbNameKey], Fixture.dbName); } void verifyErrorSpan(String description, SentrySpan? span, Exception error) { @@ -39,6 +33,23 @@ void main() { expect(span?.throwable, error); } + void verifyBreadcrumb( + String message, + Breadcrumb? crumb, { + String status = 'ok', + }) { + expect( + crumb?.message, + message, + ); + expect(crumb?.type, 'query'); + expect(crumb?.data?[SentryIsar.dbNameKey], Fixture.dbName); + expect(crumb?.data?['status'], status); + if (status != 'ok') { + expect(crumb?.level, SentryLevel.warning); + } + } + group('add spans', () { late Fixture fixture; @@ -47,6 +58,7 @@ void main() { when(fixture.hub.options).thenReturn(fixture.options); when(fixture.hub.getSpan()).thenReturn(fixture.tracer); + when(fixture.hub.scope).thenReturn(fixture.scope); await fixture.setUp(); }); @@ -57,7 +69,7 @@ void main() { test('open adds span', () async { final span = fixture.getCreatedSpan(); - verifySpan('open', span, checkName: true); + verifySpan('open', span); }); test('clear adds span', () async { @@ -65,37 +77,37 @@ void main() { await fixture.sut.clear(); }); final span = fixture.getCreatedSpan(); - verifySpan('clear', span, checkName: true); + verifySpan('clear', span); }); test('close adds span', () async { await fixture.sut.close(); final span = fixture.getCreatedSpan(); - verifySpan('close', span, checkName: true); + verifySpan('close', span); }); test('copyToFile adds span', () async { await fixture.sut.copyToFile(fixture.copyPath); final span = fixture.getCreatedSpan(); - verifySpan('copyToFile', span, checkName: true); + verifySpan('copyToFile', span); }); test('getSize adds span', () async { await fixture.sut.getSize(); final span = fixture.getCreatedSpan(); - verifySpan('getSize', span, checkName: true); + verifySpan('getSize', span); }); test('txn adds span', () async { await fixture.sut.txn(() async {}); final span = fixture.getCreatedSpan(); - verifySpan('txn', span, checkName: true); + verifySpan('txn', span); }); test('writeTxn adds span', () async { await fixture.sut.writeTxn(() async {}); final span = fixture.getCreatedSpan(); - verifySpan('writeTxn', span, checkName: true); + verifySpan('writeTxn', span); }); }); @@ -107,6 +119,8 @@ void main() { when(fixture.hub.options).thenReturn(fixture.options); when(fixture.hub.getSpan()).thenReturn(fixture.tracer); + when(fixture.hub.scope).thenReturn(fixture.scope); + when(fixture.isar.close()).thenAnswer((_) async { return true; }); @@ -186,6 +200,185 @@ void main() { }); }); + group('adds breadcrumbs', () { + late Fixture fixture; + + setUp(() async { + fixture = Fixture(); + + when(fixture.hub.options).thenReturn(fixture.options); + when(fixture.hub.getSpan()).thenReturn(fixture.tracer); + when(fixture.hub.scope).thenReturn(fixture.scope); + + await fixture.setUp(); + }); + + tearDown(() async { + await fixture.tearDown(); + }); + + test('open adds breadcrumb', () async { + final breadcrumb = fixture.getCreatedBreadcrumb(); + verifyBreadcrumb('open', breadcrumb); + }); + + test('clear adds breadcrumb', () async { + await fixture.sut.writeTxn(() async { + await fixture.sut.clear(); + }); + + // order: open, clear, writeTxn + + final openCrumb = fixture.hub.scope.breadcrumbs[0]; + verifyBreadcrumb('open', openCrumb); + + final clearCrumb = fixture.hub.scope.breadcrumbs[1]; + verifyBreadcrumb('clear', clearCrumb); + + final writeTxnCrumb = fixture.hub.scope.breadcrumbs[2]; + verifyBreadcrumb('writeTxn', writeTxnCrumb); + }); + + test('close adds breadcrumb', () async { + await fixture.sut.close(); + final breadcrumb = fixture.getCreatedBreadcrumb(); + verifyBreadcrumb('close', breadcrumb); + }); + + test('copyToFile adds breadcrumb', () async { + await fixture.sut.copyToFile(fixture.copyPath); + final breadcrumb = fixture.getCreatedBreadcrumb(); + verifyBreadcrumb('copyToFile', breadcrumb); + }); + + test('getSize adds breadcrumb', () async { + await fixture.sut.getSize(); + final breadcrumb = fixture.getCreatedBreadcrumb(); + verifyBreadcrumb('getSize', breadcrumb); + }); + + test('txn adds breadcrumb', () async { + await fixture.sut.txn(() async {}); + final breadcrumb = fixture.getCreatedBreadcrumb(); + verifyBreadcrumb('txn', breadcrumb); + }); + + test('writeTxn adds breadcrumb', () async { + await fixture.sut.writeTxn(() async {}); + final breadcrumb = fixture.getCreatedBreadcrumb(); + verifyBreadcrumb('writeTxn', breadcrumb); + }); + }); + + group('add error breadcrumbs', () { + late Fixture fixture; + + setUp(() async { + fixture = Fixture(); + + when(fixture.hub.options).thenReturn(fixture.options); + when(fixture.hub.getSpan()).thenReturn(fixture.tracer); + when(fixture.hub.scope).thenReturn(fixture.scope); + + when(fixture.isar.close()).thenAnswer((_) async { + return true; + }); + when(fixture.isar.name).thenReturn(Fixture.dbName); + + await fixture.setUp(injectMock: true); + }); + + tearDown(() async { + await fixture.tearDown(); + }); + + test('throwing close adds error breadcrumb', () async { + when(fixture.isar.close()).thenThrow(fixture.exception); + try { + await fixture.sut.close(); + } catch (error) { + expect(error, fixture.exception); + } + verifyBreadcrumb( + 'close', + fixture.getCreatedBreadcrumb(), + status: 'internal_error', + ); + }); + + test('throwing clear adds error breadcrumb', () async { + when(fixture.isar.clear()).thenThrow(fixture.exception); + try { + await fixture.sut.clear(); + } catch (error) { + expect(error, fixture.exception); + } + verifyBreadcrumb( + 'clear', + fixture.getCreatedBreadcrumb(), + status: 'internal_error', + ); + }); + + test('throwing copyToFile adds error breadcrumb', () async { + when(fixture.isar.copyToFile(any)).thenThrow(fixture.exception); + try { + await fixture.sut.copyToFile(fixture.copyPath); + } catch (error) { + expect(error, fixture.exception); + } + verifyBreadcrumb( + 'copyToFile', + fixture.getCreatedBreadcrumb(), + status: 'internal_error', + ); + }); + + test('throwing getSize adds error breadcrumb', () async { + when(fixture.isar.getSize()).thenThrow(fixture.exception); + try { + await fixture.sut.getSize(); + } catch (error) { + expect(error, fixture.exception); + } + verifyBreadcrumb( + 'getSize', + fixture.getCreatedBreadcrumb(), + status: 'internal_error', + ); + }); + + test('throwing txn adds error breadcrumb', () async { + param() async {} + when(fixture.isar.txn(param)).thenThrow(fixture.exception); + try { + await fixture.sut.txn(param); + } catch (error) { + expect(error, fixture.exception); + } + verifyBreadcrumb( + 'txn', + fixture.getCreatedBreadcrumb(), + status: 'internal_error', + ); + }); + + test('throwing writeTxn adds error breadcrumb', () async { + param() async {} + when(fixture.isar.writeTxn(param)).thenThrow(fixture.exception); + try { + await fixture.sut.writeTxn(param); + } catch (error) { + expect(error, fixture.exception); + } + verifyBreadcrumb( + 'writeTxn', + fixture.getCreatedBreadcrumb(), + status: 'internal_error', + ); + }); + }); + group('integrations', () { late Fixture fixture; @@ -194,6 +387,7 @@ void main() { when(fixture.hub.options).thenReturn(fixture.options); when(fixture.hub.getSpan()).thenReturn(fixture.tracer); + when(fixture.hub.scope).thenReturn(fixture.scope); await fixture.setUp(); }); @@ -233,6 +427,7 @@ class Fixture { final _context = SentryTransactionContext('name', 'operation'); late final tracer = SentryTracer(_context, hub); late Isar sut; + late final scope = Scope(options); Future setUp({bool injectMock = false}) async { if (injectMock) { @@ -268,6 +463,10 @@ class Fixture { return tracer.children.last; } + Breadcrumb? getCreatedBreadcrumb() { + return hub.scope.breadcrumbs.last; + } + Future deleteCopyPath() async { final file = File(copyPath); if (await file.exists()) { From 1cdcacf02367fc5937faac0a53973741676d7e40 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 8 Jan 2024 12:43:48 +0100 Subject: [PATCH 047/237] chore: update flutter/scripts/update-cocoa.sh to 8.18.0 (#1803) Co-authored-by: GitHub --- CHANGELOG.md | 3 +++ flutter/ios/sentry_flutter.podspec | 2 +- flutter/lib/src/native/cocoa/binding.dart | 32 ++++++++++++++--------- 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a099b054d8..864bc01d69 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,9 @@ - Bump Android SDK from v7.0.0 to v7.1.0 ([#1788](https://github.com/getsentry/sentry-dart/pull/1788)) - [changelog](https://github.com/getsentry/sentry-java/blob/main/CHANGELOG.md#710) - [diff](https://github.com/getsentry/sentry-java/compare/7.0.0...7.1.0) +- Bump Cocoa SDK from v8.17.2 to v8.18.0 ([#1803](https://github.com/getsentry/sentry-dart/pull/1803)) + - [changelog](https://github.com/getsentry/sentry-cocoa/blob/main/CHANGELOG.md#8180) + - [diff](https://github.com/getsentry/sentry-cocoa/compare/8.17.2...8.18.0) ## 7.14.0 diff --git a/flutter/ios/sentry_flutter.podspec b/flutter/ios/sentry_flutter.podspec index 15edfce6d7..1dc2c0fa06 100644 --- a/flutter/ios/sentry_flutter.podspec +++ b/flutter/ios/sentry_flutter.podspec @@ -12,7 +12,7 @@ Sentry SDK for Flutter with support to native through sentry-cocoa. :tag => s.version.to_s } s.source_files = 'Classes/**/*' s.public_header_files = 'Classes/**/*.h' - s.dependency 'Sentry/HybridSDK', '8.17.2' + s.dependency 'Sentry/HybridSDK', '8.18.0' s.ios.dependency 'Flutter' s.osx.dependency 'FlutterMacOS' s.ios.deployment_target = '11.0' diff --git a/flutter/lib/src/native/cocoa/binding.dart b/flutter/lib/src/native/cocoa/binding.dart index 646a6bea83..d614c12b1b 100644 --- a/flutter/lib/src/native/cocoa/binding.dart +++ b/flutter/lib/src/native/cocoa/binding.dart @@ -37603,7 +37603,8 @@ class ObjCBlock_bool_ObjCObject_ffiUnsignedLong_bool extends _ObjCBlockBase { ObjCBlock_bool_ObjCObject_ffiUnsignedLong_bool.fromFunctionPointer( SentryCocoa lib, ffi.Pointer< - ffi.NativeFunction< + ffi + .NativeFunction< ffi.Bool Function(ffi.Pointer arg0, ffi.UnsignedLong arg1, ffi.Pointer arg2)>> ptr) @@ -42031,15 +42032,17 @@ class ObjCBlock_bool_ObjCObject_bool extends _ObjCBlockBase { ffi.Pointer arg1)>> ptr) : this._( - lib._newBlock1( - _cFuncTrampoline ??= ffi.Pointer.fromFunction< - ffi.Bool Function( - ffi.Pointer<_ObjCBlock> block, - ffi.Pointer arg0, - ffi.Pointer arg1)>( - _ObjCBlock_bool_ObjCObject_bool_fnPtrTrampoline, false) - .cast(), - ptr.cast()), + lib + ._newBlock1( + _cFuncTrampoline ??= ffi.Pointer.fromFunction< + ffi.Bool Function( + ffi.Pointer<_ObjCBlock> block, + ffi.Pointer arg0, + ffi.Pointer arg1)>( + _ObjCBlock_bool_ObjCObject_bool_fnPtrTrampoline, + false) + .cast(), + ptr.cast()), lib); static ffi.Pointer? _cFuncTrampoline; @@ -70495,15 +70498,18 @@ class PrivateSentrySDKOnly extends NSObject { /// Collect a profiler session data associated with the given @c SentryId. /// This also discards the profiler. - static NSDictionary collectProfileBetween_and_forTrace_(SentryCocoa _lib, - int startSystemTime, int endSystemTime, SentryId? traceId) { + static NSMutableDictionary collectProfileBetween_and_forTrace_( + SentryCocoa _lib, + int startSystemTime, + int endSystemTime, + SentryId? traceId) { final _ret = _lib._objc_msgSend_1059( _lib._class_PrivateSentrySDKOnly1, _lib._sel_collectProfileBetween_and_forTrace_1, startSystemTime, endSystemTime, traceId?._id ?? ffi.nullptr); - return NSDictionary._(_ret, _lib, retain: true, release: true); + return NSMutableDictionary._(_ret, _lib, retain: true, release: true); } /// Discard profiler session data associated with the given @c SentryId. From d0312c9616494d7365a21482a4564461e3bbd14d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20Andra=C5=A1ec?= Date: Tue, 9 Jan 2024 10:10:06 +0000 Subject: [PATCH 048/237] Add `beforeScreenshotCallback` to `SentryFlutterOptions` (#1805) --- CHANGELOG.md | 1 + .../screenshot_event_processor.dart | 26 ++++++ flutter/lib/src/native/cocoa/binding.dart | 23 +++-- flutter/lib/src/sentry_flutter_options.dart | 17 +++- .../screenshot_event_processor_test.dart | 88 ++++++++++++++++++- 5 files changed, 139 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 864bc01d69..f822c59ae8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ - APM for isar ([#1726](https://github.com/getsentry/sentry-dart/pull/1726)) - Add isar breadcrumbs ([#1800](https://github.com/getsentry/sentry-dart/pull/1800)) - Starting with Flutter 3.16, Sentry adds the [`appFlavor`](https://api.flutter.dev/flutter/services/appFlavor-constant.html) to the `flutter_context` ([#1799](https://github.com/getsentry/sentry-dart/pull/1799)) +- Add beforeScreenshotCallback to SentryFlutterOptions ([#1805](https://github.com/getsentry/sentry-dart/pull/1805)) ### Dependencies diff --git a/flutter/lib/src/event_processor/screenshot_event_processor.dart b/flutter/lib/src/event_processor/screenshot_event_processor.dart index 263722fdad..48e0a4c4d6 100644 --- a/flutter/lib/src/event_processor/screenshot_event_processor.dart +++ b/flutter/lib/src/event_processor/screenshot_event_processor.dart @@ -30,6 +30,32 @@ class ScreenshotEventProcessor implements EventProcessor { _hasSentryScreenshotWidget) { return event; } + final beforeScreenshot = _options.beforeScreenshot; + if (beforeScreenshot != null) { + try { + final result = beforeScreenshot(event, hint: hint); + bool takeScreenshot; + if (result is Future) { + takeScreenshot = await result; + } else { + takeScreenshot = result; + } + if (!takeScreenshot) { + return event; + } + } catch (exception, stackTrace) { + _options.logger( + SentryLevel.error, + 'The beforeScreenshot callback threw an exception', + exception: exception, + stackTrace: stackTrace, + ); + // ignore: invalid_use_of_internal_member + if (_options.automatedTestMode) { + rethrow; + } + } + } final renderer = _options.rendererWrapper.getRenderer(); diff --git a/flutter/lib/src/native/cocoa/binding.dart b/flutter/lib/src/native/cocoa/binding.dart index d614c12b1b..41350a3a2c 100644 --- a/flutter/lib/src/native/cocoa/binding.dart +++ b/flutter/lib/src/native/cocoa/binding.dart @@ -37603,8 +37603,7 @@ class ObjCBlock_bool_ObjCObject_ffiUnsignedLong_bool extends _ObjCBlockBase { ObjCBlock_bool_ObjCObject_ffiUnsignedLong_bool.fromFunctionPointer( SentryCocoa lib, ffi.Pointer< - ffi - .NativeFunction< + ffi.NativeFunction< ffi.Bool Function(ffi.Pointer arg0, ffi.UnsignedLong arg1, ffi.Pointer arg2)>> ptr) @@ -42032,17 +42031,15 @@ class ObjCBlock_bool_ObjCObject_bool extends _ObjCBlockBase { ffi.Pointer arg1)>> ptr) : this._( - lib - ._newBlock1( - _cFuncTrampoline ??= ffi.Pointer.fromFunction< - ffi.Bool Function( - ffi.Pointer<_ObjCBlock> block, - ffi.Pointer arg0, - ffi.Pointer arg1)>( - _ObjCBlock_bool_ObjCObject_bool_fnPtrTrampoline, - false) - .cast(), - ptr.cast()), + lib._newBlock1( + _cFuncTrampoline ??= ffi.Pointer.fromFunction< + ffi.Bool Function( + ffi.Pointer<_ObjCBlock> block, + ffi.Pointer arg0, + ffi.Pointer arg1)>( + _ObjCBlock_bool_ObjCObject_bool_fnPtrTrampoline, false) + .cast(), + ptr.cast()), lib); static ffi.Pointer? _cFuncTrampoline; diff --git a/flutter/lib/src/sentry_flutter_options.dart b/flutter/lib/src/sentry_flutter_options.dart index 3806397465..ee722f8e9e 100644 --- a/flutter/lib/src/sentry_flutter_options.dart +++ b/flutter/lib/src/sentry_flutter_options.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:meta/meta.dart'; import 'package:sentry/sentry.dart'; import 'package:flutter/widgets.dart'; @@ -5,8 +7,9 @@ import 'package:flutter/widgets.dart'; import 'binding_wrapper.dart'; import 'renderer/renderer.dart'; import 'screenshot/sentry_screenshot_quality.dart'; +import 'event_processor/screenshot_event_processor.dart'; -/// This class adds options which are only availble in a Flutter environment. +/// This class adds options which are only available in a Flutter environment. /// Note that some of these options require native Sentry integration, which is /// not available on all platforms. class SentryFlutterOptions extends SentryOptions { @@ -169,6 +172,11 @@ class SentryFlutterOptions extends SentryOptions { /// Only attach a screenshot when the app is resumed. bool attachScreenshotOnlyWhenResumed = false; + /// Sets a callback which is executed before capturing screenshots. Only + /// relevant if `attachScreenshot` is set to true. When false is returned + /// from the function, no screenshot will be attached. + BeforeScreenshotCallback? beforeScreenshot; + /// Enable or disable automatic breadcrumbs for User interactions Using [Listener] /// /// Requires adding the [SentryUserInteractionWidget] to the widget tree. @@ -289,3 +297,10 @@ class SentryFlutterOptions extends SentryOptions { /// The [navigatorKey] is used to add information of the currently used locale to the contexts. GlobalKey? navigatorKey; } + +/// Callback being executed in [ScreenshotEventProcessor], deciding if a +/// screenshot should be recorded and attached. +typedef BeforeScreenshotCallback = FutureOr Function( + SentryEvent event, { + Hint? hint, +}); diff --git a/flutter/test/event_processor/screenshot_event_processor_test.dart b/flutter/test/event_processor/screenshot_event_processor_test.dart index e0ed2eb182..4beeea3ef3 100644 --- a/flutter/test/event_processor/screenshot_event_processor_test.dart +++ b/flutter/test/event_processor/screenshot_event_processor_test.dart @@ -14,6 +14,9 @@ void main() { TestWidgetsFlutterBinding.ensureInitialized(); late Fixture fixture; + late SentryEvent event; + late Hint hint; + setUp(() { fixture = Fixture(); }); @@ -34,8 +37,8 @@ void main() { textDirection: TextDirection.ltr))); final throwable = Exception(); - final event = SentryEvent(throwable: throwable); - final hint = Hint(); + event = SentryEvent(throwable: throwable); + hint = Hint(); await sut.apply(event, hint: hint); expect(hint.screenshot != null, added); @@ -91,6 +94,87 @@ void main() { await _addScreenshotAttachment(tester, null, added: true, isWeb: false, expectedMaxWidthOrHeight: widthOrHeight); }); + + group('beforeScreenshot', () { + testWidgets('does add screenshot if beforeScreenshot returns true', + (tester) async { + fixture.options.beforeScreenshot = (SentryEvent event, {Hint? hint}) { + return true; + }; + await _addScreenshotAttachment(tester, FlutterRenderer.canvasKit, + added: true, isWeb: false); + }); + + testWidgets('does add screenshot if async beforeScreenshot returns true', + (tester) async { + fixture.options.beforeScreenshot = + (SentryEvent event, {Hint? hint}) async { + await Future.delayed(Duration(milliseconds: 1)); + return true; + }; + await _addScreenshotAttachment(tester, FlutterRenderer.canvasKit, + added: true, isWeb: false); + }); + + testWidgets('does not add screenshot if beforeScreenshot returns false', + (tester) async { + fixture.options.beforeScreenshot = (SentryEvent event, {Hint? hint}) { + return false; + }; + await _addScreenshotAttachment(tester, FlutterRenderer.canvasKit, + added: false, isWeb: false); + }); + + testWidgets( + 'does not add screenshot if async beforeScreenshot returns false', + (tester) async { + fixture.options.beforeScreenshot = + (SentryEvent event, {Hint? hint}) async { + await Future.delayed(Duration(milliseconds: 1)); + return false; + }; + await _addScreenshotAttachment(tester, FlutterRenderer.canvasKit, + added: false, isWeb: false); + }); + + testWidgets('does add screenshot if beforeScreenshot throws', + (tester) async { + fixture.options.beforeScreenshot = (SentryEvent event, {Hint? hint}) { + throw Error(); + }; + await _addScreenshotAttachment(tester, FlutterRenderer.canvasKit, + added: true, isWeb: false); + }); + + testWidgets('does add screenshot if async beforeScreenshot throws', + (tester) async { + fixture.options.beforeScreenshot = + (SentryEvent event, {Hint? hint}) async { + await Future.delayed(Duration(milliseconds: 1)); + throw Error(); + }; + await _addScreenshotAttachment(tester, FlutterRenderer.canvasKit, + added: true, isWeb: false); + }); + + testWidgets('passes event & hint to beforeScreenshot callback', + (tester) async { + SentryEvent? beforeScreenshotEvent; + Hint? beforeScreenshotHint; + + fixture.options.beforeScreenshot = (SentryEvent event, {Hint? hint}) { + beforeScreenshotEvent = event; + beforeScreenshotHint = hint; + return true; + }; + + await _addScreenshotAttachment(tester, FlutterRenderer.canvasKit, + added: true, isWeb: false); + + expect(beforeScreenshotEvent, event); + expect(beforeScreenshotHint, hint); + }); + }); } class Fixture { From 92562b3ddcfddb3573653eb00bd135912ae84b5e Mon Sep 17 00:00:00 2001 From: Oleg Magomedov <69794332+smart7even@users.noreply.github.com> Date: Mon, 15 Jan 2024 12:29:55 +0300 Subject: [PATCH 049/237] fix typo in docs (#1816) --- flutter/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flutter/README.md b/flutter/README.md index ed8b2d2007..41e835aea8 100644 --- a/flutter/README.md +++ b/flutter/README.md @@ -99,7 +99,7 @@ runApp( ); ``` -This adds performance tracing for all `AssetBundle` usages, where the `AssetBundle` is accessed with `DefaultAssetBunlde.of(context)`. +This adds performance tracing for all `AssetBundle` usages, where the `AssetBundle` is accessed with `DefaultAssetBundle.of(context)`. This includes all of Flutters internal access of `AssetBundle`s, like `Image.asset` for example. ##### Tracking HTTP events From 24b6e601e2c8a3bc70ac06d1d0293067d3df5351 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 15 Jan 2024 12:17:38 +0100 Subject: [PATCH 050/237] chore: update metrics/flutter.properties to 3.16.7 (#1814) Co-authored-by: GitHub --- metrics/flutter.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/metrics/flutter.properties b/metrics/flutter.properties index 8ec4606076..d423be6b0c 100644 --- a/metrics/flutter.properties +++ b/metrics/flutter.properties @@ -1,2 +1,2 @@ -version = 3.16.5 +version = 3.16.7 repo = https://github.com/flutter/flutter From 552c543f85f4895866773acf3782c5f53b2e539f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20Andra=C5=A1ec?= Date: Wed, 17 Jan 2024 09:01:28 +0000 Subject: [PATCH 051/237] Add support for `readTransaction` in `sqflite` (#1819) --- CHANGELOG.md | 3 +- sqflite/lib/src/sentry_database.dart | 93 +++++++++++++++++++++++++- sqflite/test/sentry_database_test.dart | 42 ++++++++++++ 3 files changed, 134 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f822c59ae8..fd7f354246 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,8 @@ - Add isar breadcrumbs ([#1800](https://github.com/getsentry/sentry-dart/pull/1800)) - Starting with Flutter 3.16, Sentry adds the [`appFlavor`](https://api.flutter.dev/flutter/services/appFlavor-constant.html) to the `flutter_context` ([#1799](https://github.com/getsentry/sentry-dart/pull/1799)) - Add beforeScreenshotCallback to SentryFlutterOptions ([#1805](https://github.com/getsentry/sentry-dart/pull/1805)) - +- Add support for `readTransaction` in `sqflite` ([#1819](https://github.com/getsentry/sentry-dart/pull/1819)) + ### Dependencies - Bump Android SDK from v7.0.0 to v7.1.0 ([#1788](https://github.com/getsentry/sentry-dart/pull/1788)) diff --git a/sqflite/lib/src/sentry_database.dart b/sqflite/lib/src/sentry_database.dart index fafcad06d9..23ac1dae63 100644 --- a/sqflite/lib/src/sentry_database.dart +++ b/sqflite/lib/src/sentry_database.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:meta/meta.dart'; import 'package:sentry/sentry.dart'; import 'package:sqflite/sqflite.dart'; @@ -32,7 +34,10 @@ class SentryDatabase extends SentryDatabaseExecutor implements Database { // ignore: public_member_api_docs static const dbSqlQueryOp = 'db.sql.query'; - static const _dbSqlOp = 'db.sql.transaction'; + static const _dbSqlTransactionOp = 'db.sql.transaction'; + + static const _dbSqlReadTransactionOp = 'db.sql.read_transaction'; + @internal // ignore: public_member_api_docs static const dbSystemKey = 'db.system'; @@ -143,7 +148,7 @@ class SentryDatabase extends SentryDatabaseExecutor implements Database { final currentSpan = _hub.getSpan(); final description = 'Transaction DB: ${_database.path}'; final span = currentSpan?.startChild( - _dbSqlOp, + _dbSqlTransactionOp, description: description, ); // ignore: invalid_use_of_internal_member @@ -152,7 +157,7 @@ class SentryDatabase extends SentryDatabaseExecutor implements Database { var breadcrumb = Breadcrumb( message: description, - category: _dbSqlOp, + category: _dbSqlTransactionOp, data: {}, type: 'query', ); @@ -196,4 +201,86 @@ class SentryDatabase extends SentryDatabaseExecutor implements Database { } }); } + + @override + // ignore: override_on_non_overriding_member, public_member_api_docs + Future readTransaction(Future Function(Transaction txn) action) { + return Future(() async { + final currentSpan = _hub.getSpan(); + final description = 'Transaction DB: ${_database.path}'; + final span = currentSpan?.startChild( + _dbSqlReadTransactionOp, + description: description, + ); + // ignore: invalid_use_of_internal_member + span?.origin = SentryTraceOrigins.autoDbSqfliteDatabase; + setDatabaseAttributeData(span, dbName); + + var breadcrumb = Breadcrumb( + message: description, + category: _dbSqlReadTransactionOp, + data: {}, + type: 'query', + ); + setDatabaseAttributeOnBreadcrumb(breadcrumb, dbName); + + Future newAction(Transaction txn) async { + final executor = SentryDatabaseExecutor( + txn, + parentSpan: span, + hub: _hub, + dbName: dbName, + ); + final sentrySqfliteTransaction = + SentrySqfliteTransaction(executor, hub: _hub, dbName: dbName); + + return await action(sentrySqfliteTransaction); + } + + try { + final futureOrResult = _resolvedReadTransaction(newAction); + T result; + + if (futureOrResult is Future) { + result = await futureOrResult; + } else { + result = futureOrResult; + } + + span?.status = SpanStatus.ok(); + breadcrumb.data?['status'] = 'ok'; + + return result; + } catch (exception) { + span?.throwable = exception; + span?.status = SpanStatus.internalError(); + breadcrumb.data?['status'] = 'internal_error'; + breadcrumb = breadcrumb.copyWith( + level: SentryLevel.warning, + ); + + rethrow; + } finally { + await span?.finish(); + + // ignore: invalid_use_of_internal_member + await _hub.scope.addBreadcrumb(breadcrumb); + } + }); + } + + FutureOr _resolvedReadTransaction( + Future Function(Transaction txn) action, + ) async { + try { + // ignore: return_of_invalid_type + final result = await (_database as dynamic).readTransaction(action); + // Await and cast, as directly returning the future resulted in a runtime error. + return result as T; + } on NoSuchMethodError catch (_) { + // The `readTransaction` does not exists on sqflite version < 2.5.0+2. + // Fallback to transaction instead. + return _database.transaction(action); + } + } } diff --git a/sqflite/test/sentry_database_test.dart b/sqflite/test/sentry_database_test.dart index ad1a07b360..492da311df 100644 --- a/sqflite/test/sentry_database_test.dart +++ b/sqflite/test/sentry_database_test.dart @@ -107,6 +107,27 @@ void main() { await db.close(); }); + test('creates readTransaction span', () async { + final db = await fixture.getSut(); + + await db.readTransaction((txn) async { + expect(txn is SentrySqfliteTransaction, true); + }); + final span = fixture.tracer.children.last; + expect(span.context.operation, 'db.sql.read_transaction'); + expect(span.context.description, 'Transaction DB: $inMemoryDatabasePath'); + expect(span.status, SpanStatus.ok()); + expect(span.data[SentryDatabase.dbSystemKey], SentryDatabase.dbSystem); + expect(span.data[SentryDatabase.dbNameKey], inMemoryDatabasePath); + expect( + span.origin, + // ignore: invalid_use_of_internal_member + SentryTraceOrigins.autoDbSqfliteDatabase, + ); + + await db.close(); + }); + test('creates transaction breadcrumb', () async { final db = await fixture.getSut(); @@ -128,6 +149,27 @@ void main() { await db.close(); }); + test('creates readTransaction breadcrumb', () async { + final db = await fixture.getSut(); + + await db.readTransaction((txn) async { + expect(txn is SentrySqfliteTransaction, true); + }); + + final breadcrumb = fixture.hub.scope.breadcrumbs.first; + expect(breadcrumb.message, 'Transaction DB: $inMemoryDatabasePath'); + expect(breadcrumb.category, 'db.sql.read_transaction'); + expect(breadcrumb.data?['status'], 'ok'); + expect( + breadcrumb.data?[SentryDatabase.dbSystemKey], + SentryDatabase.dbSystem, + ); + expect(breadcrumb.data?[SentryDatabase.dbNameKey], inMemoryDatabasePath); + expect(breadcrumb.type, 'query'); + + await db.close(); + }); + test('creates transaction children run by the transaction', () async { final db = await fixture.getSut(); From d68bee781fa063972c3b0e8341c49be33f593441 Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Mon, 22 Jan 2024 13:54:19 -0500 Subject: [PATCH 052/237] ci: disable some tests temporarily (#1835) --- .github/workflows/dart.yml | 3 ++- .github/workflows/flutter_test.yml | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml index 779cf5ea90..2eedf96de9 100644 --- a/.github/workflows/dart.yml +++ b/.github/workflows/dart.yml @@ -31,7 +31,8 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest, windows-latest, macos-latest] + # TODO: exclude windows for now, because of failing tests in the new image runner + os: [ubuntu-latest, macos-latest] sdk: [stable, beta] exclude: - os: windows-latest diff --git a/.github/workflows/flutter_test.yml b/.github/workflows/flutter_test.yml index d1ce043f54..33990219b3 100644 --- a/.github/workflows/flutter_test.yml +++ b/.github/workflows/flutter_test.yml @@ -120,7 +120,8 @@ jobs: fail-fast: false matrix: sdk: ["stable", "beta"] - target: ["ios", "macos"] + # TODO: remove ios for now, will be fixed in v8 + target: ["macos"] steps: - name: checkout uses: actions/checkout@v4 From 7551d2930b29d9a29747d4786134d2614a84594e Mon Sep 17 00:00:00 2001 From: getsentry-bot Date: Mon, 22 Jan 2024 19:17:46 +0000 Subject: [PATCH 053/237] release: 7.15.0 --- CHANGELOG.md | 2 +- dart/lib/src/version.dart | 2 +- dart/pubspec.yaml | 2 +- dio/lib/src/version.dart | 2 +- dio/pubspec.yaml | 4 ++-- drift/lib/src/version.dart | 2 +- drift/pubspec.yaml | 4 ++-- file/lib/src/version.dart | 2 +- file/pubspec.yaml | 4 ++-- flutter/example/pubspec.yaml | 2 +- flutter/lib/src/version.dart | 2 +- flutter/pubspec.yaml | 4 ++-- hive/lib/src/version.dart | 2 +- hive/pubspec.yaml | 4 ++-- isar/lib/src/version.dart | 2 +- isar/pubspec.yaml | 4 ++-- logging/lib/src/version.dart | 2 +- logging/pubspec.yaml | 4 ++-- sqflite/lib/src/version.dart | 2 +- sqflite/pubspec.yaml | 4 ++-- 20 files changed, 28 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fd7f354246..e073b7b29f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## Unreleased +## 7.15.0 ### Features diff --git a/dart/lib/src/version.dart b/dart/lib/src/version.dart index dc38fd3e11..cd68dd9443 100644 --- a/dart/lib/src/version.dart +++ b/dart/lib/src/version.dart @@ -9,7 +9,7 @@ library version; /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.14.0'; +const String sdkVersion = '7.15.0'; String sdkName(bool isWeb) => isWeb ? _browserSdkName : _ioSdkName; diff --git a/dart/pubspec.yaml b/dart/pubspec.yaml index 2580a618d3..e4668ad96d 100644 --- a/dart/pubspec.yaml +++ b/dart/pubspec.yaml @@ -1,5 +1,5 @@ name: sentry -version: 7.14.0 +version: 7.15.0 description: > A crash reporting library for Dart that sends crash reports to Sentry.io. This library supports Dart VM and Web. For Flutter consider sentry_flutter instead. diff --git a/dio/lib/src/version.dart b/dio/lib/src/version.dart index 9737ee6520..a0d410b5dd 100644 --- a/dio/lib/src/version.dart +++ b/dio/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.14.0'; +const String sdkVersion = '7.15.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_dio'; diff --git a/dio/pubspec.yaml b/dio/pubspec.yaml index 92e57a96a9..abd613d381 100644 --- a/dio/pubspec.yaml +++ b/dio/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_dio description: An integration which adds support for performance tracing for the Dio package. -version: 7.14.0 +version: 7.15.0 homepage: https://docs.sentry.io/platforms/dart/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -11,7 +11,7 @@ environment: dependencies: dio: ^5.0.0 - sentry: 7.14.0 + sentry: 7.15.0 dev_dependencies: meta: ^1.3.0 diff --git a/drift/lib/src/version.dart b/drift/lib/src/version.dart index 621ab96e95..0a1bc2ce4d 100644 --- a/drift/lib/src/version.dart +++ b/drift/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.14.0'; +const String sdkVersion = '7.15.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_drift'; diff --git a/drift/pubspec.yaml b/drift/pubspec.yaml index df6380ba9d..af1d524c8b 100644 --- a/drift/pubspec.yaml +++ b/drift/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_drift description: An integration which adds support for performance tracing for the drift package. -version: 7.14.0 +version: 7.15.0 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -10,7 +10,7 @@ environment: flutter: '>=3.3.0' dependencies: - sentry: 7.14.0 + sentry: 7.15.0 meta: ^1.3.0 drift: ^2.13.0 diff --git a/file/lib/src/version.dart b/file/lib/src/version.dart index 6900c8de5d..27f4d170a5 100644 --- a/file/lib/src/version.dart +++ b/file/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.14.0'; +const String sdkVersion = '7.15.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_file'; diff --git a/file/pubspec.yaml b/file/pubspec.yaml index 273124df8f..60c56c6248 100644 --- a/file/pubspec.yaml +++ b/file/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_file description: An integration which adds support for performance tracing for dart.io.File. -version: 7.14.0 +version: 7.15.0 homepage: https://docs.sentry.io/platforms/dart/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -10,7 +10,7 @@ environment: sdk: '>=2.19.0 <4.0.0' dependencies: - sentry: 7.14.0 + sentry: 7.15.0 meta: ^1.3.0 dev_dependencies: diff --git a/flutter/example/pubspec.yaml b/flutter/example/pubspec.yaml index 0f279e8e8f..bb021595c1 100644 --- a/flutter/example/pubspec.yaml +++ b/flutter/example/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_flutter_example description: Demonstrates how to use the sentry_flutter plugin. -version: 7.14.0 +version: 7.15.0 publish_to: 'none' # Remove this line if you wish to publish to pub.dev diff --git a/flutter/lib/src/version.dart b/flutter/lib/src/version.dart index ff71dd6e87..dd50a348fd 100644 --- a/flutter/lib/src/version.dart +++ b/flutter/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.14.0'; +const String sdkVersion = '7.15.0'; /// The default SDK name reported to Sentry.io in the submitted events. const String sdkName = 'sentry.dart.flutter'; diff --git a/flutter/pubspec.yaml b/flutter/pubspec.yaml index d06f95e31e..c41ef8d6b0 100644 --- a/flutter/pubspec.yaml +++ b/flutter/pubspec.yaml @@ -1,5 +1,5 @@ name: sentry_flutter -version: 7.14.0 +version: 7.15.0 description: Sentry SDK for Flutter. This package aims to support different Flutter targets by relying on the many platforms supported by Sentry with native SDKs. homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart @@ -15,7 +15,7 @@ dependencies: sdk: flutter flutter_web_plugins: sdk: flutter - sentry: 7.14.0 + sentry: 7.15.0 package_info_plus: '>=1.0.0 <=5.0.1' meta: ^1.3.0 ffi: ^2.0.0 diff --git a/hive/lib/src/version.dart b/hive/lib/src/version.dart index 08b6cbe335..b775854f98 100644 --- a/hive/lib/src/version.dart +++ b/hive/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.14.0'; +const String sdkVersion = '7.15.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_hive'; diff --git a/hive/pubspec.yaml b/hive/pubspec.yaml index 1bdad09235..4a8ac02d4e 100644 --- a/hive/pubspec.yaml +++ b/hive/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_hive description: An integration which adds support for performance tracing for the hive package. -version: 7.14.0 +version: 7.15.0 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -9,7 +9,7 @@ environment: sdk: '>=2.17.0 <4.0.0' dependencies: - sentry: 7.14.0 + sentry: 7.15.0 hive: ^2.2.3 meta: ^1.3.0 diff --git a/isar/lib/src/version.dart b/isar/lib/src/version.dart index 7c1a7d4031..8d8ef99293 100644 --- a/isar/lib/src/version.dart +++ b/isar/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.13.1'; +const String sdkVersion = '7.15.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_isar'; diff --git a/isar/pubspec.yaml b/isar/pubspec.yaml index df066786f8..f618fe7543 100644 --- a/isar/pubspec.yaml +++ b/isar/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_isar description: An integration which adds support for performance tracing for the isar package. -version: 7.13.1 +version: 7.15.0 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -12,7 +12,7 @@ environment: dependencies: isar: ^3.1.0 isar_flutter_libs: ^3.1.0 # contains Isar Core - sentry: 7.14.0 + sentry: 7.15.0 meta: ^1.3.0 path: ^1.8.3 diff --git a/logging/lib/src/version.dart b/logging/lib/src/version.dart index b1e21478f7..45fd9a81a7 100644 --- a/logging/lib/src/version.dart +++ b/logging/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.14.0'; +const String sdkVersion = '7.15.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_logging'; diff --git a/logging/pubspec.yaml b/logging/pubspec.yaml index 02cef6966a..71de51c471 100644 --- a/logging/pubspec.yaml +++ b/logging/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_logging description: An integration which adds support for recording log from the logging package. -version: 7.14.0 +version: 7.15.0 homepage: https://docs.sentry.io/platforms/dart/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -11,7 +11,7 @@ environment: dependencies: logging: ^1.0.0 - sentry: 7.14.0 + sentry: 7.15.0 dev_dependencies: lints: ^3.0.0 diff --git a/sqflite/lib/src/version.dart b/sqflite/lib/src/version.dart index 9c361f297d..e0f78f9f60 100644 --- a/sqflite/lib/src/version.dart +++ b/sqflite/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.14.0'; +const String sdkVersion = '7.15.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_sqflite'; diff --git a/sqflite/pubspec.yaml b/sqflite/pubspec.yaml index 22188a8d91..d3e48214b3 100644 --- a/sqflite/pubspec.yaml +++ b/sqflite/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_sqflite description: An integration which adds support for performance tracing for the sqflite package. -version: 7.14.0 +version: 7.15.0 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -10,7 +10,7 @@ environment: flutter: '>=3.3.0' # matching sqflite dependencies: - sentry: 7.14.0 + sentry: 7.15.0 sqflite: ^2.0.0 sqflite_common: ^2.0.0 meta: ^1.3.0 From 270031a1b1eeaa94c3225fc05854352ce4786027 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20Andra=C5=A1ec?= Date: Tue, 23 Jan 2024 13:11:49 +0000 Subject: [PATCH 054/237] Accept `Map` in `Hint` class (#1807) --- CHANGELOG.md | 11 +++++++++++ dart/lib/src/hint.dart | 18 ++++++++++-------- dart/test/hint_test.dart | 17 +++++++++++++++++ 3 files changed, 38 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e073b7b29f..fc9e7352bd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,16 @@ # Changelog +## Unreleased + +### Features + +- Accept `Map` in `Hint` class ([#1807](https://github.com/getsentry/sentry-dart/pull/1807)) + - Please check if everything works as expected when using `Hint` + - Factory constructor `Hint.withMap(Map map)` now takes `Map` instead of `Map` + - Method `hint.addAll(Map keysAndValues)` now takes `Map` instead of `Map` + - Method `set(String key, dynamic value)` now takes value of `dynamic` instead of `Object` + - Method `hint.get(String key)` now returns `dynamic` instead of `Object?` + ## 7.15.0 ### Features diff --git a/dart/lib/src/hint.dart b/dart/lib/src/hint.dart index 87620d7ba1..aaa614518c 100644 --- a/dart/lib/src/hint.dart +++ b/dart/lib/src/hint.dart @@ -40,7 +40,7 @@ import 'sentry_attachment/sentry_attachment.dart'; /// }; /// ``` class Hint { - final Map _internalStorage = {}; + final Map _internalStorage = {}; final List attachments = []; @@ -62,7 +62,7 @@ class Hint { return hint; } - factory Hint.withMap(Map map) { + factory Hint.withMap(Map map) { final hint = Hint(); hint.addAll(map); return hint; @@ -80,17 +80,19 @@ class Hint { return hint; } - // Objects + // Key/Value Storage - void addAll(Map keysAndValues) { - _internalStorage.addAll(keysAndValues); + void addAll(Map keysAndValues) { + final withoutNullValues = + keysAndValues.map((key, value) => MapEntry(key, value ?? "null")); + _internalStorage.addAll(withoutNullValues); } - void set(String key, Object value) { - _internalStorage[key] = value; + void set(String key, dynamic value) { + _internalStorage[key] = value ?? "null"; } - Object? get(String key) { + dynamic get(String key) { return _internalStorage[key]; } diff --git a/dart/test/hint_test.dart b/dart/test/hint_test.dart index d46a022405..04c09a28a0 100644 --- a/dart/test/hint_test.dart +++ b/dart/test/hint_test.dart @@ -82,6 +82,23 @@ void main() { expect(sut.screenshot, attachment); expect(sut.viewHierarchy, attachment); }); + + test('Hint init with map null fallback', () { + final hint = Hint.withMap({'fixture-key': null}); + expect("null", hint.get("fixture-key")); + }); + + test('Hint addAll with map null fallback', () { + final hint = Hint(); + hint.addAll({'fixture-key': null}); + expect("null", hint.get("fixture-key")); + }); + + test('Hint set with null value fallback', () { + final hint = Hint(); + hint.set("fixture-key", null); + expect("null", hint.get("fixture-key")); + }); } class Fixture { From f770c4cf27cf7af52784b27085d7efce09f70004 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 Jan 2024 10:05:54 -0500 Subject: [PATCH 055/237] build(deps): bump actions/cache from 3 to 4 (#1833) Bumps [actions/cache](https://github.com/actions/cache) from 3 to 4. - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/cache dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor --- .github/workflows/flutter_test.yml | 2 +- .github/workflows/metrics.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/flutter_test.yml b/.github/workflows/flutter_test.yml index 33990219b3..9a5b583420 100644 --- a/.github/workflows/flutter_test.yml +++ b/.github/workflows/flutter_test.yml @@ -57,7 +57,7 @@ jobs: uses: gradle/gradle-build-action@v2 - name: AVD cache - uses: actions/cache@v3 + uses: actions/cache@v4 id: avd-cache with: path: | diff --git a/.github/workflows/metrics.yml b/.github/workflows/metrics.yml index c190889723..1e383a93ea 100644 --- a/.github/workflows/metrics.yml +++ b/.github/workflows/metrics.yml @@ -65,7 +65,7 @@ jobs: - run: ./metrics/prepare.sh - - uses: actions/cache@v3 + - uses: actions/cache@v4 id: app-plain-cache with: path: ${{ matrix.appPlain }} From b4b36f589128e047dd1b1e97982328606e1d80e0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 Jan 2024 15:43:46 -0500 Subject: [PATCH 056/237] build(deps): bump dart-lang/setup-dart from 1.6.0 to 1.6.1 (#1817) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.6.0 to 1.6.1. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/b64355ae6ca0b5d484f0106a033dd1388965d06d...ca7e6fee45ffbd82b555a7ebfc236d2c86439f5b) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor --- .github/workflows/analyze.yml | 2 +- .github/workflows/dart.yml | 2 +- .github/workflows/diagrams.yml | 2 +- .github/workflows/dio.yml | 2 +- .github/workflows/e2e_dart.yml | 2 +- .github/workflows/file.yml | 2 +- .github/workflows/flutter-symbols.yml | 4 ++-- .github/workflows/format-and-fix.yml | 2 +- .github/workflows/hive.yml | 2 +- .github/workflows/logging.yml | 2 +- 10 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/analyze.yml b/.github/workflows/analyze.yml index 6218eaa27a..bde8004cec 100644 --- a/.github/workflows/analyze.yml +++ b/.github/workflows/analyze.yml @@ -32,7 +32,7 @@ jobs: working-directory: ${{ inputs.package }} steps: - uses: actions/checkout@v4 - - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d # pin@v1 + - uses: dart-lang/setup-dart@ca7e6fee45ffbd82b555a7ebfc236d2c86439f5b # pin@v1 if: ${{ inputs.sdk == 'dart' }} - uses: subosito/flutter-action@2783a3f08e1baf891508463f8c6653c258246225 # pin@v2.12.0 if: ${{ inputs.sdk == 'flutter' }} diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml index 2eedf96de9..b68c1426ee 100644 --- a/.github/workflows/dart.yml +++ b/.github/workflows/dart.yml @@ -40,7 +40,7 @@ jobs: - os: macos-latest sdk: beta steps: - - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d # pin@v1 + - uses: dart-lang/setup-dart@ca7e6fee45ffbd82b555a7ebfc236d2c86439f5b # pin@v1 with: sdk: ${{ matrix.sdk }} - uses: actions/checkout@v4 diff --git a/.github/workflows/diagrams.yml b/.github/workflows/diagrams.yml index a534112e8b..8b8cee500e 100644 --- a/.github/workflows/diagrams.yml +++ b/.github/workflows/diagrams.yml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-latest name: "Create class diagrams of all packages" steps: - - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d # pin@v1 + - uses: dart-lang/setup-dart@ca7e6fee45ffbd82b555a7ebfc236d2c86439f5b # pin@v1 with: sdk: stable diff --git a/.github/workflows/dio.yml b/.github/workflows/dio.yml index c85ab43a1a..8f9fa41dc5 100644 --- a/.github/workflows/dio.yml +++ b/.github/workflows/dio.yml @@ -40,7 +40,7 @@ jobs: - os: macos-latest sdk: beta steps: - - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d # pin@v1 + - uses: dart-lang/setup-dart@ca7e6fee45ffbd82b555a7ebfc236d2c86439f5b # pin@v1 with: sdk: ${{ matrix.sdk }} - uses: actions/checkout@v4 diff --git a/.github/workflows/e2e_dart.yml b/.github/workflows/e2e_dart.yml index 2d66eaf9e2..8a6953a0aa 100644 --- a/.github/workflows/e2e_dart.yml +++ b/.github/workflows/e2e_dart.yml @@ -37,7 +37,7 @@ jobs: matrix: sdk: [stable, beta] steps: - - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d # pin@v1 + - uses: dart-lang/setup-dart@ca7e6fee45ffbd82b555a7ebfc236d2c86439f5b # pin@v1 with: sdk: ${{ matrix.sdk }} - uses: actions/checkout@v4 diff --git a/.github/workflows/file.yml b/.github/workflows/file.yml index 322c24b22e..3d1431f63b 100644 --- a/.github/workflows/file.yml +++ b/.github/workflows/file.yml @@ -41,7 +41,7 @@ jobs: - os: macos-latest sdk: beta steps: - - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d # pin@v1 + - uses: dart-lang/setup-dart@ca7e6fee45ffbd82b555a7ebfc236d2c86439f5b # pin@v1 with: sdk: ${{ matrix.sdk }} - uses: actions/checkout@v4 diff --git a/.github/workflows/flutter-symbols.yml b/.github/workflows/flutter-symbols.yml index cf4af7c71c..4462ccccc8 100644 --- a/.github/workflows/flutter-symbols.yml +++ b/.github/workflows/flutter-symbols.yml @@ -21,7 +21,7 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d # pin@v1 + - uses: dart-lang/setup-dart@ca7e6fee45ffbd82b555a7ebfc236d2c86439f5b # pin@v1 - run: dart pub get @@ -33,7 +33,7 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d # pin@v1 + - uses: dart-lang/setup-dart@ca7e6fee45ffbd82b555a7ebfc236d2c86439f5b # pin@v1 - run: dart pub get diff --git a/.github/workflows/format-and-fix.yml b/.github/workflows/format-and-fix.yml index 89fc66cede..f7d0ec9cfb 100644 --- a/.github/workflows/format-and-fix.yml +++ b/.github/workflows/format-and-fix.yml @@ -30,7 +30,7 @@ jobs: working-directory: ${{ matrix.package.name }} steps: - uses: actions/checkout@v4 - - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d # pin@v1 + - uses: dart-lang/setup-dart@ca7e6fee45ffbd82b555a7ebfc236d2c86439f5b # pin@v1 if: ${{ matrix.package.sdk == 'dart' }} - uses: subosito/flutter-action@2783a3f08e1baf891508463f8c6653c258246225 # pin@v2.12.0 if: ${{ matrix.package.sdk == 'flutter' }} diff --git a/.github/workflows/hive.yml b/.github/workflows/hive.yml index 1ff1a8483e..15bef1ecdb 100644 --- a/.github/workflows/hive.yml +++ b/.github/workflows/hive.yml @@ -40,7 +40,7 @@ jobs: - os: macos-latest sdk: beta steps: - - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d # pin@v1 + - uses: dart-lang/setup-dart@ca7e6fee45ffbd82b555a7ebfc236d2c86439f5b # pin@v1 with: sdk: ${{ matrix.sdk }} - uses: actions/checkout@v4 diff --git a/.github/workflows/logging.yml b/.github/workflows/logging.yml index d6af6538bd..4e39833caa 100644 --- a/.github/workflows/logging.yml +++ b/.github/workflows/logging.yml @@ -40,7 +40,7 @@ jobs: - os: macos-latest sdk: beta steps: - - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d # pin@v1 + - uses: dart-lang/setup-dart@ca7e6fee45ffbd82b555a7ebfc236d2c86439f5b # pin@v1 with: sdk: ${{ matrix.sdk }} - uses: actions/checkout@v4 From 4477d2eb1051cec2f698e56dcaba09b1f87e2227 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 23 Jan 2024 15:44:04 -0500 Subject: [PATCH 057/237] chore(deps): update Flutter SDK (metrics) to v3.16.8 (#1825) * chore: update metrics/flutter.properties to 3.16.8 * update path --------- Co-authored-by: GitHub Co-authored-by: Giancarlo Buenaflor --- .github/workflows/flutter.yml | 1 + metrics/flutter.properties | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/flutter.yml b/.github/workflows/flutter.yml index e21b884a01..8847114974 100644 --- a/.github/workflows/flutter.yml +++ b/.github/workflows/flutter.yml @@ -11,6 +11,7 @@ on: - "!**/class-diagram.svg" - "dart/**" - "flutter/**" + - "metrics/flutter.properties" jobs: cancel-previous-workflow: diff --git a/metrics/flutter.properties b/metrics/flutter.properties index d423be6b0c..8a0f53ceea 100644 --- a/metrics/flutter.properties +++ b/metrics/flutter.properties @@ -1,2 +1,2 @@ -version = 3.16.7 +version = 3.16.8 repo = https://github.com/flutter/flutter From 2f0d4155e6da1ce20cb783aa4a0638b5cf277ce5 Mon Sep 17 00:00:00 2001 From: Igor Khramtsov Date: Wed, 24 Jan 2024 18:31:44 +0400 Subject: [PATCH 058/237] feat: tracing without performance for dio (#1837) * feat: tracing without performance for dio * chore: update CHANGELOG.md --- CHANGELOG.md | 1 + dio/lib/src/tracing_client_adapter.dart | 31 +++++++++++++++---- dio/test/tracing_client_adapter_test.dart | 37 ++++++++++++++++++----- 3 files changed, 56 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fc9e7352bd..c4509dcbf5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### Features +- Tracing without performance for Dio integration ([#1837](https://github.com/getsentry/sentry-dart/pull/1837)) - Accept `Map` in `Hint` class ([#1807](https://github.com/getsentry/sentry-dart/pull/1807)) - Please check if everything works as expected when using `Hint` - Factory constructor `Hint.withMap(Map map)` now takes `Map` instead of `Map` diff --git a/dio/lib/src/tracing_client_adapter.dart b/dio/lib/src/tracing_client_adapter.dart index 19a003b633..0c8def1442 100644 --- a/dio/lib/src/tracing_client_adapter.dart +++ b/dio/lib/src/tracing_client_adapter.dart @@ -51,12 +51,12 @@ class TracingClientAdapter implements HttpClientAdapter { ResponseBody? response; try { - if (span != null) { - if (containsTargetOrMatchesRegExp( - // ignore: invalid_use_of_internal_member - _hub.options.tracePropagationTargets, - options.uri.toString(), - )) { + if (containsTargetOrMatchesRegExp( + // ignore: invalid_use_of_internal_member + _hub.options.tracePropagationTargets, + options.uri.toString(), + )) { + if (span != null) { addSentryTraceHeaderFromSpan(span, options.headers); addBaggageHeaderFromSpan( span, @@ -64,6 +64,25 @@ class TracingClientAdapter implements HttpClientAdapter { // ignore: invalid_use_of_internal_member logger: _hub.options.logger, ); + } else { + // ignore: invalid_use_of_internal_member + final scope = _hub.scope; + // ignore: invalid_use_of_internal_member + final propagationContext = scope.propagationContext; + + final traceHeader = propagationContext.toSentryTrace(); + addSentryTraceHeader(traceHeader, options.headers); + + final baggage = propagationContext.baggage; + if (baggage != null) { + final baggageHeader = SentryBaggageHeader.fromBaggage(baggage); + addBaggageHeader( + baggageHeader, + options.headers, + // ignore: invalid_use_of_internal_member + logger: _hub.options.logger, + ); + } } } diff --git a/dio/test/tracing_client_adapter_test.dart b/dio/test/tracing_client_adapter_test.dart index b758c5a765..f67ec4c14d 100644 --- a/dio/test/tracing_client_adapter_test.dart +++ b/dio/test/tracing_client_adapter_test.dart @@ -127,25 +127,48 @@ void main() { ); }); - test('captured span do not add headers if NoOp', () async { + test('do not throw if no span bound to the scope', () async { + final sut = fixture.getSut( + client: fixture.getClient(statusCode: 200, reason: 'OK'), + ); + + await sut.get(requestOptions); + }); + + test('set headers from propagationContext when tracing is disabled', + () async { + fixture._options.enableTracing = false; final sut = fixture.getSut( client: fixture.getClient(statusCode: 200, reason: 'OK'), ); - await fixture._hub - .configureScope((scope) => scope.span = NoOpSentrySpan()); + + final propagationContext = fixture._hub.scope.propagationContext; + propagationContext.baggage = SentryBaggage({'foo': 'bar'}); final response = await sut.get(requestOptions); - expect(response.headers['baggage'], null); - expect(response.headers['sentry-trace'], null); + expect( + response.headers['sentry-trace'], + [propagationContext.toSentryTrace().value], + ); + expect(response.headers['baggage'], ['foo=bar']); }); - test('do not throw if no span bound to the scope', () async { + test('set headers from propagationContext when no transaction', () async { final sut = fixture.getSut( client: fixture.getClient(statusCode: 200, reason: 'OK'), ); - await sut.get(requestOptions); + final propagationContext = fixture._hub.scope.propagationContext; + propagationContext.baggage = SentryBaggage({'foo': 'bar'}); + + final response = await sut.get(requestOptions); + + expect( + response.headers['sentry-trace'], + [propagationContext.toSentryTrace().value], + ); + expect(response.headers['baggage'], ['foo=bar']); }); }); } From 920ec411c43151f7d10b9fc46ddfd5d348136599 Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Wed, 24 Jan 2024 14:07:36 -0500 Subject: [PATCH 059/237] chore: reenable testing sentry-dart on windows (#1838) * enable windows again * test with chrome * test with chrome * reenable windows test --- .github/workflows/dart.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml index b68c1426ee..6ce30080f8 100644 --- a/.github/workflows/dart.yml +++ b/.github/workflows/dart.yml @@ -31,8 +31,7 @@ jobs: strategy: fail-fast: false matrix: - # TODO: exclude windows for now, because of failing tests in the new image runner - os: [ubuntu-latest, macos-latest] + os: [ubuntu-latest, windows-latest, macos-latest] sdk: [stable, beta] exclude: - os: windows-latest From 7e4a1ec92cb05cfd6226a72e9533240aaa97f180 Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Wed, 24 Jan 2024 15:04:14 -0500 Subject: [PATCH 060/237] chore: add isar to craft (#1843) * add isar * Update Changelog --- .craft.yml | 1 + CHANGELOG.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.craft.yml b/.craft.yml index 45554efb25..ac5e86e3c7 100644 --- a/.craft.yml +++ b/.craft.yml @@ -13,6 +13,7 @@ targets: sqflite: hive: drift: + isar: - name: github - name: registry sdks: diff --git a/CHANGELOG.md b/CHANGELOG.md index c4509dcbf5..29749471f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### Features +- APM for isar ([#1726](https://github.com/getsentry/sentry-dart/pull/1726)) - Tracing without performance for Dio integration ([#1837](https://github.com/getsentry/sentry-dart/pull/1837)) - Accept `Map` in `Hint` class ([#1807](https://github.com/getsentry/sentry-dart/pull/1807)) - Please check if everything works as expected when using `Hint` @@ -20,7 +21,6 @@ - Set `options.spotlight = Spotlight(enabled: true)` to enable Spotlight - Add `ConnectivityIntegration` for web ([#1765](https://github.com/getsentry/sentry-dart/pull/1765)) - We only get the info if online/offline on web platform. The added breadcrumb is set to either `wifi` or `none`. -- APM for isar ([#1726](https://github.com/getsentry/sentry-dart/pull/1726)) - Add isar breadcrumbs ([#1800](https://github.com/getsentry/sentry-dart/pull/1800)) - Starting with Flutter 3.16, Sentry adds the [`appFlavor`](https://api.flutter.dev/flutter/services/appFlavor-constant.html) to the `flutter_context` ([#1799](https://github.com/getsentry/sentry-dart/pull/1799)) - Add beforeScreenshotCallback to SentryFlutterOptions ([#1805](https://github.com/getsentry/sentry-dart/pull/1805)) From bd1b99021721963c751db2b5418473c5cea711f1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 25 Jan 2024 11:06:00 -0500 Subject: [PATCH 061/237] chore(deps): update Cocoa SDK to v8.19.0 (#1844) * chore: update flutter/scripts/update-cocoa.sh to 8.19.0 --------- Co-authored-by: GitHub Co-authored-by: GIancarlo Buenaflor --- CHANGELOG.md | 2 +- flutter/ios/sentry_flutter.podspec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 29749471f6..b92af634f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ ### Features -- APM for isar ([#1726](https://github.com/getsentry/sentry-dart/pull/1726)) +- Performance monitoring support for isar ([#1726](https://github.com/getsentry/sentry-dart/pull/1726)) - Tracing without performance for Dio integration ([#1837](https://github.com/getsentry/sentry-dart/pull/1837)) - Accept `Map` in `Hint` class ([#1807](https://github.com/getsentry/sentry-dart/pull/1807)) - Please check if everything works as expected when using `Hint` diff --git a/flutter/ios/sentry_flutter.podspec b/flutter/ios/sentry_flutter.podspec index 1dc2c0fa06..03220ac7bf 100644 --- a/flutter/ios/sentry_flutter.podspec +++ b/flutter/ios/sentry_flutter.podspec @@ -12,7 +12,7 @@ Sentry SDK for Flutter with support to native through sentry-cocoa. :tag => s.version.to_s } s.source_files = 'Classes/**/*' s.public_header_files = 'Classes/**/*.h' - s.dependency 'Sentry/HybridSDK', '8.18.0' + s.dependency 'Sentry/HybridSDK', '8.19.0' s.ios.dependency 'Flutter' s.osx.dependency 'FlutterMacOS' s.ios.deployment_target = '11.0' From 413323059624e4ad389969782d04f7aa586c419a Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Tue, 30 Jan 2024 09:48:21 +0100 Subject: [PATCH 062/237] feat: Add sentry widget that includes other sentry widgets (#1846) * add sentry widget * Update CHANGELOG.md * Update CHANGELOG.md --- CHANGELOG.md | 3 + flutter/example/lib/main.dart | 10 +-- flutter/lib/sentry_flutter.dart | 1 + .../screenshot/sentry_screenshot_widget.dart | 31 ++++++-- flutter/lib/src/sentry_widget.dart | 23 ++++++ .../sentry_user_interaction_widget.dart | 16 ++-- .../screenshot_event_processor_test.dart | 7 ++ .../sentry_screenshot_widget_test.dart | 79 +++++++++++++++++++ flutter/test/sentry_widget_test.dart | 37 +++++++++ .../sentry_user_interaction_widget_test.dart | 69 ++++++++++++++++ 10 files changed, 258 insertions(+), 18 deletions(-) create mode 100644 flutter/lib/src/sentry_widget.dart create mode 100644 flutter/test/screenshot/sentry_screenshot_widget_test.dart create mode 100644 flutter/test/sentry_widget_test.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index b92af634f9..62207422c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ ### Features +- Add `SentryWidget` ([#1846](https://github.com/getsentry/sentry-dart/pull/1846)) + - Prefer to use `SentryWidget` now instead of `SentryScreenshotWidget` and `SentryUserInteractionWidget` directly +- APM for isar ([#1726](https://github.com/getsentry/sentry-dart/pull/1726)) - Performance monitoring support for isar ([#1726](https://github.com/getsentry/sentry-dart/pull/1726)) - Tracing without performance for Dio integration ([#1837](https://github.com/getsentry/sentry-dart/pull/1837)) - Accept `Map` in `Hint` class ([#1807](https://github.com/getsentry/sentry-dart/pull/1807)) diff --git a/flutter/example/lib/main.dart b/flutter/example/lib/main.dart index 4cb5b97942..26bbdce6d8 100644 --- a/flutter/example/lib/main.dart +++ b/flutter/example/lib/main.dart @@ -43,12 +43,10 @@ final GlobalKey navigatorKey = GlobalKey(); Future main() async { await setupSentry( () => runApp( - SentryScreenshotWidget( - child: SentryUserInteractionWidget( - child: DefaultAssetBundle( - bundle: SentryAssetBundle(), - child: const MyApp(), - ), + SentryWidget( + child: DefaultAssetBundle( + bundle: SentryAssetBundle(), + child: const MyApp(), ), ), ), diff --git a/flutter/lib/sentry_flutter.dart b/flutter/lib/sentry_flutter.dart index 6760e99efb..0f43bf741b 100644 --- a/flutter/lib/sentry_flutter.dart +++ b/flutter/lib/sentry_flutter.dart @@ -15,3 +15,4 @@ export 'src/screenshot/sentry_screenshot_widget.dart'; export 'src/screenshot/sentry_screenshot_quality.dart'; export 'src/user_interaction/sentry_user_interaction_widget.dart'; export 'src/binding_wrapper.dart'; +export 'src/sentry_widget.dart'; diff --git a/flutter/lib/src/screenshot/sentry_screenshot_widget.dart b/flutter/lib/src/screenshot/sentry_screenshot_widget.dart index b7273b8979..e83d46d0c5 100644 --- a/flutter/lib/src/screenshot/sentry_screenshot_widget.dart +++ b/flutter/lib/src/screenshot/sentry_screenshot_widget.dart @@ -1,6 +1,8 @@ import 'package:flutter/material.dart'; import 'package:meta/meta.dart'; +import '../../sentry_flutter.dart'; + /// Key which is used to identify the [RepaintBoundary] @internal final sentryScreenshotWidgetGlobalKey = @@ -22,20 +24,37 @@ final sentryScreenshotWidgetGlobalKey = /// - You can only have one [SentryScreenshotWidget] widget in your widget tree at all /// times. class SentryScreenshotWidget extends StatefulWidget { - const SentryScreenshotWidget({super.key, required this.child}); - final Widget child; + late final Hub _hub; + + SentryFlutterOptions? get _options => + // ignore: invalid_use_of_internal_member + _hub.options is SentryFlutterOptions + // ignore: invalid_use_of_internal_member + ? _hub.options as SentryFlutterOptions + : null; + + SentryScreenshotWidget({ + super.key, + required this.child, + @internal Hub? hub, + }) : _hub = hub ?? HubAdapter(); @override _SentryScreenshotWidgetState createState() => _SentryScreenshotWidgetState(); } class _SentryScreenshotWidgetState extends State { + SentryFlutterOptions? get _options => widget._options; + @override Widget build(BuildContext context) { - return RepaintBoundary( - key: sentryScreenshotWidgetGlobalKey, - child: widget.child, - ); + if (_options?.attachScreenshot ?? false) { + return RepaintBoundary( + key: sentryScreenshotWidgetGlobalKey, + child: widget.child, + ); + } + return widget.child; } } diff --git a/flutter/lib/src/sentry_widget.dart b/flutter/lib/src/sentry_widget.dart new file mode 100644 index 0000000000..ed390d1ab4 --- /dev/null +++ b/flutter/lib/src/sentry_widget.dart @@ -0,0 +1,23 @@ +import 'package:flutter/cupertino.dart'; +import '../sentry_flutter.dart'; + +/// This widget serves as a wrapper to include Sentry widgets such +/// as [SentryScreenshotWidget] and [SentryUserInteractionWidget]. +class SentryWidget extends StatefulWidget { + final Widget child; + + const SentryWidget({super.key, required this.child}); + + @override + _SentryWidgetState createState() => _SentryWidgetState(); +} + +class _SentryWidgetState extends State { + @override + Widget build(BuildContext context) { + Widget content = widget.child; + content = SentryScreenshotWidget(child: content); + content = SentryUserInteractionWidget(child: content); + return content; + } +} diff --git a/flutter/lib/src/user_interaction/sentry_user_interaction_widget.dart b/flutter/lib/src/user_interaction/sentry_user_interaction_widget.dart index 94d364899e..45af49b14d 100644 --- a/flutter/lib/src/user_interaction/sentry_user_interaction_widget.dart +++ b/flutter/lib/src/user_interaction/sentry_user_interaction_widget.dart @@ -281,12 +281,16 @@ class _SentryUserInteractionWidgetState @override Widget build(BuildContext context) { - return Listener( - behavior: HitTestBehavior.translucent, - onPointerDown: _onPointerDown, - onPointerUp: _onPointerUp, - child: widget.child, - ); + if ((_options?.enableUserInteractionTracing ?? true) || + (_options?.enableUserInteractionBreadcrumbs ?? true)) { + return Listener( + behavior: HitTestBehavior.translucent, + onPointerDown: _onPointerDown, + onPointerUp: _onPointerUp, + child: widget.child, + ); + } + return widget.child; } void _onPointerDown(PointerDownEvent event) { diff --git a/flutter/test/event_processor/screenshot_event_processor_test.dart b/flutter/test/event_processor/screenshot_event_processor_test.dart index 4beeea3ef3..763c0e0ca3 100644 --- a/flutter/test/event_processor/screenshot_event_processor_test.dart +++ b/flutter/test/event_processor/screenshot_event_processor_test.dart @@ -33,6 +33,7 @@ void main() { final sut = fixture.getSut(renderer, isWeb); await tester.pumpWidget(SentryScreenshotWidget( + hub: fixture.hub, child: Text('Catching Pokémon is a snap!', textDirection: TextDirection.ltr))); @@ -178,8 +179,14 @@ void main() { } class Fixture { + late Hub hub; SentryFlutterOptions options = SentryFlutterOptions(dsn: fakeDsn); + Fixture() { + options.attachScreenshot = true; + hub = Hub(options); + } + ScreenshotEventProcessor getSut( FlutterRenderer? flutterRenderer, bool isWeb) { options.rendererWrapper = MockRendererWrapper(flutterRenderer); diff --git a/flutter/test/screenshot/sentry_screenshot_widget_test.dart b/flutter/test/screenshot/sentry_screenshot_widget_test.dart new file mode 100644 index 0000000000..fd4603c794 --- /dev/null +++ b/flutter/test/screenshot/sentry_screenshot_widget_test.dart @@ -0,0 +1,79 @@ +@TestOn('vm') +// ignore_for_file: invalid_use_of_internal_member + +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:sentry_flutter/sentry_flutter.dart'; + +import '../mocks.dart'; + +void main() { + late Fixture fixture; + setUp(() { + fixture = Fixture(); + TestWidgetsFlutterBinding.ensureInitialized(); + }); + + testWidgets( + '$SentryScreenshotWidget does not apply when attachScreenshot is false', + (tester) async { + await tester.pumpWidget( + fixture.getSut( + attachScreenshot: false, + ), + ); + + final widget = find.byType(MyApp); + final repaintBoundaryFinder = find.descendant( + of: widget, + matching: find.byType(RepaintBoundary), + ); + expect(repaintBoundaryFinder, findsNothing); + }, + ); + + testWidgets( + '$SentryScreenshotWidget applies when attachScreenshot is true', + (tester) async { + await tester.pumpWidget( + fixture.getSut( + attachScreenshot: true, + ), + ); + + final widget = find.byType(MyApp); + final repaintBoundaryFinder = find.ancestor( + of: widget, + matching: find.byKey(sentryScreenshotWidgetGlobalKey), + ); + expect(repaintBoundaryFinder, findsOneWidget); + }, + ); +} + +class Fixture { + final _options = SentryFlutterOptions(dsn: fakeDsn); + late Hub hub; + + SentryScreenshotWidget getSut({ + bool attachScreenshot = false, + }) { + _options.attachScreenshot = attachScreenshot; + + hub = Hub(_options); + + return SentryScreenshotWidget( + hub: hub, + child: MaterialApp(home: MyApp()), + ); + } +} + +class MyApp extends StatelessWidget { + const MyApp({super.key}); + + @override + Widget build(BuildContext context) { + return const Text('test'); + } +} diff --git a/flutter/test/sentry_widget_test.dart b/flutter/test/sentry_widget_test.dart new file mode 100644 index 0000000000..a64fded42f --- /dev/null +++ b/flutter/test/sentry_widget_test.dart @@ -0,0 +1,37 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:sentry_flutter/sentry_flutter.dart'; + +void main() { + group('SentryWidget', () { + const testChild = Text('Test Child'); + + setUp(() async { + TestWidgetsFlutterBinding.ensureInitialized(); + }); + + testWidgets('SentryWidget wraps child with SentryUserInteractionWidget', + (WidgetTester tester) async { + await tester.pumpWidget( + MaterialApp( + home: SentryWidget(child: testChild), + ), + ); + + expect(find.byType(SentryUserInteractionWidget), findsOneWidget); + expect(find.byWidget(testChild), findsOneWidget); + }); + + testWidgets('SentryWidget wraps child with SentryScreenshotWidget', + (WidgetTester tester) async { + await tester.pumpWidget( + MaterialApp( + home: SentryWidget(child: testChild), + ), + ); + + expect(find.byType(SentryScreenshotWidget), findsOneWidget); + expect(find.byWidget(testChild), findsOneWidget); + }); + }); +} diff --git a/flutter/test/user_interaction/sentry_user_interaction_widget_test.dart b/flutter/test/user_interaction/sentry_user_interaction_widget_test.dart index a814bd0b54..0fb73cb930 100644 --- a/flutter/test/user_interaction/sentry_user_interaction_widget_test.dart +++ b/flutter/test/user_interaction/sentry_user_interaction_widget_test.dart @@ -32,6 +32,75 @@ void main() { }, ); + testWidgets( + '$SentryUserInteractionWidget does not apply when enableUserInteractionTracing and enableUserInteractionBreadcrumbs is false', + (tester) async { + await tester.runAsync(() async { + await tester.pumpWidget( + fixture.getSut( + enableUserInteractionTracing: false, + enableUserInteractionBreadcrumbs: false, + ), + ); + final specificChildFinder = find.byType(MyApp); + + expect( + find.ancestor( + of: specificChildFinder, + matching: find.byType(Listener), + ), + findsNothing, + ); + }); + }, + ); + + testWidgets( + '$SentryUserInteractionWidget does apply when enableUserInteractionTracing is true', + (tester) async { + await tester.runAsync(() async { + await tester.pumpWidget( + fixture.getSut( + enableUserInteractionTracing: true, + enableUserInteractionBreadcrumbs: false, + ), + ); + final specificChildFinder = find.byType(MyApp); + + expect( + find.ancestor( + of: specificChildFinder, + matching: find.byType(Listener), + ), + findsOne, + ); + }); + }, + ); + + testWidgets( + '$SentryUserInteractionWidget does apply when enableUserInteractionBreadcrumbs is true', + (tester) async { + await tester.runAsync(() async { + await tester.pumpWidget( + fixture.getSut( + enableUserInteractionTracing: false, + enableUserInteractionBreadcrumbs: true, + ), + ); + final specificChildFinder = find.byType(MyApp); + + expect( + find.ancestor( + of: specificChildFinder, + matching: find.byType(Listener), + ), + findsOne, + ); + }); + }, + ); + group('$SentryUserInteractionWidget crumbs', () { testWidgets('Add crumb for MaterialButton', (tester) async { await tester.runAsync(() async { From e3ef57098845edc69a00ce9b4845b54351beccbf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Jan 2024 09:54:21 +0100 Subject: [PATCH 063/237] build(deps): bump styfle/cancel-workflow-action from 0.12.0 to 0.12.1 (#1849) Bumps [styfle/cancel-workflow-action](https://github.com/styfle/cancel-workflow-action) from 0.12.0 to 0.12.1. - [Release notes](https://github.com/styfle/cancel-workflow-action/releases) - [Commits](https://github.com/styfle/cancel-workflow-action/compare/01ce38bf961b4e243a6342cbade0dbc8ba3f0432...85880fa0301c86cca9da44039ee3bb12d3bedbfa) --- updated-dependencies: - dependency-name: styfle/cancel-workflow-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/analyze.yml | 2 +- .github/workflows/dart.yml | 2 +- .github/workflows/dio.yml | 2 +- .github/workflows/drift.yml | 2 +- .github/workflows/e2e_dart.yml | 2 +- .github/workflows/file.yml | 2 +- .github/workflows/flutter.yml | 2 +- .github/workflows/flutter_test.yml | 2 +- .github/workflows/format-and-fix.yml | 2 +- .github/workflows/hive.yml | 2 +- .github/workflows/isar.yml | 2 +- .github/workflows/logging.yml | 2 +- .github/workflows/metrics.yml | 2 +- .github/workflows/min_version_test.yml | 2 +- .github/workflows/sqflite.yml | 2 +- 15 files changed, 15 insertions(+), 15 deletions(-) diff --git a/.github/workflows/analyze.yml b/.github/workflows/analyze.yml index bde8004cec..2db1a28642 100644 --- a/.github/workflows/analyze.yml +++ b/.github/workflows/analyze.yml @@ -19,7 +19,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Cancel Previous Runs - uses: styfle/cancel-workflow-action@01ce38bf961b4e243a6342cbade0dbc8ba3f0432 # pin@0.12.0 + uses: styfle/cancel-workflow-action@85880fa0301c86cca9da44039ee3bb12d3bedbfa # pin@0.12.1 with: access_token: ${{ github.token }} diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml index 6ce30080f8..be47e369e6 100644 --- a/.github/workflows/dart.yml +++ b/.github/workflows/dart.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Cancel Previous Runs - uses: styfle/cancel-workflow-action@01ce38bf961b4e243a6342cbade0dbc8ba3f0432 # pin@0.12.0 + uses: styfle/cancel-workflow-action@85880fa0301c86cca9da44039ee3bb12d3bedbfa # pin@0.12.1 with: access_token: ${{ github.token }} diff --git a/.github/workflows/dio.yml b/.github/workflows/dio.yml index 8f9fa41dc5..f50dc7be62 100644 --- a/.github/workflows/dio.yml +++ b/.github/workflows/dio.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Cancel Previous Runs - uses: styfle/cancel-workflow-action@01ce38bf961b4e243a6342cbade0dbc8ba3f0432 # pin@0.12.0 + uses: styfle/cancel-workflow-action@85880fa0301c86cca9da44039ee3bb12d3bedbfa # pin@0.12.1 with: access_token: ${{ github.token }} diff --git a/.github/workflows/drift.yml b/.github/workflows/drift.yml index f13f6d22f6..ac79f6a039 100644 --- a/.github/workflows/drift.yml +++ b/.github/workflows/drift.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Cancel Previous Runs - uses: styfle/cancel-workflow-action@01ce38bf961b4e243a6342cbade0dbc8ba3f0432 # pin@0.12.0 + uses: styfle/cancel-workflow-action@85880fa0301c86cca9da44039ee3bb12d3bedbfa # pin@0.12.1 with: access_token: ${{ github.token }} diff --git a/.github/workflows/e2e_dart.yml b/.github/workflows/e2e_dart.yml index 8a6953a0aa..bec5e47c95 100644 --- a/.github/workflows/e2e_dart.yml +++ b/.github/workflows/e2e_dart.yml @@ -21,7 +21,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Cancel Previous Runs - uses: styfle/cancel-workflow-action@01ce38bf961b4e243a6342cbade0dbc8ba3f0432 # pin@0.12.0 + uses: styfle/cancel-workflow-action@85880fa0301c86cca9da44039ee3bb12d3bedbfa # pin@0.12.1 with: access_token: ${{ github.token }} diff --git a/.github/workflows/file.yml b/.github/workflows/file.yml index 3d1431f63b..51cad38597 100644 --- a/.github/workflows/file.yml +++ b/.github/workflows/file.yml @@ -18,7 +18,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Cancel Previous Runs - uses: styfle/cancel-workflow-action@01ce38bf961b4e243a6342cbade0dbc8ba3f0432 # pin@0.12.0 + uses: styfle/cancel-workflow-action@85880fa0301c86cca9da44039ee3bb12d3bedbfa # pin@0.12.1 with: access_token: ${{ github.token }} diff --git a/.github/workflows/flutter.yml b/.github/workflows/flutter.yml index 8847114974..0424e153dc 100644 --- a/.github/workflows/flutter.yml +++ b/.github/workflows/flutter.yml @@ -18,7 +18,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Cancel Previous Runs - uses: styfle/cancel-workflow-action@01ce38bf961b4e243a6342cbade0dbc8ba3f0432 # pin@0.12.0 + uses: styfle/cancel-workflow-action@85880fa0301c86cca9da44039ee3bb12d3bedbfa # pin@0.12.1 with: access_token: ${{ github.token }} diff --git a/.github/workflows/flutter_test.yml b/.github/workflows/flutter_test.yml index 9a5b583420..61af6b0fe6 100644 --- a/.github/workflows/flutter_test.yml +++ b/.github/workflows/flutter_test.yml @@ -20,7 +20,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Cancel Previous Runs - uses: styfle/cancel-workflow-action@01ce38bf961b4e243a6342cbade0dbc8ba3f0432 # pin@0.12.0 + uses: styfle/cancel-workflow-action@85880fa0301c86cca9da44039ee3bb12d3bedbfa # pin@0.12.1 with: access_token: ${{ github.token }} diff --git a/.github/workflows/format-and-fix.yml b/.github/workflows/format-and-fix.yml index f7d0ec9cfb..4f6d96f106 100644 --- a/.github/workflows/format-and-fix.yml +++ b/.github/workflows/format-and-fix.yml @@ -6,7 +6,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Cancel Previous Runs - uses: styfle/cancel-workflow-action@01ce38bf961b4e243a6342cbade0dbc8ba3f0432 # pin@0.12.0 + uses: styfle/cancel-workflow-action@85880fa0301c86cca9da44039ee3bb12d3bedbfa # pin@0.12.1 with: access_token: ${{ github.token }} diff --git a/.github/workflows/hive.yml b/.github/workflows/hive.yml index 15bef1ecdb..f930716063 100644 --- a/.github/workflows/hive.yml +++ b/.github/workflows/hive.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Cancel Previous Runs - uses: styfle/cancel-workflow-action@01ce38bf961b4e243a6342cbade0dbc8ba3f0432 # pin@0.12.0 + uses: styfle/cancel-workflow-action@85880fa0301c86cca9da44039ee3bb12d3bedbfa # pin@0.12.1 with: access_token: ${{ github.token }} diff --git a/.github/workflows/isar.yml b/.github/workflows/isar.yml index 4e090f6307..7ae6bec76e 100644 --- a/.github/workflows/isar.yml +++ b/.github/workflows/isar.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Cancel Previous Runs - uses: styfle/cancel-workflow-action@01ce38bf961b4e243a6342cbade0dbc8ba3f0432 # pin@0.12.0 + uses: styfle/cancel-workflow-action@85880fa0301c86cca9da44039ee3bb12d3bedbfa # pin@0.12.1 with: access_token: ${{ github.token }} diff --git a/.github/workflows/logging.yml b/.github/workflows/logging.yml index 4e39833caa..eea78ca9a2 100644 --- a/.github/workflows/logging.yml +++ b/.github/workflows/logging.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Cancel Previous Runs - uses: styfle/cancel-workflow-action@01ce38bf961b4e243a6342cbade0dbc8ba3f0432 # pin@0.12.0 + uses: styfle/cancel-workflow-action@85880fa0301c86cca9da44039ee3bb12d3bedbfa # pin@0.12.1 with: access_token: ${{ github.token }} diff --git a/.github/workflows/metrics.yml b/.github/workflows/metrics.yml index 1e383a93ea..94278a167c 100644 --- a/.github/workflows/metrics.yml +++ b/.github/workflows/metrics.yml @@ -18,7 +18,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Cancel Previous Runs - uses: styfle/cancel-workflow-action@01ce38bf961b4e243a6342cbade0dbc8ba3f0432 # pin@0.12.0 + uses: styfle/cancel-workflow-action@85880fa0301c86cca9da44039ee3bb12d3bedbfa # pin@0.12.1 with: access_token: ${{ github.token }} diff --git a/.github/workflows/min_version_test.yml b/.github/workflows/min_version_test.yml index 6b08e3ca95..c20f06489d 100644 --- a/.github/workflows/min_version_test.yml +++ b/.github/workflows/min_version_test.yml @@ -18,7 +18,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Cancel Previous Runs - uses: styfle/cancel-workflow-action@01ce38bf961b4e243a6342cbade0dbc8ba3f0432 # pin@0.12.0 + uses: styfle/cancel-workflow-action@85880fa0301c86cca9da44039ee3bb12d3bedbfa # pin@0.12.1 with: access_token: ${{ github.token }} diff --git a/.github/workflows/sqflite.yml b/.github/workflows/sqflite.yml index 1168c4561e..14b50c944c 100644 --- a/.github/workflows/sqflite.yml +++ b/.github/workflows/sqflite.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Cancel Previous Runs - uses: styfle/cancel-workflow-action@01ce38bf961b4e243a6342cbade0dbc8ba3f0432 # pin@0.12.0 + uses: styfle/cancel-workflow-action@85880fa0301c86cca9da44039ee3bb12d3bedbfa # pin@0.12.1 with: access_token: ${{ github.token }} From 432757792888cd316a8eefa8a799826a1eb1721e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Jan 2024 09:54:36 +0100 Subject: [PATCH 064/237] build(deps): bump reactivecircus/android-emulator-runner (#1848) Bumps [reactivecircus/android-emulator-runner](https://github.com/reactivecircus/android-emulator-runner) from 2.29.0 to 2.30.1. - [Release notes](https://github.com/reactivecircus/android-emulator-runner/releases) - [Changelog](https://github.com/ReactiveCircus/android-emulator-runner/blob/main/CHANGELOG.md) - [Commits](https://github.com/reactivecircus/android-emulator-runner/compare/99a4aac18b4df9b3af66c4a1f04c1f23fa10c270...6b0df4b0efb23bb0ec63d881db79aefbc976e4b2) --- updated-dependencies: - dependency-name: reactivecircus/android-emulator-runner dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/flutter_test.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/flutter_test.yml b/.github/workflows/flutter_test.yml index 61af6b0fe6..391f10d5af 100644 --- a/.github/workflows/flutter_test.yml +++ b/.github/workflows/flutter_test.yml @@ -67,7 +67,7 @@ jobs: - name: create AVD and generate snapshot for caching if: steps.avd-cache.outputs.cache-hit != 'true' - uses: reactivecircus/android-emulator-runner@99a4aac18b4df9b3af66c4a1f04c1f23fa10c270 #pin@v2.29.0 + uses: reactivecircus/android-emulator-runner@6b0df4b0efb23bb0ec63d881db79aefbc976e4b2 #pin@v2.30.1 with: working-directory: ./flutter/example api-level: 31 @@ -84,7 +84,7 @@ jobs: run: flutter build apk --debug - name: launch android emulator & run android native test - uses: reactivecircus/android-emulator-runner@99a4aac18b4df9b3af66c4a1f04c1f23fa10c270 #pin@v2.29.0 + uses: reactivecircus/android-emulator-runner@6b0df4b0efb23bb0ec63d881db79aefbc976e4b2 #pin@v2.30.1 with: working-directory: ./flutter/example/android api-level: 31 @@ -97,7 +97,7 @@ jobs: script: ./gradlew testDebugUnitTest - name: launch android emulator & run android integration test - uses: reactivecircus/android-emulator-runner@99a4aac18b4df9b3af66c4a1f04c1f23fa10c270 #pin@v2.29.0 + uses: reactivecircus/android-emulator-runner@6b0df4b0efb23bb0ec63d881db79aefbc976e4b2 #pin@v2.30.1 with: working-directory: ./flutter/example api-level: 31 From 21bf0dea9ae6067b147650228bd2c3a1a38e4ee0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Jan 2024 09:54:56 +0100 Subject: [PATCH 065/237] build(deps): bump codecov/codecov-action from 3.1.4 to 3.1.5 (#1850) Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 3.1.4 to 3.1.5. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/eaaf4bedf32dbdc6b720b63067d99c4d77d6047d...4fe8c5f003fae66aa5ebb77cfd3e7bfbbda0b6b0) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor --- .github/workflows/dart.yml | 2 +- .github/workflows/dio.yml | 2 +- .github/workflows/drift.yml | 2 +- .github/workflows/file.yml | 2 +- .github/workflows/flutter.yml | 2 +- .github/workflows/hive.yml | 2 +- .github/workflows/isar.yml | 2 +- .github/workflows/logging.yml | 2 +- .github/workflows/sqflite.yml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml index be47e369e6..a8bccd8d82 100644 --- a/.github/workflows/dart.yml +++ b/.github/workflows/dart.yml @@ -68,7 +68,7 @@ jobs: dart pub get webdev build - - uses: codecov/codecov-action@eaaf4bedf32dbdc6b720b63067d99c4d77d6047d # pin@v3 + - uses: codecov/codecov-action@4fe8c5f003fae66aa5ebb77cfd3e7bfbbda0b6b0 # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: name: sentry diff --git a/.github/workflows/dio.yml b/.github/workflows/dio.yml index f50dc7be62..f92f029d98 100644 --- a/.github/workflows/dio.yml +++ b/.github/workflows/dio.yml @@ -52,7 +52,7 @@ jobs: dart test -p vm --coverage=coverage --test-randomize-ordering-seed=random --chain-stack-traces dart pub run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.dart_tool/package_config.json --report-on=lib - - uses: codecov/codecov-action@eaaf4bedf32dbdc6b720b63067d99c4d77d6047d # pin@v3 + - uses: codecov/codecov-action@4fe8c5f003fae66aa5ebb77cfd3e7bfbbda0b6b0 # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: name: sentry_dio diff --git a/.github/workflows/drift.yml b/.github/workflows/drift.yml index ac79f6a039..bbd07f905b 100644 --- a/.github/workflows/drift.yml +++ b/.github/workflows/drift.yml @@ -93,7 +93,7 @@ jobs: cd drift flutter test --coverage --test-randomize-ordering-seed=random - - uses: codecov/codecov-action@eaaf4bedf32dbdc6b720b63067d99c4d77d6047d # pin@v3 + - uses: codecov/codecov-action@4fe8c5f003fae66aa5ebb77cfd3e7bfbbda0b6b0 # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' with: name: sentry_drift diff --git a/.github/workflows/file.yml b/.github/workflows/file.yml index 51cad38597..d981a7cac5 100644 --- a/.github/workflows/file.yml +++ b/.github/workflows/file.yml @@ -52,7 +52,7 @@ jobs: dart test -p vm --coverage=coverage --test-randomize-ordering-seed=random --chain-stack-traces dart pub run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.dart_tool/package_config.json --report-on=lib - - uses: codecov/codecov-action@eaaf4bedf32dbdc6b720b63067d99c4d77d6047d # pin@v3 + - uses: codecov/codecov-action@4fe8c5f003fae66aa5ebb77cfd3e7bfbbda0b6b0 # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: name: sentry_file diff --git a/.github/workflows/flutter.yml b/.github/workflows/flutter.yml index 0424e153dc..4443f84e05 100644 --- a/.github/workflows/flutter.yml +++ b/.github/workflows/flutter.yml @@ -106,7 +106,7 @@ jobs: flutter test --coverage --test-randomize-ordering-seed=random dart run remove_from_coverage -f coverage/lcov.info -r 'binding.dart' - - uses: codecov/codecov-action@eaaf4bedf32dbdc6b720b63067d99c4d77d6047d # pin@v3 + - uses: codecov/codecov-action@4fe8c5f003fae66aa5ebb77cfd3e7bfbbda0b6b0 # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' with: name: sentry_flutter diff --git a/.github/workflows/hive.yml b/.github/workflows/hive.yml index f930716063..5893673318 100644 --- a/.github/workflows/hive.yml +++ b/.github/workflows/hive.yml @@ -51,7 +51,7 @@ jobs: dart test -p vm --coverage=coverage --test-randomize-ordering-seed=random --chain-stack-traces dart pub run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.dart_tool/package_config.json --report-on=lib - - uses: codecov/codecov-action@eaaf4bedf32dbdc6b720b63067d99c4d77d6047d # pin@v3 + - uses: codecov/codecov-action@4fe8c5f003fae66aa5ebb77cfd3e7bfbbda0b6b0 # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: name: sentry_hive diff --git a/.github/workflows/isar.yml b/.github/workflows/isar.yml index 7ae6bec76e..f4038421df 100644 --- a/.github/workflows/isar.yml +++ b/.github/workflows/isar.yml @@ -93,7 +93,7 @@ jobs: cd isar flutter test -j 1 --coverage --test-randomize-ordering-seed=random - - uses: codecov/codecov-action@eaaf4bedf32dbdc6b720b63067d99c4d77d6047d # pin@v3 + - uses: codecov/codecov-action@4fe8c5f003fae66aa5ebb77cfd3e7bfbbda0b6b0 # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' with: name: sentry_isar diff --git a/.github/workflows/logging.yml b/.github/workflows/logging.yml index eea78ca9a2..9a3fead839 100644 --- a/.github/workflows/logging.yml +++ b/.github/workflows/logging.yml @@ -52,7 +52,7 @@ jobs: dart test -p vm --coverage=coverage --test-randomize-ordering-seed=random --chain-stack-traces dart pub run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.dart_tool/package_config.json --report-on=lib - - uses: codecov/codecov-action@eaaf4bedf32dbdc6b720b63067d99c4d77d6047d # pin@v3 + - uses: codecov/codecov-action@4fe8c5f003fae66aa5ebb77cfd3e7bfbbda0b6b0 # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: name: sentry_logging diff --git a/.github/workflows/sqflite.yml b/.github/workflows/sqflite.yml index 14b50c944c..a94c31475f 100644 --- a/.github/workflows/sqflite.yml +++ b/.github/workflows/sqflite.yml @@ -93,7 +93,7 @@ jobs: cd sqflite flutter test --coverage --test-randomize-ordering-seed=random - - uses: codecov/codecov-action@eaaf4bedf32dbdc6b720b63067d99c4d77d6047d # pin@v3 + - uses: codecov/codecov-action@4fe8c5f003fae66aa5ebb77cfd3e7bfbbda0b6b0 # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' with: name: sentry_sqflite From fb77dcfabc1246296be034aba3b791e76030ce77 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 30 Jan 2024 10:43:41 +0100 Subject: [PATCH 066/237] chore(deps): update Android SDK to v7.2.0 (#1815) * chore: update flutter/scripts/update-android.sh to 7.2.0 * Update podfile * Update podfile * Update deployment target * update * update --------- Co-authored-by: GitHub Co-authored-by: GIancarlo Buenaflor --- CHANGELOG.md | 6 +++--- flutter/android/build.gradle | 2 +- flutter/example/ios/Podfile | 8 ++++---- flutter/example/ios/Runner.xcodeproj/project.pbxproj | 6 +++--- flutter/ios/sentry_flutter.podspec | 2 +- min_version_test/ios/Podfile | 2 +- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 62207422c4..572bed3257 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,9 +31,9 @@ ### Dependencies -- Bump Android SDK from v7.0.0 to v7.1.0 ([#1788](https://github.com/getsentry/sentry-dart/pull/1788)) - - [changelog](https://github.com/getsentry/sentry-java/blob/main/CHANGELOG.md#710) - - [diff](https://github.com/getsentry/sentry-java/compare/7.0.0...7.1.0) +- Bump Android SDK from v7.0.0 to v7.2.0 ([#1788](https://github.com/getsentry/sentry-dart/pull/1788), [#1815](https://github.com/getsentry/sentry-dart/pull/1815)) + - [changelog](https://github.com/getsentry/sentry-java/blob/main/CHANGELOG.md#720) + - [diff](https://github.com/getsentry/sentry-java/compare/7.0.0...7.2.0) - Bump Cocoa SDK from v8.17.2 to v8.18.0 ([#1803](https://github.com/getsentry/sentry-dart/pull/1803)) - [changelog](https://github.com/getsentry/sentry-cocoa/blob/main/CHANGELOG.md#8180) - [diff](https://github.com/getsentry/sentry-cocoa/compare/8.17.2...8.18.0) diff --git a/flutter/android/build.gradle b/flutter/android/build.gradle index e594b017ea..e7f2cf157a 100644 --- a/flutter/android/build.gradle +++ b/flutter/android/build.gradle @@ -60,7 +60,7 @@ android { } dependencies { - api 'io.sentry:sentry-android:7.1.0' + api 'io.sentry:sentry-android:7.2.0' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" // Required -- JUnit 4 framework diff --git a/flutter/example/ios/Podfile b/flutter/example/ios/Podfile index 8d38fc9608..8cb4ddb285 100644 --- a/flutter/example/ios/Podfile +++ b/flutter/example/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -platform :ios, '11.0' +platform :ios, '12.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' @@ -32,19 +32,19 @@ target 'Runner' do use_modular_headers! flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) - + # Configure test target target 'RunnerTests' do inherit! :search_paths end - + end post_install do |installer| installer.pods_project.targets.each do |target| flutter_additional_ios_build_settings(target) target.build_configurations.each do |config| - config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '11.0' + config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '12.0' end end end diff --git a/flutter/example/ios/Runner.xcodeproj/project.pbxproj b/flutter/example/ios/Runner.xcodeproj/project.pbxproj index 29c58327af..58add4db19 100644 --- a/flutter/example/ios/Runner.xcodeproj/project.pbxproj +++ b/flutter/example/ios/Runner.xcodeproj/project.pbxproj @@ -460,7 +460,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -631,7 +631,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -681,7 +681,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; diff --git a/flutter/ios/sentry_flutter.podspec b/flutter/ios/sentry_flutter.podspec index 03220ac7bf..b5cf5dd606 100644 --- a/flutter/ios/sentry_flutter.podspec +++ b/flutter/ios/sentry_flutter.podspec @@ -15,7 +15,7 @@ Sentry SDK for Flutter with support to native through sentry-cocoa. s.dependency 'Sentry/HybridSDK', '8.19.0' s.ios.dependency 'Flutter' s.osx.dependency 'FlutterMacOS' - s.ios.deployment_target = '11.0' + s.ios.deployment_target = '12.0' # Flutter 3.7 requires 10.14 s.osx.deployment_target = '10.13' diff --git a/min_version_test/ios/Podfile b/min_version_test/ios/Podfile index 88359b225f..2c068c404b 100644 --- a/min_version_test/ios/Podfile +++ b/min_version_test/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -# platform :ios, '11.0' +platform :ios, '12.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' From c3e6c820747f2dbb4515a2ed1dcb362eeba83072 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 30 Jan 2024 10:50:09 +0100 Subject: [PATCH 067/237] chore(deps): update Flutter SDK (metrics) to v3.16.9 (#1847) * chore: update metrics/flutter.properties to 3.16.9 * update * update --------- Co-authored-by: GitHub Co-authored-by: GIancarlo Buenaflor --- flutter/example/ios/Podfile | 4 ++-- flutter/example/ios/Runner.xcodeproj/project.pbxproj | 6 +++--- flutter/ios/sentry_flutter.podspec | 2 +- metrics/flutter.properties | 2 +- min_version_test/ios/Podfile | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/flutter/example/ios/Podfile b/flutter/example/ios/Podfile index 8cb4ddb285..877d653518 100644 --- a/flutter/example/ios/Podfile +++ b/flutter/example/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -platform :ios, '12.0' +platform :ios, '11.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' @@ -44,7 +44,7 @@ post_install do |installer| installer.pods_project.targets.each do |target| flutter_additional_ios_build_settings(target) target.build_configurations.each do |config| - config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '12.0' + config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '11.0' end end end diff --git a/flutter/example/ios/Runner.xcodeproj/project.pbxproj b/flutter/example/ios/Runner.xcodeproj/project.pbxproj index 58add4db19..29c58327af 100644 --- a/flutter/example/ios/Runner.xcodeproj/project.pbxproj +++ b/flutter/example/ios/Runner.xcodeproj/project.pbxproj @@ -460,7 +460,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -631,7 +631,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -681,7 +681,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; diff --git a/flutter/ios/sentry_flutter.podspec b/flutter/ios/sentry_flutter.podspec index b5cf5dd606..03220ac7bf 100644 --- a/flutter/ios/sentry_flutter.podspec +++ b/flutter/ios/sentry_flutter.podspec @@ -15,7 +15,7 @@ Sentry SDK for Flutter with support to native through sentry-cocoa. s.dependency 'Sentry/HybridSDK', '8.19.0' s.ios.dependency 'Flutter' s.osx.dependency 'FlutterMacOS' - s.ios.deployment_target = '12.0' + s.ios.deployment_target = '11.0' # Flutter 3.7 requires 10.14 s.osx.deployment_target = '10.13' diff --git a/metrics/flutter.properties b/metrics/flutter.properties index 8a0f53ceea..5b903acb68 100644 --- a/metrics/flutter.properties +++ b/metrics/flutter.properties @@ -1,2 +1,2 @@ -version = 3.16.8 +version = 3.16.9 repo = https://github.com/flutter/flutter diff --git a/min_version_test/ios/Podfile b/min_version_test/ios/Podfile index 2c068c404b..88359b225f 100644 --- a/min_version_test/ios/Podfile +++ b/min_version_test/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -platform :ios, '12.0' +# platform :ios, '11.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' From 42b79b3af5b36307519b19032dc77b423bd347ae Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 30 Jan 2024 11:58:19 +0100 Subject: [PATCH 068/237] chore(deps): update Symbol collector CLI to v1.14.0 (#1827) * chore: update scripts/update-symbol-collector.sh to 1.14.0 * update --------- Co-authored-by: GitHub Co-authored-by: GIancarlo Buenaflor --- CHANGELOG.md | 3 +-- .../flutter_symbol_collector/lib/src/symbol_collector_cli.dart | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 572bed3257..458e511cd5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,8 +6,7 @@ - Add `SentryWidget` ([#1846](https://github.com/getsentry/sentry-dart/pull/1846)) - Prefer to use `SentryWidget` now instead of `SentryScreenshotWidget` and `SentryUserInteractionWidget` directly -- APM for isar ([#1726](https://github.com/getsentry/sentry-dart/pull/1726)) -- Performance monitoring support for isar ([#1726](https://github.com/getsentry/sentry-dart/pull/1726)) +- Performance monitoring support for Isar ([#1726](https://github.com/getsentry/sentry-dart/pull/1726)) - Tracing without performance for Dio integration ([#1837](https://github.com/getsentry/sentry-dart/pull/1837)) - Accept `Map` in `Hint` class ([#1807](https://github.com/getsentry/sentry-dart/pull/1807)) - Please check if everything works as expected when using `Hint` diff --git a/scripts/flutter_symbol_collector/lib/src/symbol_collector_cli.dart b/scripts/flutter_symbol_collector/lib/src/symbol_collector_cli.dart index d89cbaeb84..1d4e29a66a 100644 --- a/scripts/flutter_symbol_collector/lib/src/symbol_collector_cli.dart +++ b/scripts/flutter_symbol_collector/lib/src/symbol_collector_cli.dart @@ -19,7 +19,7 @@ class SymbolCollectorCli { // https://github.com/getsentry/symbol-collector/releases @internal - static const version = '1.13.0'; + static const version = '1.14.0'; @internal late final String cli; From f2e496dce9b9da13c48049bac16ff033269f44ad Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Tue, 30 Jan 2024 14:39:10 +0100 Subject: [PATCH 069/237] Update CHANGELOG.md (#1845) --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 458e511cd5..dadea3ed77 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,12 @@ - Method `hint.addAll(Map keysAndValues)` now takes `Map` instead of `Map` - Method `set(String key, dynamic value)` now takes value of `dynamic` instead of `Object` - Method `hint.get(String key)` now returns `dynamic` instead of `Object?` + +### Dependencies + +- Bump Cocoa SDK from v8.18.0 to v8.19.0 ([#1803](https://github.com/getsentry/sentry-dart/pull/1844)) + - [changelog](https://github.com/getsentry/sentry-cocoa/blob/main/CHANGELOG.md#8190) + - [diff](https://github.com/getsentry/sentry-cocoa/compare/8.18.0...8.19.0) ## 7.15.0 From 4c78360ef218251d46e8468c8aaf00132482e4a4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 30 Jan 2024 15:29:04 +0100 Subject: [PATCH 070/237] chore: update flutter/scripts/update-android.sh to 7.3.0 (#1852) Co-authored-by: GitHub --- CHANGELOG.md | 3 +++ flutter/android/build.gradle | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dadea3ed77..402c273459 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,9 @@ - Bump Cocoa SDK from v8.18.0 to v8.19.0 ([#1803](https://github.com/getsentry/sentry-dart/pull/1844)) - [changelog](https://github.com/getsentry/sentry-cocoa/blob/main/CHANGELOG.md#8190) - [diff](https://github.com/getsentry/sentry-cocoa/compare/8.18.0...8.19.0) +- Bump Android SDK from v7.2.0 to v7.3.0 ([#1852](https://github.com/getsentry/sentry-dart/pull/1852)) + - [changelog](https://github.com/getsentry/sentry-java/blob/main/CHANGELOG.md#730) + - [diff](https://github.com/getsentry/sentry-java/compare/7.2.0...7.3.0) ## 7.15.0 diff --git a/flutter/android/build.gradle b/flutter/android/build.gradle index e7f2cf157a..5bb8ed8a20 100644 --- a/flutter/android/build.gradle +++ b/flutter/android/build.gradle @@ -60,7 +60,7 @@ android { } dependencies { - api 'io.sentry:sentry-android:7.2.0' + api 'io.sentry:sentry-android:7.3.0' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" // Required -- JUnit 4 framework From 147ef50f030e4933e0ccd93f70110b4b8ba27109 Mon Sep 17 00:00:00 2001 From: getsentry-bot Date: Tue, 30 Jan 2024 14:30:03 +0000 Subject: [PATCH 071/237] release: 7.16.0 --- CHANGELOG.md | 2 +- dart/lib/src/version.dart | 2 +- dart/pubspec.yaml | 2 +- dio/lib/src/version.dart | 2 +- dio/pubspec.yaml | 4 ++-- drift/lib/src/version.dart | 2 +- drift/pubspec.yaml | 4 ++-- file/lib/src/version.dart | 2 +- file/pubspec.yaml | 4 ++-- flutter/example/pubspec.yaml | 2 +- flutter/lib/src/version.dart | 2 +- flutter/pubspec.yaml | 4 ++-- hive/lib/src/version.dart | 2 +- hive/pubspec.yaml | 4 ++-- isar/lib/src/version.dart | 2 +- isar/pubspec.yaml | 4 ++-- logging/lib/src/version.dart | 2 +- logging/pubspec.yaml | 4 ++-- sqflite/lib/src/version.dart | 2 +- sqflite/pubspec.yaml | 4 ++-- 20 files changed, 28 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 402c273459..ddf41c4811 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## Unreleased +## 7.16.0 ### Features diff --git a/dart/lib/src/version.dart b/dart/lib/src/version.dart index cd68dd9443..c29bdd09cb 100644 --- a/dart/lib/src/version.dart +++ b/dart/lib/src/version.dart @@ -9,7 +9,7 @@ library version; /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.15.0'; +const String sdkVersion = '7.16.0'; String sdkName(bool isWeb) => isWeb ? _browserSdkName : _ioSdkName; diff --git a/dart/pubspec.yaml b/dart/pubspec.yaml index e4668ad96d..1cc9bf8c75 100644 --- a/dart/pubspec.yaml +++ b/dart/pubspec.yaml @@ -1,5 +1,5 @@ name: sentry -version: 7.15.0 +version: 7.16.0 description: > A crash reporting library for Dart that sends crash reports to Sentry.io. This library supports Dart VM and Web. For Flutter consider sentry_flutter instead. diff --git a/dio/lib/src/version.dart b/dio/lib/src/version.dart index a0d410b5dd..175e956f04 100644 --- a/dio/lib/src/version.dart +++ b/dio/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.15.0'; +const String sdkVersion = '7.16.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_dio'; diff --git a/dio/pubspec.yaml b/dio/pubspec.yaml index abd613d381..e1f02a0123 100644 --- a/dio/pubspec.yaml +++ b/dio/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_dio description: An integration which adds support for performance tracing for the Dio package. -version: 7.15.0 +version: 7.16.0 homepage: https://docs.sentry.io/platforms/dart/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -11,7 +11,7 @@ environment: dependencies: dio: ^5.0.0 - sentry: 7.15.0 + sentry: 7.16.0 dev_dependencies: meta: ^1.3.0 diff --git a/drift/lib/src/version.dart b/drift/lib/src/version.dart index 0a1bc2ce4d..2795a157be 100644 --- a/drift/lib/src/version.dart +++ b/drift/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.15.0'; +const String sdkVersion = '7.16.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_drift'; diff --git a/drift/pubspec.yaml b/drift/pubspec.yaml index af1d524c8b..92323b4f63 100644 --- a/drift/pubspec.yaml +++ b/drift/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_drift description: An integration which adds support for performance tracing for the drift package. -version: 7.15.0 +version: 7.16.0 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -10,7 +10,7 @@ environment: flutter: '>=3.3.0' dependencies: - sentry: 7.15.0 + sentry: 7.16.0 meta: ^1.3.0 drift: ^2.13.0 diff --git a/file/lib/src/version.dart b/file/lib/src/version.dart index 27f4d170a5..a2a31b3a5e 100644 --- a/file/lib/src/version.dart +++ b/file/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.15.0'; +const String sdkVersion = '7.16.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_file'; diff --git a/file/pubspec.yaml b/file/pubspec.yaml index 60c56c6248..509e596a13 100644 --- a/file/pubspec.yaml +++ b/file/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_file description: An integration which adds support for performance tracing for dart.io.File. -version: 7.15.0 +version: 7.16.0 homepage: https://docs.sentry.io/platforms/dart/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -10,7 +10,7 @@ environment: sdk: '>=2.19.0 <4.0.0' dependencies: - sentry: 7.15.0 + sentry: 7.16.0 meta: ^1.3.0 dev_dependencies: diff --git a/flutter/example/pubspec.yaml b/flutter/example/pubspec.yaml index bb021595c1..6530b23e99 100644 --- a/flutter/example/pubspec.yaml +++ b/flutter/example/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_flutter_example description: Demonstrates how to use the sentry_flutter plugin. -version: 7.15.0 +version: 7.16.0 publish_to: 'none' # Remove this line if you wish to publish to pub.dev diff --git a/flutter/lib/src/version.dart b/flutter/lib/src/version.dart index dd50a348fd..078ad6a08f 100644 --- a/flutter/lib/src/version.dart +++ b/flutter/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.15.0'; +const String sdkVersion = '7.16.0'; /// The default SDK name reported to Sentry.io in the submitted events. const String sdkName = 'sentry.dart.flutter'; diff --git a/flutter/pubspec.yaml b/flutter/pubspec.yaml index c41ef8d6b0..9757dbd698 100644 --- a/flutter/pubspec.yaml +++ b/flutter/pubspec.yaml @@ -1,5 +1,5 @@ name: sentry_flutter -version: 7.15.0 +version: 7.16.0 description: Sentry SDK for Flutter. This package aims to support different Flutter targets by relying on the many platforms supported by Sentry with native SDKs. homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart @@ -15,7 +15,7 @@ dependencies: sdk: flutter flutter_web_plugins: sdk: flutter - sentry: 7.15.0 + sentry: 7.16.0 package_info_plus: '>=1.0.0 <=5.0.1' meta: ^1.3.0 ffi: ^2.0.0 diff --git a/hive/lib/src/version.dart b/hive/lib/src/version.dart index b775854f98..ac6247b5a5 100644 --- a/hive/lib/src/version.dart +++ b/hive/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.15.0'; +const String sdkVersion = '7.16.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_hive'; diff --git a/hive/pubspec.yaml b/hive/pubspec.yaml index 4a8ac02d4e..cbcb5b16e6 100644 --- a/hive/pubspec.yaml +++ b/hive/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_hive description: An integration which adds support for performance tracing for the hive package. -version: 7.15.0 +version: 7.16.0 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -9,7 +9,7 @@ environment: sdk: '>=2.17.0 <4.0.0' dependencies: - sentry: 7.15.0 + sentry: 7.16.0 hive: ^2.2.3 meta: ^1.3.0 diff --git a/isar/lib/src/version.dart b/isar/lib/src/version.dart index 8d8ef99293..0e551e8349 100644 --- a/isar/lib/src/version.dart +++ b/isar/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.15.0'; +const String sdkVersion = '7.16.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_isar'; diff --git a/isar/pubspec.yaml b/isar/pubspec.yaml index f618fe7543..81770c4d52 100644 --- a/isar/pubspec.yaml +++ b/isar/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_isar description: An integration which adds support for performance tracing for the isar package. -version: 7.15.0 +version: 7.16.0 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -12,7 +12,7 @@ environment: dependencies: isar: ^3.1.0 isar_flutter_libs: ^3.1.0 # contains Isar Core - sentry: 7.15.0 + sentry: 7.16.0 meta: ^1.3.0 path: ^1.8.3 diff --git a/logging/lib/src/version.dart b/logging/lib/src/version.dart index 45fd9a81a7..47dc6b25a2 100644 --- a/logging/lib/src/version.dart +++ b/logging/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.15.0'; +const String sdkVersion = '7.16.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_logging'; diff --git a/logging/pubspec.yaml b/logging/pubspec.yaml index 71de51c471..97e888064b 100644 --- a/logging/pubspec.yaml +++ b/logging/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_logging description: An integration which adds support for recording log from the logging package. -version: 7.15.0 +version: 7.16.0 homepage: https://docs.sentry.io/platforms/dart/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -11,7 +11,7 @@ environment: dependencies: logging: ^1.0.0 - sentry: 7.15.0 + sentry: 7.16.0 dev_dependencies: lints: ^3.0.0 diff --git a/sqflite/lib/src/version.dart b/sqflite/lib/src/version.dart index e0f78f9f60..6982ffcf1f 100644 --- a/sqflite/lib/src/version.dart +++ b/sqflite/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.15.0'; +const String sdkVersion = '7.16.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_sqflite'; diff --git a/sqflite/pubspec.yaml b/sqflite/pubspec.yaml index d3e48214b3..4fae66faf9 100644 --- a/sqflite/pubspec.yaml +++ b/sqflite/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_sqflite description: An integration which adds support for performance tracing for the sqflite package. -version: 7.15.0 +version: 7.16.0 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -10,7 +10,7 @@ environment: flutter: '>=3.3.0' # matching sqflite dependencies: - sentry: 7.15.0 + sentry: 7.16.0 sqflite: ^2.0.0 sqflite_common: ^2.0.0 meta: ^1.3.0 From 74e1fdd2ec34816cd8eedefc833dccc7d3baa2c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kry=C5=A1tof=20Wold=C5=99ich?= <31292499+krystofwoldrich@users.noreply.github.com> Date: Mon, 5 Feb 2024 17:00:29 +0100 Subject: [PATCH 072/237] chore(sample): Upgrade SAGP to v4.2.0 in the flutter example app (#1860) --- flutter/example/android/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flutter/example/android/build.gradle b/flutter/example/android/build.gradle index e628374358..50bb21eda7 100644 --- a/flutter/example/android/build.gradle +++ b/flutter/example/android/build.gradle @@ -7,7 +7,7 @@ buildscript { } dependencies { - classpath 'io.sentry:sentry-android-gradle-plugin:3.5.0' + classpath 'io.sentry:sentry-android-gradle-plugin:4.2.0' classpath 'com.android.tools.build:gradle:7.2.2' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath 'io.github.howardpang:androidNativeBundle:1.1.3' From 36615c315bd0340da4845965113cfb7d598ebd6c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Feb 2024 17:00:51 +0100 Subject: [PATCH 073/237] build(deps): bump dart-lang/setup-dart from 1.6.1 to 1.6.2 (#1864) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.6.1 to 1.6.2. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/ca7e6fee45ffbd82b555a7ebfc236d2c86439f5b...fedb1266e91cf51be2fdb382869461a434b920a3) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/analyze.yml | 2 +- .github/workflows/dart.yml | 2 +- .github/workflows/diagrams.yml | 2 +- .github/workflows/dio.yml | 2 +- .github/workflows/e2e_dart.yml | 2 +- .github/workflows/file.yml | 2 +- .github/workflows/flutter-symbols.yml | 4 ++-- .github/workflows/format-and-fix.yml | 2 +- .github/workflows/hive.yml | 2 +- .github/workflows/logging.yml | 2 +- 10 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/analyze.yml b/.github/workflows/analyze.yml index 2db1a28642..28d192a55a 100644 --- a/.github/workflows/analyze.yml +++ b/.github/workflows/analyze.yml @@ -32,7 +32,7 @@ jobs: working-directory: ${{ inputs.package }} steps: - uses: actions/checkout@v4 - - uses: dart-lang/setup-dart@ca7e6fee45ffbd82b555a7ebfc236d2c86439f5b # pin@v1 + - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 # pin@v1 if: ${{ inputs.sdk == 'dart' }} - uses: subosito/flutter-action@2783a3f08e1baf891508463f8c6653c258246225 # pin@v2.12.0 if: ${{ inputs.sdk == 'flutter' }} diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml index a8bccd8d82..70d3f291d5 100644 --- a/.github/workflows/dart.yml +++ b/.github/workflows/dart.yml @@ -39,7 +39,7 @@ jobs: - os: macos-latest sdk: beta steps: - - uses: dart-lang/setup-dart@ca7e6fee45ffbd82b555a7ebfc236d2c86439f5b # pin@v1 + - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 # pin@v1 with: sdk: ${{ matrix.sdk }} - uses: actions/checkout@v4 diff --git a/.github/workflows/diagrams.yml b/.github/workflows/diagrams.yml index 8b8cee500e..a7671824cf 100644 --- a/.github/workflows/diagrams.yml +++ b/.github/workflows/diagrams.yml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-latest name: "Create class diagrams of all packages" steps: - - uses: dart-lang/setup-dart@ca7e6fee45ffbd82b555a7ebfc236d2c86439f5b # pin@v1 + - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 # pin@v1 with: sdk: stable diff --git a/.github/workflows/dio.yml b/.github/workflows/dio.yml index f92f029d98..e3a2414077 100644 --- a/.github/workflows/dio.yml +++ b/.github/workflows/dio.yml @@ -40,7 +40,7 @@ jobs: - os: macos-latest sdk: beta steps: - - uses: dart-lang/setup-dart@ca7e6fee45ffbd82b555a7ebfc236d2c86439f5b # pin@v1 + - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 # pin@v1 with: sdk: ${{ matrix.sdk }} - uses: actions/checkout@v4 diff --git a/.github/workflows/e2e_dart.yml b/.github/workflows/e2e_dart.yml index bec5e47c95..64a2644940 100644 --- a/.github/workflows/e2e_dart.yml +++ b/.github/workflows/e2e_dart.yml @@ -37,7 +37,7 @@ jobs: matrix: sdk: [stable, beta] steps: - - uses: dart-lang/setup-dart@ca7e6fee45ffbd82b555a7ebfc236d2c86439f5b # pin@v1 + - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 # pin@v1 with: sdk: ${{ matrix.sdk }} - uses: actions/checkout@v4 diff --git a/.github/workflows/file.yml b/.github/workflows/file.yml index d981a7cac5..121d82aa9d 100644 --- a/.github/workflows/file.yml +++ b/.github/workflows/file.yml @@ -41,7 +41,7 @@ jobs: - os: macos-latest sdk: beta steps: - - uses: dart-lang/setup-dart@ca7e6fee45ffbd82b555a7ebfc236d2c86439f5b # pin@v1 + - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 # pin@v1 with: sdk: ${{ matrix.sdk }} - uses: actions/checkout@v4 diff --git a/.github/workflows/flutter-symbols.yml b/.github/workflows/flutter-symbols.yml index 4462ccccc8..e9fccdbbbc 100644 --- a/.github/workflows/flutter-symbols.yml +++ b/.github/workflows/flutter-symbols.yml @@ -21,7 +21,7 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: dart-lang/setup-dart@ca7e6fee45ffbd82b555a7ebfc236d2c86439f5b # pin@v1 + - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 # pin@v1 - run: dart pub get @@ -33,7 +33,7 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: dart-lang/setup-dart@ca7e6fee45ffbd82b555a7ebfc236d2c86439f5b # pin@v1 + - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 # pin@v1 - run: dart pub get diff --git a/.github/workflows/format-and-fix.yml b/.github/workflows/format-and-fix.yml index 4f6d96f106..681514d13d 100644 --- a/.github/workflows/format-and-fix.yml +++ b/.github/workflows/format-and-fix.yml @@ -30,7 +30,7 @@ jobs: working-directory: ${{ matrix.package.name }} steps: - uses: actions/checkout@v4 - - uses: dart-lang/setup-dart@ca7e6fee45ffbd82b555a7ebfc236d2c86439f5b # pin@v1 + - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 # pin@v1 if: ${{ matrix.package.sdk == 'dart' }} - uses: subosito/flutter-action@2783a3f08e1baf891508463f8c6653c258246225 # pin@v2.12.0 if: ${{ matrix.package.sdk == 'flutter' }} diff --git a/.github/workflows/hive.yml b/.github/workflows/hive.yml index 5893673318..389c224daa 100644 --- a/.github/workflows/hive.yml +++ b/.github/workflows/hive.yml @@ -40,7 +40,7 @@ jobs: - os: macos-latest sdk: beta steps: - - uses: dart-lang/setup-dart@ca7e6fee45ffbd82b555a7ebfc236d2c86439f5b # pin@v1 + - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 # pin@v1 with: sdk: ${{ matrix.sdk }} - uses: actions/checkout@v4 diff --git a/.github/workflows/logging.yml b/.github/workflows/logging.yml index 9a3fead839..f11a269df9 100644 --- a/.github/workflows/logging.yml +++ b/.github/workflows/logging.yml @@ -40,7 +40,7 @@ jobs: - os: macos-latest sdk: beta steps: - - uses: dart-lang/setup-dart@ca7e6fee45ffbd82b555a7ebfc236d2c86439f5b # pin@v1 + - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 # pin@v1 with: sdk: ${{ matrix.sdk }} - uses: actions/checkout@v4 From 1ac008b595f39f8eb8d7c8d67df3f9db827b7c1e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 6 Feb 2024 10:04:32 +0100 Subject: [PATCH 074/237] chore(deps): update Cocoa SDK to v8.20.0 (#1856) * chore: update flutter/scripts/update-cocoa.sh to 8.20.0 * format --------- Co-authored-by: GitHub Co-authored-by: GIancarlo Buenaflor --- CHANGELOG.md | 8 ++++++++ flutter/ios/sentry_flutter.podspec | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ddf41c4811..a3cf574ec4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## Unreleased + +### Dependencies + +- Bump Cocoa SDK from v8.19.0 to v8.20.0 ([#1856](https://github.com/getsentry/sentry-dart/pull/1856)) + - [changelog](https://github.com/getsentry/sentry-cocoa/blob/main/CHANGELOG.md#8200) + - [diff](https://github.com/getsentry/sentry-cocoa/compare/8.19.0...8.20.0) + ## 7.16.0 ### Features diff --git a/flutter/ios/sentry_flutter.podspec b/flutter/ios/sentry_flutter.podspec index 03220ac7bf..dc89732f1d 100644 --- a/flutter/ios/sentry_flutter.podspec +++ b/flutter/ios/sentry_flutter.podspec @@ -12,7 +12,7 @@ Sentry SDK for Flutter with support to native through sentry-cocoa. :tag => s.version.to_s } s.source_files = 'Classes/**/*' s.public_header_files = 'Classes/**/*.h' - s.dependency 'Sentry/HybridSDK', '8.19.0' + s.dependency 'Sentry/HybridSDK', '8.20.0' s.ios.dependency 'Flutter' s.osx.dependency 'FlutterMacOS' s.ios.deployment_target = '11.0' From e6dd065c8b3bafc026a4752d488eb0382ba2481a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 6 Feb 2024 10:26:37 +0100 Subject: [PATCH 075/237] build(deps): bump natiginfo/action-detekt-all from 1.23.4 to 1.23.5 (#1862) Bumps [natiginfo/action-detekt-all](https://github.com/natiginfo/action-detekt-all) from 1.23.4 to 1.23.5. - [Release notes](https://github.com/natiginfo/action-detekt-all/releases) - [Commits](https://github.com/natiginfo/action-detekt-all/compare/1349d3d957cba64d7b6b2752ef874d1e03e402a2...60495f27089d3432d83335c1f14e46ba61de5637) --- updated-dependencies: - dependency-name: natiginfo/action-detekt-all dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor --- .github/workflows/flutter.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/flutter.yml b/.github/workflows/flutter.yml index 4443f84e05..80d7f2706b 100644 --- a/.github/workflows/flutter.yml +++ b/.github/workflows/flutter.yml @@ -201,6 +201,6 @@ jobs: steps: - uses: actions/checkout@v4 # To recreate baseline run: detekt -i flutter/android,flutter/example/android -b flutter/config/detekt-bl.xml -cb - - uses: natiginfo/action-detekt-all@1349d3d957cba64d7b6b2752ef874d1e03e402a2 # pin@1.23.4 + - uses: natiginfo/action-detekt-all@60495f27089d3432d83335c1f14e46ba61de5637 # pin@1.23.5 with: args: -i flutter/android,flutter/example/android --baseline flutter/config/detekt-bl.xml --jvm-target 1.8 --build-upon-default-config --all-rules From cdd9dbd1a11b15908137ff30bcba6655e7547732 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 6 Feb 2024 10:26:49 +0100 Subject: [PATCH 076/237] build(deps): bump codecov/codecov-action from 3.1.5 to 4.0.1 (#1863) Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 3.1.5 to 4.0.1. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/4fe8c5f003fae66aa5ebb77cfd3e7bfbbda0b6b0...e0b68c6749509c5f83f984dd99a76a1c1a231044) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor --- .github/workflows/dart.yml | 2 +- .github/workflows/dio.yml | 2 +- .github/workflows/drift.yml | 2 +- .github/workflows/file.yml | 2 +- .github/workflows/flutter.yml | 2 +- .github/workflows/hive.yml | 2 +- .github/workflows/isar.yml | 2 +- .github/workflows/logging.yml | 2 +- .github/workflows/sqflite.yml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml index 70d3f291d5..776d63826c 100644 --- a/.github/workflows/dart.yml +++ b/.github/workflows/dart.yml @@ -68,7 +68,7 @@ jobs: dart pub get webdev build - - uses: codecov/codecov-action@4fe8c5f003fae66aa5ebb77cfd3e7bfbbda0b6b0 # pin@v3 + - uses: codecov/codecov-action@e0b68c6749509c5f83f984dd99a76a1c1a231044 # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: name: sentry diff --git a/.github/workflows/dio.yml b/.github/workflows/dio.yml index e3a2414077..29f750381d 100644 --- a/.github/workflows/dio.yml +++ b/.github/workflows/dio.yml @@ -52,7 +52,7 @@ jobs: dart test -p vm --coverage=coverage --test-randomize-ordering-seed=random --chain-stack-traces dart pub run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.dart_tool/package_config.json --report-on=lib - - uses: codecov/codecov-action@4fe8c5f003fae66aa5ebb77cfd3e7bfbbda0b6b0 # pin@v3 + - uses: codecov/codecov-action@e0b68c6749509c5f83f984dd99a76a1c1a231044 # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: name: sentry_dio diff --git a/.github/workflows/drift.yml b/.github/workflows/drift.yml index bbd07f905b..b3c8b1dc91 100644 --- a/.github/workflows/drift.yml +++ b/.github/workflows/drift.yml @@ -93,7 +93,7 @@ jobs: cd drift flutter test --coverage --test-randomize-ordering-seed=random - - uses: codecov/codecov-action@4fe8c5f003fae66aa5ebb77cfd3e7bfbbda0b6b0 # pin@v3 + - uses: codecov/codecov-action@e0b68c6749509c5f83f984dd99a76a1c1a231044 # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' with: name: sentry_drift diff --git a/.github/workflows/file.yml b/.github/workflows/file.yml index 121d82aa9d..41c4623324 100644 --- a/.github/workflows/file.yml +++ b/.github/workflows/file.yml @@ -52,7 +52,7 @@ jobs: dart test -p vm --coverage=coverage --test-randomize-ordering-seed=random --chain-stack-traces dart pub run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.dart_tool/package_config.json --report-on=lib - - uses: codecov/codecov-action@4fe8c5f003fae66aa5ebb77cfd3e7bfbbda0b6b0 # pin@v3 + - uses: codecov/codecov-action@e0b68c6749509c5f83f984dd99a76a1c1a231044 # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: name: sentry_file diff --git a/.github/workflows/flutter.yml b/.github/workflows/flutter.yml index 80d7f2706b..02d9a1f012 100644 --- a/.github/workflows/flutter.yml +++ b/.github/workflows/flutter.yml @@ -106,7 +106,7 @@ jobs: flutter test --coverage --test-randomize-ordering-seed=random dart run remove_from_coverage -f coverage/lcov.info -r 'binding.dart' - - uses: codecov/codecov-action@4fe8c5f003fae66aa5ebb77cfd3e7bfbbda0b6b0 # pin@v3 + - uses: codecov/codecov-action@e0b68c6749509c5f83f984dd99a76a1c1a231044 # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' with: name: sentry_flutter diff --git a/.github/workflows/hive.yml b/.github/workflows/hive.yml index 389c224daa..f13e8d1522 100644 --- a/.github/workflows/hive.yml +++ b/.github/workflows/hive.yml @@ -51,7 +51,7 @@ jobs: dart test -p vm --coverage=coverage --test-randomize-ordering-seed=random --chain-stack-traces dart pub run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.dart_tool/package_config.json --report-on=lib - - uses: codecov/codecov-action@4fe8c5f003fae66aa5ebb77cfd3e7bfbbda0b6b0 # pin@v3 + - uses: codecov/codecov-action@e0b68c6749509c5f83f984dd99a76a1c1a231044 # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: name: sentry_hive diff --git a/.github/workflows/isar.yml b/.github/workflows/isar.yml index f4038421df..a1e67c3bc8 100644 --- a/.github/workflows/isar.yml +++ b/.github/workflows/isar.yml @@ -93,7 +93,7 @@ jobs: cd isar flutter test -j 1 --coverage --test-randomize-ordering-seed=random - - uses: codecov/codecov-action@4fe8c5f003fae66aa5ebb77cfd3e7bfbbda0b6b0 # pin@v3 + - uses: codecov/codecov-action@e0b68c6749509c5f83f984dd99a76a1c1a231044 # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' with: name: sentry_isar diff --git a/.github/workflows/logging.yml b/.github/workflows/logging.yml index f11a269df9..6eafdc199a 100644 --- a/.github/workflows/logging.yml +++ b/.github/workflows/logging.yml @@ -52,7 +52,7 @@ jobs: dart test -p vm --coverage=coverage --test-randomize-ordering-seed=random --chain-stack-traces dart pub run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.dart_tool/package_config.json --report-on=lib - - uses: codecov/codecov-action@4fe8c5f003fae66aa5ebb77cfd3e7bfbbda0b6b0 # pin@v3 + - uses: codecov/codecov-action@e0b68c6749509c5f83f984dd99a76a1c1a231044 # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: name: sentry_logging diff --git a/.github/workflows/sqflite.yml b/.github/workflows/sqflite.yml index a94c31475f..9d3caa78bd 100644 --- a/.github/workflows/sqflite.yml +++ b/.github/workflows/sqflite.yml @@ -93,7 +93,7 @@ jobs: cd sqflite flutter test --coverage --test-randomize-ordering-seed=random - - uses: codecov/codecov-action@4fe8c5f003fae66aa5ebb77cfd3e7bfbbda0b6b0 # pin@v3 + - uses: codecov/codecov-action@e0b68c6749509c5f83f984dd99a76a1c1a231044 # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' with: name: sentry_sqflite From ba9c106515fc2731497c7e40c2ea0f885336884a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kry=C5=A1tof=20Wold=C5=99ich?= <31292499+krystofwoldrich@users.noreply.github.com> Date: Tue, 6 Feb 2024 21:17:16 +0100 Subject: [PATCH 077/237] chore(android): Remove dead code, cold start bool is now always present (#1861) * chore(android): Remove dead code, cold start bool is now always present * Update CHANGELOG.md --------- Co-authored-by: Giancarlo Buenaflor --- CHANGELOG.md | 4 ++++ .../src/main/kotlin/io/sentry/flutter/SentryFlutterPlugin.kt | 3 --- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a3cf574ec4..6ec2a05f5e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Fixes + +- Remove dead code, cold start bool is now always present ([#1861](https://github.com/getsentry/sentry-dart/pull/1861)) + ### Dependencies - Bump Cocoa SDK from v8.19.0 to v8.20.0 ([#1856](https://github.com/getsentry/sentry-dart/pull/1856)) diff --git a/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutterPlugin.kt b/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutterPlugin.kt index b908ff823f..ea9ab9d17e 100644 --- a/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutterPlugin.kt +++ b/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutterPlugin.kt @@ -147,9 +147,6 @@ class SentryFlutterPlugin : FlutterPlugin, MethodCallHandler, ActivityAware { if (appStartTime == null) { Log.w("Sentry", "App start won't be sent due to missing appStartTime") result.success(null) - } else if (isColdStart == null) { - Log.w("Sentry", "App start won't be sent due to missing isColdStart") - result.success(null) } else { val appStartTimeMillis = DateUtils.nanosToMillis(appStartTime.nanoTimestamp().toDouble()) val item = mapOf( From ffe46aea1c056bb411a050327d2349bcb673aa0e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 6 Feb 2024 21:17:42 +0100 Subject: [PATCH 078/237] chore: update scripts/update-symbol-collector.sh to 1.15.0 (#1853) Co-authored-by: GitHub --- .../flutter_symbol_collector/lib/src/symbol_collector_cli.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/flutter_symbol_collector/lib/src/symbol_collector_cli.dart b/scripts/flutter_symbol_collector/lib/src/symbol_collector_cli.dart index 1d4e29a66a..c3ab23ee83 100644 --- a/scripts/flutter_symbol_collector/lib/src/symbol_collector_cli.dart +++ b/scripts/flutter_symbol_collector/lib/src/symbol_collector_cli.dart @@ -19,7 +19,7 @@ class SymbolCollectorCli { // https://github.com/getsentry/symbol-collector/releases @internal - static const version = '1.14.0'; + static const version = '1.15.0'; @internal late final String cli; From e8ed5a0306881da1b886aca12ca43f372db9d350 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 6 Feb 2024 22:06:39 +0100 Subject: [PATCH 079/237] build(deps): bump gradle/gradle-build-action from 2 to 3 (#1851) * build(deps): bump gradle/gradle-build-action from 2 to 3 Bumps [gradle/gradle-build-action](https://github.com/gradle/gradle-build-action) from 2 to 3. - [Release notes](https://github.com/gradle/gradle-build-action/releases) - [Commits](https://github.com/gradle/gradle-build-action/compare/v2...v3) --- updated-dependencies: - dependency-name: gradle/gradle-build-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] * Update flutter_test.yml --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor --- .github/workflows/flutter_test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/flutter_test.yml b/.github/workflows/flutter_test.yml index 391f10d5af..e90485c9a4 100644 --- a/.github/workflows/flutter_test.yml +++ b/.github/workflows/flutter_test.yml @@ -54,7 +54,7 @@ jobs: run: flutter pub get - name: Gradle cache - uses: gradle/gradle-build-action@v2 + uses: gradle/gradle-build-action@3b1b3b9a2104c2b47fbae53f3938079c00c9bb87 - name: AVD cache uses: actions/cache@v4 From 91ff12ff7ca274d12f116f683bba209ebd06823a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 6 Feb 2024 22:11:05 +0100 Subject: [PATCH 080/237] chore: update scripts/update-symbol-collector.sh to 1.15.0 (#1869) Co-authored-by: GitHub Co-authored-by: Giancarlo Buenaflor From 6f57f1506ef07411d50f2a3154043d32b7c176ad Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Wed, 7 Feb 2024 10:55:33 +0100 Subject: [PATCH 081/237] fix: remove Flutter dep from Drift integration (#1867) * Remove Flutter dep * Update CHANGELOG --- CHANGELOG.md | 1 + drift/pubspec.yaml | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ec2a05f5e..56777b2fde 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### Fixes +- Remove Flutter dependency from Drift integration ([#1867](https://github.com/getsentry/sentry-dart/pull/1867)) - Remove dead code, cold start bool is now always present ([#1861](https://github.com/getsentry/sentry-dart/pull/1861)) ### Dependencies diff --git a/drift/pubspec.yaml b/drift/pubspec.yaml index 92323b4f63..93a854043f 100644 --- a/drift/pubspec.yaml +++ b/drift/pubspec.yaml @@ -7,7 +7,6 @@ issue_tracker: https://github.com/getsentry/sentry-dart/issues environment: sdk: '>=2.17.0 <4.0.0' - flutter: '>=3.3.0' dependencies: sentry: 7.16.0 From 2966d88d828c6e2604b15b95f0d0d958acc2cc68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20Andra=C5=A1ec?= Date: Wed, 14 Feb 2024 09:31:51 +0000 Subject: [PATCH 082/237] Fix iOS "Arithmetic Overflow" (#1874) * guard against arithmetic overflow * Fix issue where transaction was finished multiple times * add changelog entry * update test expectations * test that didPop does not call finsh transaction multiple times --- CHANGELOG.md | 1 + .../Classes/SentryFlutterPluginApple.swift | 7 +++--- .../navigation/sentry_navigator_observer.dart | 10 ++++++-- .../test/sentry_navigator_observer_test.dart | 25 ++++++++++++++++--- 4 files changed, 34 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 56777b2fde..415db64a2e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - Remove Flutter dependency from Drift integration ([#1867](https://github.com/getsentry/sentry-dart/pull/1867)) - Remove dead code, cold start bool is now always present ([#1861](https://github.com/getsentry/sentry-dart/pull/1861)) +- Fix iOS "Arithmetic Overflow" ([#1874](https://github.com/getsentry/sentry-dart/pull/1874)) ### Dependencies diff --git a/flutter/ios/Classes/SentryFlutterPluginApple.swift b/flutter/ios/Classes/SentryFlutterPluginApple.swift index be5e301791..ec6eb7cdb7 100644 --- a/flutter/ios/Classes/SentryFlutterPluginApple.swift +++ b/flutter/ios/Classes/SentryFlutterPluginApple.swift @@ -430,10 +430,9 @@ public class SentryFlutterPluginApple: NSObject, FlutterPlugin { } let currentFrames = PrivateSentrySDKOnly.currentScreenFrames - - let total = currentFrames.total - totalFrames - let frozen = currentFrames.frozen - frozenFrames - let slow = currentFrames.slow - slowFrames + let total = max(Int(currentFrames.total) - Int(totalFrames), 0) + let frozen = max(Int(currentFrames.frozen) - Int(frozenFrames), 0) + let slow = max(Int(currentFrames.slow) - Int(slowFrames), 0) if total <= 0 && frozen <= 0 && slow <= 0 { result(nil) diff --git a/flutter/lib/src/navigation/sentry_navigator_observer.dart b/flutter/lib/src/navigation/sentry_navigator_observer.dart index 6893d47aca..b24f4f0c7b 100644 --- a/flutter/lib/src/navigation/sentry_navigator_observer.dart +++ b/flutter/lib/src/navigation/sentry_navigator_observer.dart @@ -207,6 +207,7 @@ class SentryNavigatorObserver extends RouteObserver> { autoFinishAfter: _autoFinishAfter, trimEnd: true, onFinish: (transaction) async { + _transaction = null; final nativeFrames = await _native ?.endNativeFramesCollection(transaction.context.traceId); if (nativeFrames != null) { @@ -241,8 +242,13 @@ class SentryNavigatorObserver extends RouteObserver> { } Future _finishTransaction() async { - _transaction?.status ??= SpanStatus.ok(); - await _transaction?.finish(); + final transaction = _transaction; + _transaction = null; + if (transaction == null || transaction.finished) { + return; + } + transaction.status ??= SpanStatus.ok(); + await transaction.finish(); } } diff --git a/flutter/test/sentry_navigator_observer_test.dart b/flutter/test/sentry_navigator_observer_test.dart index c49588ab85..aca9646c0b 100644 --- a/flutter/test/sentry_navigator_observer_test.dart +++ b/flutter/test/sentry_navigator_observer_test.dart @@ -261,7 +261,7 @@ void main() { final secondRoute = route(RouteSettings(name: 'Second Route')); final hub = _MockHub(); - final span = getMockSentryTracer(); + final span = getMockSentryTracer(finished: false); when(span.context).thenReturn(SentrySpanContext(operation: 'op')); when(span.status).thenReturn(null); _whenAnyStart(hub, span); @@ -279,7 +279,7 @@ void main() { final currentRoute = route(RouteSettings(name: 'Current Route')); final hub = _MockHub(); - final span = getMockSentryTracer(); + final span = getMockSentryTracer(finished: false); when(span.context).thenReturn(SentrySpanContext(operation: 'op')); when(span.status).thenReturn(null); _whenAnyStart(hub, span); @@ -293,6 +293,24 @@ void main() { verify(span.finish()); }); + test('multiple didPop only finish transaction once', () { + final currentRoute = route(RouteSettings(name: 'Current Route')); + + final hub = _MockHub(); + final span = getMockSentryTracer(finished: false); + when(span.context).thenReturn(SentrySpanContext(operation: 'op')); + when(span.status).thenReturn(null); + _whenAnyStart(hub, span); + + final sut = fixture.getSut(hub: hub); + + sut.didPush(currentRoute, null); + sut.didPop(currentRoute, null); + sut.didPop(currentRoute, null); + + verify(span.finish()).called(1); + }); + test('didPop re-starts previous', () { final previousRoute = route(RouteSettings(name: 'Previous Route')); final currentRoute = route(RouteSettings(name: 'Current Route')); @@ -833,9 +851,10 @@ class _MockHub extends MockHub { } } -ISentrySpan getMockSentryTracer({String? name}) { +ISentrySpan getMockSentryTracer({String? name, bool? finished}) { final tracer = MockSentryTracer(); when(tracer.name).thenReturn(name ?? 'name'); + when(tracer.finished).thenReturn(finished ?? true); return tracer; } From 65c9645c475b3296f06e68cf52105672179bb3a6 Mon Sep 17 00:00:00 2001 From: getsentry-bot Date: Wed, 14 Feb 2024 09:44:58 +0000 Subject: [PATCH 083/237] release: 7.16.1 --- CHANGELOG.md | 2 +- dart/lib/src/version.dart | 2 +- dart/pubspec.yaml | 2 +- dio/lib/src/version.dart | 2 +- dio/pubspec.yaml | 4 ++-- drift/lib/src/version.dart | 2 +- drift/pubspec.yaml | 4 ++-- file/lib/src/version.dart | 2 +- file/pubspec.yaml | 4 ++-- flutter/example/pubspec.yaml | 2 +- flutter/lib/src/version.dart | 2 +- flutter/pubspec.yaml | 4 ++-- hive/lib/src/version.dart | 2 +- hive/pubspec.yaml | 4 ++-- isar/lib/src/version.dart | 2 +- isar/pubspec.yaml | 4 ++-- logging/lib/src/version.dart | 2 +- logging/pubspec.yaml | 4 ++-- sqflite/lib/src/version.dart | 2 +- sqflite/pubspec.yaml | 4 ++-- 20 files changed, 28 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 415db64a2e..52f902b373 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## Unreleased +## 7.16.1 ### Fixes diff --git a/dart/lib/src/version.dart b/dart/lib/src/version.dart index c29bdd09cb..3ad262fa98 100644 --- a/dart/lib/src/version.dart +++ b/dart/lib/src/version.dart @@ -9,7 +9,7 @@ library version; /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.16.0'; +const String sdkVersion = '7.16.1'; String sdkName(bool isWeb) => isWeb ? _browserSdkName : _ioSdkName; diff --git a/dart/pubspec.yaml b/dart/pubspec.yaml index 1cc9bf8c75..6021b39df7 100644 --- a/dart/pubspec.yaml +++ b/dart/pubspec.yaml @@ -1,5 +1,5 @@ name: sentry -version: 7.16.0 +version: 7.16.1 description: > A crash reporting library for Dart that sends crash reports to Sentry.io. This library supports Dart VM and Web. For Flutter consider sentry_flutter instead. diff --git a/dio/lib/src/version.dart b/dio/lib/src/version.dart index 175e956f04..46d77d60ec 100644 --- a/dio/lib/src/version.dart +++ b/dio/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.16.0'; +const String sdkVersion = '7.16.1'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_dio'; diff --git a/dio/pubspec.yaml b/dio/pubspec.yaml index e1f02a0123..82443b5eb1 100644 --- a/dio/pubspec.yaml +++ b/dio/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_dio description: An integration which adds support for performance tracing for the Dio package. -version: 7.16.0 +version: 7.16.1 homepage: https://docs.sentry.io/platforms/dart/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -11,7 +11,7 @@ environment: dependencies: dio: ^5.0.0 - sentry: 7.16.0 + sentry: 7.16.1 dev_dependencies: meta: ^1.3.0 diff --git a/drift/lib/src/version.dart b/drift/lib/src/version.dart index 2795a157be..7f75ff407a 100644 --- a/drift/lib/src/version.dart +++ b/drift/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.16.0'; +const String sdkVersion = '7.16.1'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_drift'; diff --git a/drift/pubspec.yaml b/drift/pubspec.yaml index 93a854043f..a4c6fdee08 100644 --- a/drift/pubspec.yaml +++ b/drift/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_drift description: An integration which adds support for performance tracing for the drift package. -version: 7.16.0 +version: 7.16.1 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -9,7 +9,7 @@ environment: sdk: '>=2.17.0 <4.0.0' dependencies: - sentry: 7.16.0 + sentry: 7.16.1 meta: ^1.3.0 drift: ^2.13.0 diff --git a/file/lib/src/version.dart b/file/lib/src/version.dart index a2a31b3a5e..e04b2f58b0 100644 --- a/file/lib/src/version.dart +++ b/file/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.16.0'; +const String sdkVersion = '7.16.1'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_file'; diff --git a/file/pubspec.yaml b/file/pubspec.yaml index 509e596a13..8f2208135d 100644 --- a/file/pubspec.yaml +++ b/file/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_file description: An integration which adds support for performance tracing for dart.io.File. -version: 7.16.0 +version: 7.16.1 homepage: https://docs.sentry.io/platforms/dart/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -10,7 +10,7 @@ environment: sdk: '>=2.19.0 <4.0.0' dependencies: - sentry: 7.16.0 + sentry: 7.16.1 meta: ^1.3.0 dev_dependencies: diff --git a/flutter/example/pubspec.yaml b/flutter/example/pubspec.yaml index 6530b23e99..255acb68f4 100644 --- a/flutter/example/pubspec.yaml +++ b/flutter/example/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_flutter_example description: Demonstrates how to use the sentry_flutter plugin. -version: 7.16.0 +version: 7.16.1 publish_to: 'none' # Remove this line if you wish to publish to pub.dev diff --git a/flutter/lib/src/version.dart b/flutter/lib/src/version.dart index 078ad6a08f..436f5e0a3e 100644 --- a/flutter/lib/src/version.dart +++ b/flutter/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.16.0'; +const String sdkVersion = '7.16.1'; /// The default SDK name reported to Sentry.io in the submitted events. const String sdkName = 'sentry.dart.flutter'; diff --git a/flutter/pubspec.yaml b/flutter/pubspec.yaml index 9757dbd698..e2cfbed0e0 100644 --- a/flutter/pubspec.yaml +++ b/flutter/pubspec.yaml @@ -1,5 +1,5 @@ name: sentry_flutter -version: 7.16.0 +version: 7.16.1 description: Sentry SDK for Flutter. This package aims to support different Flutter targets by relying on the many platforms supported by Sentry with native SDKs. homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart @@ -15,7 +15,7 @@ dependencies: sdk: flutter flutter_web_plugins: sdk: flutter - sentry: 7.16.0 + sentry: 7.16.1 package_info_plus: '>=1.0.0 <=5.0.1' meta: ^1.3.0 ffi: ^2.0.0 diff --git a/hive/lib/src/version.dart b/hive/lib/src/version.dart index ac6247b5a5..2dafd49739 100644 --- a/hive/lib/src/version.dart +++ b/hive/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.16.0'; +const String sdkVersion = '7.16.1'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_hive'; diff --git a/hive/pubspec.yaml b/hive/pubspec.yaml index cbcb5b16e6..abb9cec12a 100644 --- a/hive/pubspec.yaml +++ b/hive/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_hive description: An integration which adds support for performance tracing for the hive package. -version: 7.16.0 +version: 7.16.1 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -9,7 +9,7 @@ environment: sdk: '>=2.17.0 <4.0.0' dependencies: - sentry: 7.16.0 + sentry: 7.16.1 hive: ^2.2.3 meta: ^1.3.0 diff --git a/isar/lib/src/version.dart b/isar/lib/src/version.dart index 0e551e8349..8b6ad5a4c0 100644 --- a/isar/lib/src/version.dart +++ b/isar/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.16.0'; +const String sdkVersion = '7.16.1'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_isar'; diff --git a/isar/pubspec.yaml b/isar/pubspec.yaml index 81770c4d52..4e54204063 100644 --- a/isar/pubspec.yaml +++ b/isar/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_isar description: An integration which adds support for performance tracing for the isar package. -version: 7.16.0 +version: 7.16.1 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -12,7 +12,7 @@ environment: dependencies: isar: ^3.1.0 isar_flutter_libs: ^3.1.0 # contains Isar Core - sentry: 7.16.0 + sentry: 7.16.1 meta: ^1.3.0 path: ^1.8.3 diff --git a/logging/lib/src/version.dart b/logging/lib/src/version.dart index 47dc6b25a2..2e858e22d4 100644 --- a/logging/lib/src/version.dart +++ b/logging/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.16.0'; +const String sdkVersion = '7.16.1'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_logging'; diff --git a/logging/pubspec.yaml b/logging/pubspec.yaml index 97e888064b..70b879d98b 100644 --- a/logging/pubspec.yaml +++ b/logging/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_logging description: An integration which adds support for recording log from the logging package. -version: 7.16.0 +version: 7.16.1 homepage: https://docs.sentry.io/platforms/dart/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -11,7 +11,7 @@ environment: dependencies: logging: ^1.0.0 - sentry: 7.16.0 + sentry: 7.16.1 dev_dependencies: lints: ^3.0.0 diff --git a/sqflite/lib/src/version.dart b/sqflite/lib/src/version.dart index 6982ffcf1f..0363d9675c 100644 --- a/sqflite/lib/src/version.dart +++ b/sqflite/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.16.0'; +const String sdkVersion = '7.16.1'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_sqflite'; diff --git a/sqflite/pubspec.yaml b/sqflite/pubspec.yaml index 4fae66faf9..8ca7ba896b 100644 --- a/sqflite/pubspec.yaml +++ b/sqflite/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_sqflite description: An integration which adds support for performance tracing for the sqflite package. -version: 7.16.0 +version: 7.16.1 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -10,7 +10,7 @@ environment: flutter: '>=3.3.0' # matching sqflite dependencies: - sentry: 7.16.0 + sentry: 7.16.1 sqflite: ^2.0.0 sqflite_common: ^2.0.0 meta: ^1.3.0 From 55610cd119c6f00ff29fd08d54453130df9e3000 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 Feb 2024 13:32:31 +0100 Subject: [PATCH 084/237] build(deps): bump gradle/gradle-build-action from 3.0.0 to 3.1.0 (#1885) Bumps [gradle/gradle-build-action](https://github.com/gradle/gradle-build-action) from 3.0.0 to 3.1.0. - [Release notes](https://github.com/gradle/gradle-build-action/releases) - [Commits](https://github.com/gradle/gradle-build-action/compare/3b1b3b9a2104c2b47fbae53f3938079c00c9bb87...29c0906b64b8fc82467890bfb7a0a7ef34bda89e) --- updated-dependencies: - dependency-name: gradle/gradle-build-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/flutter_test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/flutter_test.yml b/.github/workflows/flutter_test.yml index e90485c9a4..637b4d1a41 100644 --- a/.github/workflows/flutter_test.yml +++ b/.github/workflows/flutter_test.yml @@ -54,7 +54,7 @@ jobs: run: flutter pub get - name: Gradle cache - uses: gradle/gradle-build-action@3b1b3b9a2104c2b47fbae53f3938079c00c9bb87 + uses: gradle/gradle-build-action@29c0906b64b8fc82467890bfb7a0a7ef34bda89e - name: AVD cache uses: actions/cache@v4 From b0811ccc76dccb91004b36b5f710163daf733d92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20Andra=C5=A1ec?= Date: Wed, 28 Feb 2024 12:59:15 +0000 Subject: [PATCH 085/237] Disable canvasKit renderer tests for `beta` channel (#1894) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Disable canvasKit renderer tests for ‚beta‘ channel * fix condition * fix analyzer issues --- .github/workflows/flutter.yml | 8 +++++++- flutter/example/lib/main.dart | 27 ++++----------------------- 2 files changed, 11 insertions(+), 24 deletions(-) diff --git a/.github/workflows/flutter.yml b/.github/workflows/flutter.yml index 02d9a1f012..456a7970f2 100644 --- a/.github/workflows/flutter.yml +++ b/.github/workflows/flutter.yml @@ -93,11 +93,17 @@ jobs: cd flutter flutter pub get - - name: Test chrome + - name: Test chrome (exclude canvasKit) if: runner.os == 'Linux' run: | cd flutter flutter test --platform chrome --test-randomize-ordering-seed=random --exclude-tags canvasKit + + # TODO: Revert when canvasKit is available again in `beta` channel + - name: Test chrome (canvasKit) + if: runner.os == 'Linux' && matrix.sdk != 'beta' + run: | + cd flutter flutter test --platform chrome --test-randomize-ordering-seed=random --tags canvasKit --web-renderer canvaskit - name: Test VM with coverage diff --git a/flutter/example/lib/main.dart b/flutter/example/lib/main.dart index 26bbdce6d8..55b9072394 100644 --- a/flutter/example/lib/main.dart +++ b/flutter/example/lib/main.dart @@ -478,12 +478,8 @@ class MainScaffold extends StatelessWidget { TooltipButton( onPressed: () async { final id = await Sentry.captureMessage('UserFeedback'); - // ignore: use_build_context_synchronously - if (!context.isMounted) { - return; - } - // ignore: use_build_context_synchronously + if (!context.mounted) return; await showDialog( context: context, builder: (context) { @@ -906,12 +902,7 @@ Future makeWebRequest(BuildContext context) async { await transaction.finish(status: const SpanStatus.ok()); - // ignore: use_build_context_synchronously - if (!context.isMounted) { - return; - } - - // ignore: use_build_context_synchronously + if (!context.mounted) return; await showDialog( context: context, builder: (context) { @@ -957,12 +948,7 @@ Future makeWebRequestWithDio(BuildContext context) async { await span.finish(); } - // ignore: use_build_context_synchronously - if (!context.isMounted) { - return; - } - - // ignore: use_build_context_synchronously + if (!context.mounted) return; await showDialog( context: context, builder: (context) { @@ -992,12 +978,7 @@ Future showDialogWithTextAndImage(BuildContext context) async { final text = await DefaultAssetBundle.of(context).loadString('assets/lorem-ipsum.txt'); - // ignore: use_build_context_synchronously - if (!context.isMounted) { - return; - } - - // ignore: use_build_context_synchronously + if (!context.mounted) return; await showDialog( context: context, // gets tracked if using SentryNavigatorObserver From 30b663fe8ce27b385ad591eb1e16e765a2250c1e Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Fri, 1 Mar 2024 12:10:03 +0100 Subject: [PATCH 086/237] ci: disable package-analysis for now (#1897) * Disable for now --- .github/workflows/analyze.yml | 63 ++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 30 deletions(-) diff --git a/.github/workflows/analyze.yml b/.github/workflows/analyze.yml index 28d192a55a..b43828001c 100644 --- a/.github/workflows/analyze.yml +++ b/.github/workflows/analyze.yml @@ -51,33 +51,36 @@ jobs: - run: dart doc --dry-run - package-analysis: - # `axel-op/dart-package-analyzer` is using `flutter pub upgrade` instead of `get`, - # which ignores pubspec.yaml `dependency_overrides`. Because of that, all `release/*` branches are failing, - # because the package cannot find the "about to be released" version of our sentry-dart package that it depends on. - if: ${{ !startsWith(github.ref, 'refs/heads/release/') && inputs.panaThreshold > 0 }} - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4 - - name: Apply dependency override - if: ${{ inputs.package == 'flutter' }} - working-directory: ${{ inputs.package }} - run: | - sed -i.bak 's|sentry:.*|sentry:\n path: /github/workspace/dart|g' pubspec.yaml - - uses: axel-op/dart-package-analyzer@7a6c3c66bce78d82b729a1ffef2d9458fde6c8d2 # pin@v3 - id: analysis - with: - githubToken: ${{ secrets.GITHUB_TOKEN }} - relativePath: ${{ inputs.package }} - - name: Check scores - env: - TOTAL: ${{ steps.analysis.outputs.total }} - TOTAL_MAX: ${{ steps.analysis.outputs.total_max }} - run: | - PERCENTAGE=$(( $TOTAL * 100 / $TOTAL_MAX )) - if (( $PERCENTAGE < ${{ inputs.panaThreshold }} )) - then - echo Score too low! - exit 1 - fi +# Currently Disabled because of git error `detected dubious ownership in repository. +# TODO: check if this is still an issue when git version in github runners is updated +# +# package-analysis: +# # `axel-op/dart-package-analyzer` is using `flutter pub upgrade` instead of `get`, +# # which ignores pubspec.yaml `dependency_overrides`. Because of that, all `release/*` branches are failing, +# # because the package cannot find the "about to be released" version of our sentry-dart package that it depends on. +# if: ${{ !startsWith(github.ref, 'refs/heads/release/') && inputs.panaThreshold > 0 }} +# runs-on: ubuntu-20.04 +# timeout-minutes: 20 +# steps: +# - uses: actions/checkout@v4 +# - name: Apply dependency override +# if: ${{ inputs.package == 'flutter' }} +# working-directory: ${{ inputs.package }} +# run: | +# sed -i.bak 's|sentry:.*|sentry:\n path: /github/workspace/dart|g' pubspec.yaml +# - uses: axel-op/dart-package-analyzer@7a6c3c66bce78d82b729a1ffef2d9458fde6c8d2 # pin@v3 +# id: analysis +# with: +# githubToken: ${{ secrets.GITHUB_TOKEN }} +# relativePath: ${{ inputs.package }} +# - name: Check scores +# env: +# TOTAL: ${{ steps.analysis.outputs.total }} +# TOTAL_MAX: ${{ steps.analysis.outputs.total_max }} +# run: | +# PERCENTAGE=$(( $TOTAL * 100 / $TOTAL_MAX )) +# if (( $PERCENTAGE < ${{ inputs.panaThreshold }} )) +# then +# echo Score too low! +# exit 1 +# fi From 3d822bfaa6b34c9a4436a4825394a3647016193b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 4 Mar 2024 09:58:40 +0100 Subject: [PATCH 087/237] chore(deps): update Android SDK to v7.5.0 (#1907) * chore: update flutter/scripts/update-android.sh to 7.5.0 * Update ktlint --------- Co-authored-by: GitHub Co-authored-by: GIancarlo Buenaflor --- .github/workflows/flutter.yml | 2 +- flutter/android/build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/flutter.yml b/.github/workflows/flutter.yml index 456a7970f2..d55a9207f5 100644 --- a/.github/workflows/flutter.yml +++ b/.github/workflows/flutter.yml @@ -194,7 +194,7 @@ jobs: - uses: actions/checkout@v4 - name: ktlint - uses: ScaCap/action-ktlint@0ff81efa49425bd0df46caabd8005aafdc8f2cf2 # pin@1.8.0 + uses: ScaCap/action-ktlint@38262d0fb8bff43ddafc8b3c04bce6e6c7263319 # pin@1.8.1 with: github_token: ${{ secrets.github_token }} reporter: github-pr-review diff --git a/flutter/android/build.gradle b/flutter/android/build.gradle index 5bb8ed8a20..355d42709d 100644 --- a/flutter/android/build.gradle +++ b/flutter/android/build.gradle @@ -60,7 +60,7 @@ android { } dependencies { - api 'io.sentry:sentry-android:7.3.0' + api 'io.sentry:sentry-android:7.5.0' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" // Required -- JUnit 4 framework From af99cbd3cbd37a65798e5764a0b7d3d530af2900 Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Mon, 4 Mar 2024 10:50:20 +0100 Subject: [PATCH 088/237] ci: fix analyze issues (#1908) * Fix analyze issues --- dart/lib/src/client_reports/client_report_recorder.dart | 1 + dart/test/sentry_test.dart | 6 +++--- sqflite/lib/src/sentry_sqflite_transaction.dart | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/dart/lib/src/client_reports/client_report_recorder.dart b/dart/lib/src/client_reports/client_report_recorder.dart index 76ae9f03eb..d064941f84 100644 --- a/dart/lib/src/client_reports/client_report_recorder.dart +++ b/dart/lib/src/client_reports/client_report_recorder.dart @@ -46,6 +46,7 @@ class _QuantityKey { int get hashCode => Object.hash(reason.hashCode, category.hashCode); @override + // ignore: non_nullable_equals_parameter bool operator ==(dynamic other) { return other is _QuantityKey && other.reason == reason && diff --git a/dart/test/sentry_test.dart b/dart/test/sentry_test.dart index b041f19527..a361c0bc4f 100644 --- a/dart/test/sentry_test.dart +++ b/dart/test/sentry_test.dart @@ -21,9 +21,9 @@ void main() { final options = SentryOptions(dsn: fakeDsn)..automatedTestMode = true; await Sentry.init( options: options, - (options) => { - options.dsn = fakeDsn, - options.tracesSampleRate = 1.0, + (options) { + options.dsn = fakeDsn; + options.tracesSampleRate = 1.0; }, ); anException = Exception('anException'); diff --git a/sqflite/lib/src/sentry_sqflite_transaction.dart b/sqflite/lib/src/sentry_sqflite_transaction.dart index 78c41b487d..c51bfe1c53 100644 --- a/sqflite/lib/src/sentry_sqflite_transaction.dart +++ b/sqflite/lib/src/sentry_sqflite_transaction.dart @@ -23,8 +23,8 @@ class SentrySqfliteTransaction extends Transaction implements DatabaseExecutor { final Hub _hub; final String? _dbName; - // ignore: public_member_api_docs @internal + // ignore: public_member_api_docs SentrySqfliteTransaction( this._executor, { @internal Hub? hub, From f754e867516d18d38272967acc03289a4ff83c0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Uek=C3=B6tter?= Date: Mon, 4 Mar 2024 11:25:04 +0100 Subject: [PATCH 089/237] Clean up code (#1878) * Code clean up * fix doc comments --- .../enricher/io_enricher_event_processor.dart | 6 +- .../web_enricher_event_processor.dart | 4 +- dart/lib/src/hint.dart | 1 + dart/lib/src/sentry_client.dart | 2 +- dart/lib/src/sentry_stack_trace_factory.dart | 18 +- dart/lib/src/sentry_tracer.dart | 6 +- flutter/example/lib/main.dart | 222 ++++++++++-------- .../integrations/screenshot_integration.dart | 3 +- .../navigation/sentry_navigator_observer.dart | 21 +- flutter/lib/src/sentry_flutter_options.dart | 3 + 10 files changed, 154 insertions(+), 132 deletions(-) diff --git a/dart/lib/src/event_processor/enricher/io_enricher_event_processor.dart b/dart/lib/src/event_processor/enricher/io_enricher_event_processor.dart index 03623d7f0b..47e3481144 100644 --- a/dart/lib/src/event_processor/enricher/io_enricher_event_processor.dart +++ b/dart/lib/src/event_processor/enricher/io_enricher_event_processor.dart @@ -7,13 +7,11 @@ EnricherEventProcessor enricherEventProcessor(SentryOptions options) { return IoEnricherEventProcessor(options); } -/// Enriches [SentryEvents] with various kinds of information. +/// Enriches [SentryEvent]s with various kinds of information. /// Uses Darts [Platform](https://api.dart.dev/stable/dart-io/Platform-class.html) /// class to read information. class IoEnricherEventProcessor implements EnricherEventProcessor { - IoEnricherEventProcessor( - this._options, - ); + IoEnricherEventProcessor(this._options); final SentryOptions _options; diff --git a/dart/lib/src/event_processor/enricher/web_enricher_event_processor.dart b/dart/lib/src/event_processor/enricher/web_enricher_event_processor.dart index fe2684d593..f7681eeeaf 100644 --- a/dart/lib/src/event_processor/enricher/web_enricher_event_processor.dart +++ b/dart/lib/src/event_processor/enricher/web_enricher_event_processor.dart @@ -50,9 +50,7 @@ class WebEnricherEventProcessor implements EnricherEventProcessor { final url = request?.url ?? _window.location.toString(); return (request ?? SentryRequest(url: url)) - .copyWith( - headers: header, - ) + .copyWith(headers: header) .sanitized(); } diff --git a/dart/lib/src/hint.dart b/dart/lib/src/hint.dart index aaa614518c..41ea7a0deb 100644 --- a/dart/lib/src/hint.dart +++ b/dart/lib/src/hint.dart @@ -1,4 +1,5 @@ import 'sentry_attachment/sentry_attachment.dart'; +import 'sentry_options.dart'; /// Hints are used in [BeforeSendCallback], [BeforeBreadcrumbCallback] and /// event processors. diff --git a/dart/lib/src/sentry_client.dart b/dart/lib/src/sentry_client.dart index 709bda104f..be866d6719 100644 --- a/dart/lib/src/sentry_client.dart +++ b/dart/lib/src/sentry_client.dart @@ -24,7 +24,7 @@ import 'client_reports/client_report_recorder.dart'; import 'client_reports/discard_reason.dart'; import 'transport/data_category.dart'; -/// Default value for [User.ipAddress]. It gets set when an event does not have +/// Default value for [SentryUser.ipAddress]. It gets set when an event does not have /// a user and IP address. Only applies if [SentryOptions.sendDefaultPii] is set /// to true. const _defaultIpAddress = '{{auto}}'; diff --git a/dart/lib/src/sentry_stack_trace_factory.dart b/dart/lib/src/sentry_stack_trace_factory.dart index fe6b3cc88b..b7f0504bb9 100644 --- a/dart/lib/src/sentry_stack_trace_factory.dart +++ b/dart/lib/src/sentry_stack_trace_factory.dart @@ -5,7 +5,7 @@ import 'noop_origin.dart' if (dart.library.html) 'origin.dart'; import 'protocol.dart'; import 'sentry_options.dart'; -/// converts [StackTrace] to [SentryStackFrames] +/// converts [StackTrace] to [SentryStackFrame]s class SentryStackTraceFactory { final SentryOptions _options; @@ -21,6 +21,10 @@ class SentryStackTraceFactory { 'sentry_logging', 'sentry_dio', 'sentry_file', + 'sentry_hive', + 'sentry_isar', + 'sentry_sqflite', + 'sentry_drift', ]; SentryStackTraceFactory(this._options); @@ -123,16 +127,18 @@ class SentryStackTraceFactory { absPath: abs, function: member, // https://docs.sentry.io/development/sdk-dev/features/#in-app-frames - inApp: isInApp(frame), + inApp: _isInApp(frame), fileName: fileName, package: frame.package, ); - if (frame.line != null && frame.line! >= 0) { + final line = frame.line; + if (line != null && line >= 0) { sentryStackFrame = sentryStackFrame.copyWith(lineNo: frame.line); } - if (frame.column != null && frame.column! >= 0) { + final column = frame.column; + if (column != null && column >= 0) { sentryStackFrame = sentryStackFrame.copyWith(colNo: frame.column); } return sentryStackFrame; @@ -153,11 +159,11 @@ class SentryStackTraceFactory { return frame.uri.pathSegments.last; } - return '${frame.uri}'; + return frame.uri.toString(); } /// whether this frame comes from the app and not from Dart core or 3rd party librairies - bool isInApp(Frame frame) { + bool _isInApp(Frame frame) { final scheme = frame.uri.scheme; if (scheme.isEmpty) { diff --git a/dart/lib/src/sentry_tracer.dart b/dart/lib/src/sentry_tracer.dart index 6012a13bfb..c57912fe46 100644 --- a/dart/lib/src/sentry_tracer.dart +++ b/dart/lib/src/sentry_tracer.dart @@ -49,9 +49,9 @@ class SentryTracer extends ISentrySpan { /// highest timestamp of child spans, trimming the duration of the /// transaction. This is useful to discard extra time in the transaction that /// is not accounted for in child spans, like what happens in the - /// [SentryNavigatorObserver] idle transactions, where we finish the - /// transaction after a given "idle time" and we don't want this "idle time" - /// to be part of the transaction. + /// [SentryNavigatorObserver](https://pub.dev/documentation/sentry_flutter/latest/sentry_flutter/SentryNavigatorObserver-class.html) + /// idle transactions, where we finish the transaction after a given + /// "idle time" and we don't want this "idle time" to be part of the transaction. SentryTracer( SentryTransactionContext transactionContext, this._hub, { diff --git a/flutter/example/lib/main.dart b/flutter/example/lib/main.dart index 55b9072394..6a0c0a5b81 100644 --- a/flutter/example/lib/main.dart +++ b/flutter/example/lib/main.dart @@ -42,52 +42,58 @@ final GlobalKey navigatorKey = GlobalKey(); Future main() async { await setupSentry( - () => runApp( - SentryWidget( - child: DefaultAssetBundle( - bundle: SentryAssetBundle(), - child: const MyApp(), - ), - ), - ), - exampleDsn); + () => runApp( + SentryWidget( + child: DefaultAssetBundle( + bundle: SentryAssetBundle(), + child: const MyApp(), + ), + ), + ), + exampleDsn, + ); } -Future setupSentry(AppRunner appRunner, String dsn, - {bool isIntegrationTest = false, - BeforeSendCallback? beforeSendCallback}) async { - await SentryFlutter.init((options) { - options.dsn = exampleDsn; - options.tracesSampleRate = 1.0; - options.profilesSampleRate = 1.0; - options.reportPackages = false; - options.addInAppInclude('sentry_flutter_example'); - options.considerInAppFramesByDefault = false; - options.attachThreads = true; - options.enableWindowMetricBreadcrumbs = true; - options.addIntegration(LoggingIntegration(minEventLevel: Level.INFO)); - options.sendDefaultPii = true; - options.reportSilentFlutterErrors = true; - options.attachScreenshot = true; - options.screenshotQuality = SentryScreenshotQuality.low; - options.attachViewHierarchy = true; - // We can enable Sentry debug logging during development. This is likely - // going to log too much for your app, but can be useful when figuring out - // configuration issues, e.g. finding out why your events are not uploaded. - options.debug = true; - - options.maxRequestBodySize = MaxRequestBodySize.always; - options.maxResponseBodySize = MaxResponseBodySize.always; - - _isIntegrationTest = isIntegrationTest; - if (_isIntegrationTest) { - options.dist = '1'; - options.environment = 'integration'; - options.beforeSend = beforeSendCallback; - } - }, - // Init your App. - appRunner: appRunner); +Future setupSentry( + AppRunner appRunner, + String dsn, { + bool isIntegrationTest = false, + BeforeSendCallback? beforeSendCallback, +}) async { + await SentryFlutter.init( + (options) { + options.dsn = exampleDsn; + options.tracesSampleRate = 1.0; + options.profilesSampleRate = 1.0; + options.reportPackages = false; + options.addInAppInclude('sentry_flutter_example'); + options.considerInAppFramesByDefault = false; + options.attachThreads = true; + options.enableWindowMetricBreadcrumbs = true; + options.addIntegration(LoggingIntegration(minEventLevel: Level.INFO)); + options.sendDefaultPii = true; + options.reportSilentFlutterErrors = true; + options.attachScreenshot = true; + options.screenshotQuality = SentryScreenshotQuality.low; + options.attachViewHierarchy = true; + // We can enable Sentry debug logging during development. This is likely + // going to log too much for your app, but can be useful when figuring out + // configuration issues, e.g. finding out why your events are not uploaded. + options.debug = true; + + options.maxRequestBodySize = MaxRequestBodySize.always; + options.maxResponseBodySize = MaxResponseBodySize.always; + + _isIntegrationTest = isIntegrationTest; + if (_isIntegrationTest) { + options.dist = '1'; + options.environment = 'integration'; + options.beforeSend = beforeSendCallback; + } + }, + // Init your App. + appRunner: appRunner, + ); } class MyApp extends StatefulWidget { @@ -123,22 +129,23 @@ class TooltipButton extends StatelessWidget { final String buttonTitle; final void Function()? onPressed; - const TooltipButton( - {required this.onPressed, - required this.buttonTitle, - required this.text, - Key? key}) - : super(key: key); + const TooltipButton({ + required this.onPressed, + required this.buttonTitle, + required this.text, + Key? key, + }) : super(key: key); @override Widget build(BuildContext context) { return Tooltip( - message: text, - child: ElevatedButton( - onPressed: onPressed, - key: key, - child: Text(buttonTitle), - )); + message: text, + child: ElevatedButton( + onPressed: onPressed, + key: key, + child: Text(buttonTitle), + ), + ); } } @@ -188,8 +195,9 @@ class MainScaffold extends StatelessWidget { const Padding( padding: EdgeInsets.all(15), //apply padding to all four sides child: Center( - child: Text( - 'Long press a button to see more information. (hover on web)')), + child: Text( + 'Long press a button to see more information. (hover on web)'), + ), ), TooltipButton( onPressed: () => navigateToAutoCloseScreen(context), @@ -301,20 +309,23 @@ class MainScaffold extends StatelessWidget { TooltipButton( onPressed: () { // modeled after a real exception - FlutterError.onError?.call(FlutterErrorDetails( - exception: Exception('A really bad exception'), - silent: false, - context: DiagnosticsNode.message('while handling a gesture'), - library: 'gesture', - informationCollector: () => [ - DiagnosticsNode.message( - 'Handler: "onTap" Recognizer: TapGestureRecognizer'), - DiagnosticsNode.message( - 'Handler: "onTap" Recognizer: TapGestureRecognizer'), - DiagnosticsNode.message( - 'Handler: "onTap" Recognizer: TapGestureRecognizer'), - ], - )); + FlutterError.onError?.call( + FlutterErrorDetails( + exception: Exception('A really bad exception'), + silent: false, + context: + DiagnosticsNode.message('while handling a gesture'), + library: 'gesture', + informationCollector: () => [ + DiagnosticsNode.message( + 'Handler: "onTap" Recognizer: TapGestureRecognizer'), + DiagnosticsNode.message( + 'Handler: "onTap" Recognizer: TapGestureRecognizer'), + DiagnosticsNode.message( + 'Handler: "onTap" Recognizer: TapGestureRecognizer'), + ], + ), + ); }, text: 'Creates a FlutterError and passes it to FlutterError.onError callback. This demonstrates how our flutter error integration catches unhandled exceptions.', @@ -449,27 +460,28 @@ class MainScaffold extends StatelessWidget { ), TooltipButton( onPressed: () { - feedback.BetterFeedback.of(context) - .show((feedback.UserFeedback feedback) { - Sentry.captureMessage( - feedback.text, - withScope: (scope) { - final entries = feedback.extra?.entries; - if (entries != null) { - for (final extra in entries) { - scope.setExtra(extra.key, extra.value); + feedback.BetterFeedback.of(context).show( + (feedback.UserFeedback feedback) { + Sentry.captureMessage( + feedback.text, + withScope: (scope) { + final entries = feedback.extra?.entries; + if (entries != null) { + for (final extra in entries) { + scope.setExtra(extra.key, extra.value); + } } - } - scope.addAttachment( - SentryAttachment.fromUint8List( - feedback.screenshot, - 'feedback.png', - contentType: 'image/png', - ), - ); - }, - ); - }); + scope.addAttachment( + SentryAttachment.fromUint8List( + feedback.screenshot, + 'feedback.png', + contentType: 'image/png', + ), + ); + }, + ); + }, + ); }, text: 'Sends the capture message with an image attachment to Sentry.', @@ -754,18 +766,20 @@ class _IntegrationTestWidgetState extends State { @override Widget build(BuildContext context) { - return Column(children: [ - Text( - _output, - key: const Key('output'), - ), - _isLoading - ? const CircularProgressIndicator() - : ElevatedButton( - onPressed: () async => await _captureException(), - child: const Text('captureException'), - ) - ]); + return Column( + children: [ + Text( + _output, + key: const Key('output'), + ), + _isLoading + ? const CircularProgressIndicator() + : ElevatedButton( + onPressed: () async => await _captureException(), + child: const Text('captureException'), + ) + ], + ); } Future _captureException() async { diff --git a/flutter/lib/src/integrations/screenshot_integration.dart b/flutter/lib/src/integrations/screenshot_integration.dart index d8d1adbc34..10cf60228a 100644 --- a/flutter/lib/src/integrations/screenshot_integration.dart +++ b/flutter/lib/src/integrations/screenshot_integration.dart @@ -2,7 +2,8 @@ import 'package:sentry/sentry.dart'; import '../event_processor/screenshot_event_processor.dart'; import '../sentry_flutter_options.dart'; -/// Adds [ScreenshotEventProcessor] to options event processors if [attachScreenshot] is true +/// Adds [ScreenshotEventProcessor] to options event processors if +/// [SentryFlutterOptions.attachScreenshot] is true class ScreenshotIntegration implements Integration { SentryFlutterOptions? _options; ScreenshotEventProcessor? _screenshotEventProcessor; diff --git a/flutter/lib/src/navigation/sentry_navigator_observer.dart b/flutter/lib/src/navigation/sentry_navigator_observer.dart index b24f4f0c7b..30beaa75bc 100644 --- a/flutter/lib/src/navigation/sentry_navigator_observer.dart +++ b/flutter/lib/src/navigation/sentry_navigator_observer.dart @@ -44,21 +44,22 @@ typedef AdditionalInfoExtractor = Map? Function( /// ) /// ``` /// -/// The option [enableAutoTransactions] is enabled by default. For every new -/// route a transaction is started. It's automatically finished after -/// [autoFinishAfter] duration or when all child spans are finished, -/// if those happen to take longer. The transaction will be set to [Scope.span] -/// if the latter is empty. -/// -/// Enabling the [setRouteNameAsTransaction] option overrides the current -/// [Scope.transaction] which will also override the name of the current -/// [Scope.span]. So be careful when this is used together with performance -/// monitoring. +/// See the constructor docs for the argument documentation. /// /// See also: /// - [RouteObserver](https://api.flutter.dev/flutter/widgets/RouteObserver-class.html) /// - [Navigating with arguments](https://flutter.dev/docs/cookbook/navigation/navigate-with-arguments) class SentryNavigatorObserver extends RouteObserver> { + /// The option [enableAutoTransactions] is enabled by default. + /// For every new route a transaction is started. It's automatically finished + /// after [autoFinishAfter] duration or when all child spans are + /// finished, if those happen to take longer. + /// The transaction will be set to [Scope.span] if the latter is empty. + /// + /// Enabling the [setRouteNameAsTransaction] option overrides the + /// current [Scope.transaction] which will also override the name of the current + /// [Scope.span]. So be careful when this is used together with performance + /// monitoring. SentryNavigatorObserver({ Hub? hub, bool enableAutoTransactions = true, diff --git a/flutter/lib/src/sentry_flutter_options.dart b/flutter/lib/src/sentry_flutter_options.dart index ee722f8e9e..ceda7ef0cc 100644 --- a/flutter/lib/src/sentry_flutter_options.dart +++ b/flutter/lib/src/sentry_flutter_options.dart @@ -8,6 +8,9 @@ import 'binding_wrapper.dart'; import 'renderer/renderer.dart'; import 'screenshot/sentry_screenshot_quality.dart'; import 'event_processor/screenshot_event_processor.dart'; +import 'screenshot/sentry_screenshot_widget.dart'; +import 'sentry_flutter.dart'; +import 'user_interaction/sentry_user_interaction_widget.dart'; /// This class adds options which are only available in a Flutter environment. /// Note that some of these options require native Sentry integration, which is From e964e2b8203c29a4ff03e257ff521f561b4f186c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20Andra=C5=A1ec?= Date: Mon, 4 Mar 2024 10:28:18 +0000 Subject: [PATCH 090/237] Use `recordHttpBreadcrumbs` to set iOS `enableNetworkBreadcrumbs` (#1884) --- CHANGELOG.md | 6 ++++++ dart/lib/src/sentry_options.dart | 6 ++++-- flutter/example/ios/RunnerTests/SentryFlutterTests.swift | 2 ++ flutter/ios/Classes/SentryFlutter.swift | 3 +++ flutter/lib/src/integrations/native_sdk_integration.dart | 1 + .../test/integrations/init_native_sdk_integration_test.dart | 3 +++ 6 files changed, 19 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 52f902b373..8377034385 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## Unreleased + +### Features + +- Use `recordHttpBreadcrumbs` to set iOS `enableNetworkBreadcrumbs` ([#1884](https://github.com/getsentry/sentry-dart/pull/1884)) + ## 7.16.1 ### Fixes diff --git a/dart/lib/src/sentry_options.dart b/dart/lib/src/sentry_options.dart index 918a5d5758..5fa8b793f0 100644 --- a/dart/lib/src/sentry_options.dart +++ b/dart/lib/src/sentry_options.dart @@ -248,11 +248,13 @@ class SentryOptions { /// - In an browser environment this can be requests which fail because of CORS. /// - In an mobile or desktop application this can be requests which failed /// because the connection was interrupted. - /// Use with [SentryHttpClient] or `sentry_dio` integration for this to work + /// Use with [SentryHttpClient] or `sentry_dio` integration for this to work, + /// or iOS native where it sets the value to `enableCaptureFailedRequests`. bool captureFailedRequests = true; /// Whether to records requests as breadcrumbs. This is on by default. - /// It only has an effect when the SentryHttpClient or dio integration is in use + /// It only has an effect when the SentryHttpClient or dio integration is in + /// use, or iOS native where it sets the value to `enableNetworkBreadcrumbs`. bool recordHttpBreadcrumbs = true; /// Whether [SentryEvent] deduplication is enabled. diff --git a/flutter/example/ios/RunnerTests/SentryFlutterTests.swift b/flutter/example/ios/RunnerTests/SentryFlutterTests.swift index 057b2363b5..9dbb70ba51 100644 --- a/flutter/example/ios/RunnerTests/SentryFlutterTests.swift +++ b/flutter/example/ios/RunnerTests/SentryFlutterTests.swift @@ -41,6 +41,7 @@ final class SentryFlutterTests: XCTestCase { "enableWatchdogTerminationTracking": false, "sendClientReports": false, "maxAttachmentSize": NSNumber(value: 9004), + "recordHttpBreadcrumbs": false, "captureFailedRequests": false, "enableAppHangTracking": false, "appHangTimeoutIntervalMillis": NSNumber(value: 10000) @@ -65,6 +66,7 @@ final class SentryFlutterTests: XCTestCase { XCTAssertEqual(false, fixture.options.enableWatchdogTerminationTracking) XCTAssertEqual(false, fixture.options.sendClientReports) XCTAssertEqual(9004, fixture.options.maxAttachmentSize) + XCTAssertEqual(false, fixture.options.enableNetworkBreadcrumbs) XCTAssertEqual(false, fixture.options.enableCaptureFailedRequests) XCTAssertEqual(false, fixture.options.enableAppHangTracking) XCTAssertEqual(10, fixture.options.appHangTimeoutInterval) diff --git a/flutter/ios/Classes/SentryFlutter.swift b/flutter/ios/Classes/SentryFlutter.swift index f3815455fe..b26bcfc30d 100644 --- a/flutter/ios/Classes/SentryFlutter.swift +++ b/flutter/ios/Classes/SentryFlutter.swift @@ -58,6 +58,9 @@ public final class SentryFlutter { if let maxAttachmentSize = data["maxAttachmentSize"] as? NSNumber { options.maxAttachmentSize = maxAttachmentSize.uintValue } + if let recordHttpBreadcrumbs = data["recordHttpBreadcrumbs"] as? Bool { + options.enableNetworkBreadcrumbs = recordHttpBreadcrumbs + } if let captureFailedRequests = data["captureFailedRequests"] as? Bool { options.enableCaptureFailedRequests = captureFailedRequests } diff --git a/flutter/lib/src/integrations/native_sdk_integration.dart b/flutter/lib/src/integrations/native_sdk_integration.dart index 9c4a98379e..715a821cf9 100644 --- a/flutter/lib/src/integrations/native_sdk_integration.dart +++ b/flutter/lib/src/integrations/native_sdk_integration.dart @@ -47,6 +47,7 @@ class NativeSdkIntegration implements Integration { 'sendClientReports': options.sendClientReports, 'proguardUuid': options.proguardUuid, 'maxAttachmentSize': options.maxAttachmentSize, + 'recordHttpBreadcrumbs': options.recordHttpBreadcrumbs, 'captureFailedRequests': options.captureFailedRequests, 'enableAppHangTracking': options.enableAppHangTracking, 'connectionTimeoutMillis': options.connectionTimeout.inMilliseconds, diff --git a/flutter/test/integrations/init_native_sdk_integration_test.dart b/flutter/test/integrations/init_native_sdk_integration_test.dart index 4ed6a3d3b9..b41c2d51cf 100644 --- a/flutter/test/integrations/init_native_sdk_integration_test.dart +++ b/flutter/test/integrations/init_native_sdk_integration_test.dart @@ -58,6 +58,7 @@ void main() { 'sendClientReports': true, 'proguardUuid': null, 'maxAttachmentSize': 20 * 1024 * 1024, + 'recordHttpBreadcrumbs': true, 'captureFailedRequests': true, 'enableAppHangTracking': true, 'connectionTimeoutMillis': 5000, @@ -98,6 +99,7 @@ void main() { ..enableNdkScopeSync = true ..proguardUuid = fakeProguardUuid ..maxAttachmentSize = 10 + ..recordHttpBreadcrumbs = false ..captureFailedRequests = false ..enableAppHangTracking = false ..connectionTimeout = Duration(milliseconds: 9001) @@ -141,6 +143,7 @@ void main() { 'sendClientReports': false, 'proguardUuid': fakeProguardUuid, 'maxAttachmentSize': 10, + 'recordHttpBreadcrumbs': false, 'captureFailedRequests': false, 'enableAppHangTracking': false, 'connectionTimeoutMillis': 9001, From 014c3ea4cf506cccc5cfd0eceb6e9b1c1b5fdce9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 4 Mar 2024 11:54:04 +0100 Subject: [PATCH 091/237] chore: update metrics/flutter.properties to 3.19.2 (#1899) Co-authored-by: GitHub --- metrics/flutter.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/metrics/flutter.properties b/metrics/flutter.properties index 5b903acb68..f9b46d7c2a 100644 --- a/metrics/flutter.properties +++ b/metrics/flutter.properties @@ -1,2 +1,2 @@ -version = 3.16.9 +version = 3.19.2 repo = https://github.com/flutter/flutter From 5e7abc5157b9e43973db9bc8e2a883d69d3fe136 Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Mon, 4 Mar 2024 14:52:44 +0100 Subject: [PATCH 092/237] refactor: fetch app start in integration instead of event processor (#1905) * Change app start integration in a way that works with ttid as well * Formatting * Update * add visibleForTesting * Update * update * Add app start info test * Remove set app start info null * Review improvements * run on arm mac * Fix integration test --- .github/workflows/flutter_test.yml | 2 +- CHANGELOG.md | 4 + .../integration_test/integration_test.dart | 4 + .../native_app_start_event_processor.dart | 50 ++------ flutter/lib/src/frame_callback_handler.dart | 15 +++ .../native_app_start_integration.dart | 120 +++++++++++++++--- flutter/lib/src/native/sentry_native.dart | 3 + flutter/lib/src/sentry_flutter.dart | 11 +- flutter/test/fake_frame_callback_handler.dart | 19 +++ .../native_app_start_integration_test.dart | 23 ++-- flutter/test/mocks.dart | 3 + 11 files changed, 181 insertions(+), 73 deletions(-) create mode 100644 flutter/lib/src/frame_callback_handler.dart create mode 100644 flutter/test/fake_frame_callback_handler.dart diff --git a/.github/workflows/flutter_test.yml b/.github/workflows/flutter_test.yml index 637b4d1a41..4d60fabca5 100644 --- a/.github/workflows/flutter_test.yml +++ b/.github/workflows/flutter_test.yml @@ -111,7 +111,7 @@ jobs: cocoa: name: "${{ matrix.target }} | ${{ matrix.sdk }}" - runs-on: macos-13 + runs-on: macos-latest-xlarge timeout-minutes: 30 defaults: run: diff --git a/CHANGELOG.md b/CHANGELOG.md index 8377034385..a7f259f8b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ - Use `recordHttpBreadcrumbs` to set iOS `enableNetworkBreadcrumbs` ([#1884](https://github.com/getsentry/sentry-dart/pull/1884)) +### Improvements + +- App start is now fetched within integration instead of event processor ([#1905](https://github.com/getsentry/sentry-dart/pull/1905)) + ## 7.16.1 ### Fixes diff --git a/flutter/example/integration_test/integration_test.dart b/flutter/example/integration_test/integration_test.dart index c4c71edb41..f292d04cfc 100644 --- a/flutter/example/integration_test/integration_test.dart +++ b/flutter/example/integration_test/integration_test.dart @@ -1,4 +1,5 @@ // ignore_for_file: avoid_print +// ignore_for_file: invalid_use_of_internal_member import 'dart:async'; import 'dart:convert'; @@ -8,6 +9,7 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:sentry_flutter_example/main.dart'; import 'package:http/http.dart'; +import 'package:sentry_flutter/src/integrations/native_app_start_integration.dart'; void main() { // const org = 'sentry-sdks'; @@ -24,6 +26,8 @@ void main() { // Using fake DSN for testing purposes. Future setupSentryAndApp(WidgetTester tester, {String? dsn, BeforeSendCallback? beforeSendCallback}) async { + NativeAppStartIntegration.isIntegrationTest = true; + await setupSentry( () async { await tester.pumpWidget(SentryScreenshotWidget( diff --git a/flutter/lib/src/event_processor/native_app_start_event_processor.dart b/flutter/lib/src/event_processor/native_app_start_event_processor.dart index a7abe62e05..fd1a5ec169 100644 --- a/flutter/lib/src/event_processor/native_app_start_event_processor.dart +++ b/flutter/lib/src/event_processor/native_app_start_event_processor.dart @@ -2,57 +2,29 @@ import 'dart:async'; import 'package:sentry/sentry.dart'; +import '../integrations/integrations.dart'; import '../native/sentry_native.dart'; /// EventProcessor that enriches [SentryTransaction] objects with app start /// measurement. class NativeAppStartEventProcessor implements EventProcessor { - /// We filter out App starts more than 60s - static const _maxAppStartMillis = 60000; - - NativeAppStartEventProcessor( - this._native, - ); - final SentryNative _native; + NativeAppStartEventProcessor(this._native); + @override Future apply(SentryEvent event, {Hint? hint}) async { - final appStartEnd = _native.appStartEnd; + if (_native.didAddAppStartMeasurement || event is! SentryTransaction) { + return event; + } + + final appStartInfo = await NativeAppStartIntegration.getAppStartInfo(); + final measurement = appStartInfo?.toMeasurement(); - if (appStartEnd != null && - event is SentryTransaction && - !_native.didFetchAppStart) { - final nativeAppStart = await _native.fetchNativeAppStart(); - if (nativeAppStart == null) { - return event; - } - final measurement = nativeAppStart.toMeasurement(appStartEnd); - // We filter out app start more than 60s. - // This could be due to many different reasons. - // If you do the manual init and init the SDK too late and it does not - // compute the app start end in the very first Screen. - // If the process starts but the App isn't in the foreground. - // If the system forked the process earlier to accelerate the app start. - // And some unknown reasons that could not be reproduced. - // We've seen app starts with hours, days and even months. - if (measurement.value >= _maxAppStartMillis) { - return event; - } + if (measurement != null) { event.measurements[measurement.name] = measurement; + _native.didAddAppStartMeasurement = true; } return event; } } - -extension NativeAppStartMeasurement on NativeAppStart { - SentryMeasurement toMeasurement(DateTime appStartEnd) { - final appStartDateTime = - DateTime.fromMillisecondsSinceEpoch(appStartTime.toInt()); - final duration = appStartEnd.difference(appStartDateTime); - - return isColdStart - ? SentryMeasurement.coldAppStart(duration) - : SentryMeasurement.warmAppStart(duration); - } -} diff --git a/flutter/lib/src/frame_callback_handler.dart b/flutter/lib/src/frame_callback_handler.dart new file mode 100644 index 0000000000..71a8f928b1 --- /dev/null +++ b/flutter/lib/src/frame_callback_handler.dart @@ -0,0 +1,15 @@ +import 'package:flutter/scheduler.dart'; + +abstract class FrameCallbackHandler { + void addPostFrameCallback(FrameCallback callback); +} + +class DefaultFrameCallbackHandler implements FrameCallbackHandler { + @override + void addPostFrameCallback(FrameCallback callback) { + try { + /// Flutter >= 2.12 throws if SchedulerBinding.instance isn't initialized. + SchedulerBinding.instance.addPostFrameCallback(callback); + } catch (_) {} + } +} diff --git a/flutter/lib/src/integrations/native_app_start_integration.dart b/flutter/lib/src/integrations/native_app_start_integration.dart index 47bf79dff4..91d0c01940 100644 --- a/flutter/lib/src/integrations/native_app_start_integration.dart +++ b/flutter/lib/src/integrations/native_app_start_integration.dart @@ -1,31 +1,103 @@ -import 'package:flutter/scheduler.dart'; -import 'package:sentry/sentry.dart'; +import 'dart:async'; -import '../sentry_flutter_options.dart'; +import 'package:meta/meta.dart'; + +import '../../sentry_flutter.dart'; +import '../frame_callback_handler.dart'; import '../native/sentry_native.dart'; import '../event_processor/native_app_start_event_processor.dart'; /// Integration which handles communication with native frameworks in order to /// enrich [SentryTransaction] objects with app start data for mobile vitals. class NativeAppStartIntegration extends Integration { - NativeAppStartIntegration(this._native, this._schedulerBindingProvider); + NativeAppStartIntegration(this._native, this._frameCallbackHandler); final SentryNative _native; - final SchedulerBindingProvider _schedulerBindingProvider; + final FrameCallbackHandler _frameCallbackHandler; + + /// We filter out App starts more than 60s + static const _maxAppStartMillis = 60000; + + static Completer _appStartCompleter = + Completer(); + static AppStartInfo? _appStartInfo; + + @internal + static bool isIntegrationTest = false; + + @internal + static void setAppStartInfo(AppStartInfo? appStartInfo) { + _appStartInfo = appStartInfo; + if (_appStartCompleter.isCompleted) { + _appStartCompleter = Completer(); + } + _appStartCompleter.complete(appStartInfo); + } + + @internal + static Future getAppStartInfo() { + if (_appStartInfo != null) { + return Future.value(_appStartInfo); + } + return _appStartCompleter.future; + } + + @visibleForTesting + static void clearAppStartInfo() { + _appStartInfo = null; + _appStartCompleter = Completer(); + } @override void call(Hub hub, SentryFlutterOptions options) { + if (isIntegrationTest) { + final appStartInfo = AppStartInfo(AppStartType.cold, + start: DateTime.now(), + end: DateTime.now().add(const Duration(milliseconds: 100))); + setAppStartInfo(appStartInfo); + return; + } + if (options.autoAppStart) { - final schedulerBinding = _schedulerBindingProvider(); - if (schedulerBinding == null) { - options.logger(SentryLevel.debug, - 'Scheduler binding is null. Can\'t auto detect app start time.'); - } else { - schedulerBinding.addPostFrameCallback((timeStamp) { - // ignore: invalid_use_of_internal_member - _native.appStartEnd = options.clock(); - }); - } + _frameCallbackHandler.addPostFrameCallback((timeStamp) async { + if (_native.didFetchAppStart) { + return; + } + + // We only assign the current time if it's not already set - this is useful in tests + // ignore: invalid_use_of_internal_member + _native.appStartEnd ??= options.clock(); + final appStartEnd = _native.appStartEnd; + final nativeAppStart = await _native.fetchNativeAppStart(); + + if (nativeAppStart == null || appStartEnd == null) { + return; + } + + final appStartDateTime = DateTime.fromMillisecondsSinceEpoch( + nativeAppStart.appStartTime.toInt()); + final duration = appStartEnd.difference(appStartDateTime); + + // We filter out app start more than 60s. + // This could be due to many different reasons. + // If you do the manual init and init the SDK too late and it does not + // compute the app start end in the very first Screen. + // If the process starts but the App isn't in the foreground. + // If the system forked the process earlier to accelerate the app start. + // And some unknown reasons that could not be reproduced. + // We've seen app starts with hours, days and even months. + if (duration.inMilliseconds > _maxAppStartMillis) { + setAppStartInfo(null); + return; + } + + final appStartInfo = AppStartInfo( + nativeAppStart.isColdStart ? AppStartType.cold : AppStartType.warm, + start: DateTime.fromMillisecondsSinceEpoch( + nativeAppStart.appStartTime.toInt()), + end: appStartEnd); + setAppStartInfo(appStartInfo); + }); } options.addEventProcessor(NativeAppStartEventProcessor(_native)); @@ -34,5 +106,19 @@ class NativeAppStartIntegration extends Integration { } } -/// Used to provide scheduler binding at call time. -typedef SchedulerBindingProvider = SchedulerBinding? Function(); +enum AppStartType { cold, warm } + +class AppStartInfo { + AppStartInfo(this.type, {required this.start, required this.end}); + + final AppStartType type; + final DateTime start; + final DateTime end; + + SentryMeasurement toMeasurement() { + final duration = end.difference(start); + return type == AppStartType.cold + ? SentryMeasurement.coldAppStart(duration) + : SentryMeasurement.warmAppStart(duration); + } +} diff --git a/flutter/lib/src/native/sentry_native.dart b/flutter/lib/src/native/sentry_native.dart index b8d2206a8d..a7973f8a12 100644 --- a/flutter/lib/src/native/sentry_native.dart +++ b/flutter/lib/src/native/sentry_native.dart @@ -27,6 +27,9 @@ class SentryNative { /// Flag indicating if app start was already fetched. bool get didFetchAppStart => _didFetchAppStart; + /// Flag indicating if app start measurement was added to the first transaction. + bool didAddAppStartMeasurement = false; + /// Fetch [NativeAppStart] from native channels. Can only be called once. Future fetchNativeAppStart() async { _didFetchAppStart = true; diff --git a/flutter/lib/src/sentry_flutter.dart b/flutter/lib/src/sentry_flutter.dart index 62a9043bc9..9822b49665 100644 --- a/flutter/lib/src/sentry_flutter.dart +++ b/flutter/lib/src/sentry_flutter.dart @@ -1,7 +1,6 @@ import 'dart:async'; import 'dart:ui'; -import 'package:flutter/scheduler.dart'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; import 'package:meta/meta.dart'; @@ -9,6 +8,7 @@ import '../sentry_flutter.dart'; import 'event_processor/android_platform_exception_event_processor.dart'; import 'event_processor/flutter_exception_event_processor.dart'; import 'event_processor/platform_exception_event_processor.dart'; +import 'frame_callback_handler.dart'; import 'integrations/connectivity/connectivity_integration.dart'; import 'integrations/screenshot_integration.dart'; import 'native/factory.dart'; @@ -189,13 +189,7 @@ mixin SentryFlutter { if (_native != null) { integrations.add(NativeAppStartIntegration( _native!, - () { - try { - /// Flutter >= 2.12 throws if SchedulerBinding.instance isn't initialized. - return SchedulerBinding.instance; - } catch (_) {} - return null; - }, + DefaultFrameCallbackHandler(), )); } return integrations; @@ -231,6 +225,7 @@ mixin SentryFlutter { @internal static SentryNative? get native => _native; + @internal static set native(SentryNative? value) => _native = value; static SentryNative? _native; diff --git a/flutter/test/fake_frame_callback_handler.dart b/flutter/test/fake_frame_callback_handler.dart new file mode 100644 index 0000000000..103045d0e2 --- /dev/null +++ b/flutter/test/fake_frame_callback_handler.dart @@ -0,0 +1,19 @@ +import 'package:flutter/scheduler.dart'; +import 'package:sentry_flutter/src/frame_callback_handler.dart'; + +class FakeFrameCallbackHandler implements FrameCallbackHandler { + FrameCallback? storedCallback; + + final Duration _finishAfterDuration; + + FakeFrameCallbackHandler( + {Duration finishAfterDuration = const Duration(milliseconds: 500)}) + : _finishAfterDuration = finishAfterDuration; + + @override + void addPostFrameCallback(FrameCallback callback) async { + // ignore: inference_failure_on_instance_creation + await Future.delayed(_finishAfterDuration); + callback(Duration.zero); + } +} diff --git a/flutter/test/integrations/native_app_start_integration_test.dart b/flutter/test/integrations/native_app_start_integration_test.dart index d4b8deaaf5..135d90f34b 100644 --- a/flutter/test/integrations/native_app_start_integration_test.dart +++ b/flutter/test/integrations/native_app_start_integration_test.dart @@ -1,5 +1,4 @@ @TestOn('vm') - import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/mockito.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; @@ -7,6 +6,7 @@ import 'package:sentry_flutter/src/integrations/native_app_start_integration.dar import 'package:sentry_flutter/src/native/sentry_native.dart'; import 'package:sentry/src/sentry_tracer.dart'; +import '../fake_frame_callback_handler.dart'; import '../mocks.dart'; import '../mocks.mocks.dart'; @@ -18,10 +18,10 @@ void main() { TestWidgetsFlutterBinding.ensureInitialized(); fixture = Fixture(); + NativeAppStartIntegration.clearAppStartInfo(); }); test('native app start measurement added to first transaction', () async { - fixture.options.autoAppStart = false; fixture.native.appStartEnd = DateTime.fromMillisecondsSinceEpoch(10); fixture.binding.nativeAppStart = NativeAppStart(0, true); @@ -40,7 +40,6 @@ void main() { test('native app start measurement not added to following transactions', () async { - fixture.options.autoAppStart = false; fixture.native.appStartEnd = DateTime.fromMillisecondsSinceEpoch(10); fixture.binding.nativeAppStart = NativeAppStart(0, true); @@ -58,7 +57,6 @@ void main() { }); test('measurements appended', () async { - fixture.options.autoAppStart = false; fixture.native.appStartEnd = DateTime.fromMillisecondsSinceEpoch(10); fixture.binding.nativeAppStart = NativeAppStart(0, true); final measurement = SentryMeasurement.warmAppStart(Duration(seconds: 1)); @@ -79,7 +77,6 @@ void main() { }); test('native app start measurement not added if more than 60s', () async { - fixture.options.autoAppStart = false; fixture.native.appStartEnd = DateTime.fromMillisecondsSinceEpoch(60001); fixture.binding.nativeAppStart = NativeAppStart(0, true); @@ -93,6 +90,18 @@ void main() { expect(enriched.measurements.isEmpty, true); }); + + test('native app start integration is called and sets app start info', + () async { + fixture.native.appStartEnd = DateTime.fromMillisecondsSinceEpoch(10); + fixture.binding.nativeAppStart = NativeAppStart(0, true); + + fixture.getNativeAppStartIntegration().call(fixture.hub, fixture.options); + + final appStartInfo = await NativeAppStartIntegration.getAppStartInfo(); + expect(appStartInfo?.start, DateTime.fromMillisecondsSinceEpoch(0)); + expect(appStartInfo?.end, DateTime.fromMillisecondsSinceEpoch(10)); + }); }); } @@ -110,9 +119,7 @@ class Fixture { NativeAppStartIntegration getNativeAppStartIntegration() { return NativeAppStartIntegration( native, - () { - return TestWidgetsFlutterBinding.ensureInitialized(); - }, + FakeFrameCallbackHandler(), ); } diff --git a/flutter/test/mocks.dart b/flutter/test/mocks.dart index b2e01788c1..41c3269393 100644 --- a/flutter/test/mocks.dart +++ b/flutter/test/mocks.dart @@ -171,6 +171,9 @@ class TestMockSentryNative implements SentryNative { @override bool get didFetchAppStart => _didFetchAppStart; + @override + bool didAddAppStartMeasurement = false; + Breadcrumb? breadcrumb; var numberOfAddBreadcrumbCalls = 0; var numberOfBeginNativeFramesCollectionCalls = 0; From f351d3d131466491ad8071461c2bcb754b51d4e9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Mar 2024 14:55:06 +0100 Subject: [PATCH 093/237] build(deps): bump codecov/codecov-action from 4.0.1 to 4.0.2 (#1890) Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 4.0.1 to 4.0.2. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/e0b68c6749509c5f83f984dd99a76a1c1a231044...0cfda1dd0a4ad9efc75517f399d859cd1ea4ced1) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor --- .github/workflows/dart.yml | 2 +- .github/workflows/dio.yml | 2 +- .github/workflows/drift.yml | 2 +- .github/workflows/file.yml | 2 +- .github/workflows/flutter.yml | 2 +- .github/workflows/hive.yml | 2 +- .github/workflows/isar.yml | 2 +- .github/workflows/logging.yml | 2 +- .github/workflows/sqflite.yml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml index 776d63826c..dcd8212409 100644 --- a/.github/workflows/dart.yml +++ b/.github/workflows/dart.yml @@ -68,7 +68,7 @@ jobs: dart pub get webdev build - - uses: codecov/codecov-action@e0b68c6749509c5f83f984dd99a76a1c1a231044 # pin@v3 + - uses: codecov/codecov-action@0cfda1dd0a4ad9efc75517f399d859cd1ea4ced1 # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: name: sentry diff --git a/.github/workflows/dio.yml b/.github/workflows/dio.yml index 29f750381d..2503fe6e21 100644 --- a/.github/workflows/dio.yml +++ b/.github/workflows/dio.yml @@ -52,7 +52,7 @@ jobs: dart test -p vm --coverage=coverage --test-randomize-ordering-seed=random --chain-stack-traces dart pub run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.dart_tool/package_config.json --report-on=lib - - uses: codecov/codecov-action@e0b68c6749509c5f83f984dd99a76a1c1a231044 # pin@v3 + - uses: codecov/codecov-action@0cfda1dd0a4ad9efc75517f399d859cd1ea4ced1 # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: name: sentry_dio diff --git a/.github/workflows/drift.yml b/.github/workflows/drift.yml index b3c8b1dc91..9d8fa4a45c 100644 --- a/.github/workflows/drift.yml +++ b/.github/workflows/drift.yml @@ -93,7 +93,7 @@ jobs: cd drift flutter test --coverage --test-randomize-ordering-seed=random - - uses: codecov/codecov-action@e0b68c6749509c5f83f984dd99a76a1c1a231044 # pin@v3 + - uses: codecov/codecov-action@0cfda1dd0a4ad9efc75517f399d859cd1ea4ced1 # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' with: name: sentry_drift diff --git a/.github/workflows/file.yml b/.github/workflows/file.yml index 41c4623324..45f0c91588 100644 --- a/.github/workflows/file.yml +++ b/.github/workflows/file.yml @@ -52,7 +52,7 @@ jobs: dart test -p vm --coverage=coverage --test-randomize-ordering-seed=random --chain-stack-traces dart pub run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.dart_tool/package_config.json --report-on=lib - - uses: codecov/codecov-action@e0b68c6749509c5f83f984dd99a76a1c1a231044 # pin@v3 + - uses: codecov/codecov-action@0cfda1dd0a4ad9efc75517f399d859cd1ea4ced1 # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: name: sentry_file diff --git a/.github/workflows/flutter.yml b/.github/workflows/flutter.yml index d55a9207f5..77bcdc0e08 100644 --- a/.github/workflows/flutter.yml +++ b/.github/workflows/flutter.yml @@ -112,7 +112,7 @@ jobs: flutter test --coverage --test-randomize-ordering-seed=random dart run remove_from_coverage -f coverage/lcov.info -r 'binding.dart' - - uses: codecov/codecov-action@e0b68c6749509c5f83f984dd99a76a1c1a231044 # pin@v3 + - uses: codecov/codecov-action@0cfda1dd0a4ad9efc75517f399d859cd1ea4ced1 # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' with: name: sentry_flutter diff --git a/.github/workflows/hive.yml b/.github/workflows/hive.yml index f13e8d1522..add3e9e54f 100644 --- a/.github/workflows/hive.yml +++ b/.github/workflows/hive.yml @@ -51,7 +51,7 @@ jobs: dart test -p vm --coverage=coverage --test-randomize-ordering-seed=random --chain-stack-traces dart pub run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.dart_tool/package_config.json --report-on=lib - - uses: codecov/codecov-action@e0b68c6749509c5f83f984dd99a76a1c1a231044 # pin@v3 + - uses: codecov/codecov-action@0cfda1dd0a4ad9efc75517f399d859cd1ea4ced1 # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: name: sentry_hive diff --git a/.github/workflows/isar.yml b/.github/workflows/isar.yml index a1e67c3bc8..69f79d3006 100644 --- a/.github/workflows/isar.yml +++ b/.github/workflows/isar.yml @@ -93,7 +93,7 @@ jobs: cd isar flutter test -j 1 --coverage --test-randomize-ordering-seed=random - - uses: codecov/codecov-action@e0b68c6749509c5f83f984dd99a76a1c1a231044 # pin@v3 + - uses: codecov/codecov-action@0cfda1dd0a4ad9efc75517f399d859cd1ea4ced1 # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' with: name: sentry_isar diff --git a/.github/workflows/logging.yml b/.github/workflows/logging.yml index 6eafdc199a..755ff60043 100644 --- a/.github/workflows/logging.yml +++ b/.github/workflows/logging.yml @@ -52,7 +52,7 @@ jobs: dart test -p vm --coverage=coverage --test-randomize-ordering-seed=random --chain-stack-traces dart pub run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.dart_tool/package_config.json --report-on=lib - - uses: codecov/codecov-action@e0b68c6749509c5f83f984dd99a76a1c1a231044 # pin@v3 + - uses: codecov/codecov-action@0cfda1dd0a4ad9efc75517f399d859cd1ea4ced1 # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: name: sentry_logging diff --git a/.github/workflows/sqflite.yml b/.github/workflows/sqflite.yml index 9d3caa78bd..bbbdf7e12a 100644 --- a/.github/workflows/sqflite.yml +++ b/.github/workflows/sqflite.yml @@ -93,7 +93,7 @@ jobs: cd sqflite flutter test --coverage --test-randomize-ordering-seed=random - - uses: codecov/codecov-action@e0b68c6749509c5f83f984dd99a76a1c1a231044 # pin@v3 + - uses: codecov/codecov-action@0cfda1dd0a4ad9efc75517f399d859cd1ea4ced1 # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' with: name: sentry_sqflite From 8776cdf4688ec58628a4b68a24f5d8840f2b523f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 4 Mar 2024 15:38:10 +0100 Subject: [PATCH 094/237] chore(deps): update Cocoa SDK to v8.21.0 (#1909) * chore: update flutter/scripts/update-cocoa.sh to 8.21.0 * Test auto commit * Format * Update * Update main.dart --------- Co-authored-by: GitHub Co-authored-by: GIancarlo Buenaflor --- flutter/ios/sentry_flutter.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flutter/ios/sentry_flutter.podspec b/flutter/ios/sentry_flutter.podspec index dc89732f1d..dd9e94d81c 100644 --- a/flutter/ios/sentry_flutter.podspec +++ b/flutter/ios/sentry_flutter.podspec @@ -12,7 +12,7 @@ Sentry SDK for Flutter with support to native through sentry-cocoa. :tag => s.version.to_s } s.source_files = 'Classes/**/*' s.public_header_files = 'Classes/**/*.h' - s.dependency 'Sentry/HybridSDK', '8.20.0' + s.dependency 'Sentry/HybridSDK', '8.21.0' s.ios.dependency 'Flutter' s.osx.dependency 'FlutterMacOS' s.ios.deployment_target = '11.0' From 6af26517f138040e5b681e2698b2f555ac91466e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Mar 2024 15:40:54 +0100 Subject: [PATCH 095/237] build(deps): bump invertase/github-action-dart-analyzer (#1911) Bumps [invertase/github-action-dart-analyzer](https://github.com/invertase/github-action-dart-analyzer) from 2.0.0 to 3.0.0. - [Release notes](https://github.com/invertase/github-action-dart-analyzer/releases) - [Commits](https://github.com/invertase/github-action-dart-analyzer/compare/1cda5922c6369263b1c7e2fbe281f69704f4d63e...e981b01a458d0bab71ee5da182e5b26687b7101b) --- updated-dependencies: - dependency-name: invertase/github-action-dart-analyzer dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/analyze.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/analyze.yml b/.github/workflows/analyze.yml index b43828001c..b14fe35209 100644 --- a/.github/workflows/analyze.yml +++ b/.github/workflows/analyze.yml @@ -41,7 +41,7 @@ jobs: - run: dart format --set-exit-if-changed ./ - name: dart analyze - uses: invertase/github-action-dart-analyzer@1cda5922c6369263b1c7e2fbe281f69704f4d63e # pin@v2.0.0 + uses: invertase/github-action-dart-analyzer@e981b01a458d0bab71ee5da182e5b26687b7101b # pin@v3.0.0 with: annotate: true fatal-infos: true From 8af7527558104354ed685d0c349ced818bf4bee4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Mar 2024 16:10:51 +0100 Subject: [PATCH 096/237] build(deps): bump codecov/codecov-action from 4.0.2 to 4.1.0 (#1912) Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 4.0.2 to 4.1.0. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/0cfda1dd0a4ad9efc75517f399d859cd1ea4ced1...54bcd8715eee62d40e33596ef5e8f0f48dbbccab) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor --- .github/workflows/dart.yml | 2 +- .github/workflows/dio.yml | 2 +- .github/workflows/drift.yml | 2 +- .github/workflows/file.yml | 2 +- .github/workflows/flutter.yml | 2 +- .github/workflows/hive.yml | 2 +- .github/workflows/isar.yml | 2 +- .github/workflows/logging.yml | 2 +- .github/workflows/sqflite.yml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml index dcd8212409..d0ffb5ebfe 100644 --- a/.github/workflows/dart.yml +++ b/.github/workflows/dart.yml @@ -68,7 +68,7 @@ jobs: dart pub get webdev build - - uses: codecov/codecov-action@0cfda1dd0a4ad9efc75517f399d859cd1ea4ced1 # pin@v3 + - uses: codecov/codecov-action@54bcd8715eee62d40e33596ef5e8f0f48dbbccab # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: name: sentry diff --git a/.github/workflows/dio.yml b/.github/workflows/dio.yml index 2503fe6e21..75b803f978 100644 --- a/.github/workflows/dio.yml +++ b/.github/workflows/dio.yml @@ -52,7 +52,7 @@ jobs: dart test -p vm --coverage=coverage --test-randomize-ordering-seed=random --chain-stack-traces dart pub run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.dart_tool/package_config.json --report-on=lib - - uses: codecov/codecov-action@0cfda1dd0a4ad9efc75517f399d859cd1ea4ced1 # pin@v3 + - uses: codecov/codecov-action@54bcd8715eee62d40e33596ef5e8f0f48dbbccab # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: name: sentry_dio diff --git a/.github/workflows/drift.yml b/.github/workflows/drift.yml index 9d8fa4a45c..886b93dc55 100644 --- a/.github/workflows/drift.yml +++ b/.github/workflows/drift.yml @@ -93,7 +93,7 @@ jobs: cd drift flutter test --coverage --test-randomize-ordering-seed=random - - uses: codecov/codecov-action@0cfda1dd0a4ad9efc75517f399d859cd1ea4ced1 # pin@v3 + - uses: codecov/codecov-action@54bcd8715eee62d40e33596ef5e8f0f48dbbccab # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' with: name: sentry_drift diff --git a/.github/workflows/file.yml b/.github/workflows/file.yml index 45f0c91588..de2841ae20 100644 --- a/.github/workflows/file.yml +++ b/.github/workflows/file.yml @@ -52,7 +52,7 @@ jobs: dart test -p vm --coverage=coverage --test-randomize-ordering-seed=random --chain-stack-traces dart pub run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.dart_tool/package_config.json --report-on=lib - - uses: codecov/codecov-action@0cfda1dd0a4ad9efc75517f399d859cd1ea4ced1 # pin@v3 + - uses: codecov/codecov-action@54bcd8715eee62d40e33596ef5e8f0f48dbbccab # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: name: sentry_file diff --git a/.github/workflows/flutter.yml b/.github/workflows/flutter.yml index 77bcdc0e08..040aa2f69e 100644 --- a/.github/workflows/flutter.yml +++ b/.github/workflows/flutter.yml @@ -112,7 +112,7 @@ jobs: flutter test --coverage --test-randomize-ordering-seed=random dart run remove_from_coverage -f coverage/lcov.info -r 'binding.dart' - - uses: codecov/codecov-action@0cfda1dd0a4ad9efc75517f399d859cd1ea4ced1 # pin@v3 + - uses: codecov/codecov-action@54bcd8715eee62d40e33596ef5e8f0f48dbbccab # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' with: name: sentry_flutter diff --git a/.github/workflows/hive.yml b/.github/workflows/hive.yml index add3e9e54f..2f4fcebb60 100644 --- a/.github/workflows/hive.yml +++ b/.github/workflows/hive.yml @@ -51,7 +51,7 @@ jobs: dart test -p vm --coverage=coverage --test-randomize-ordering-seed=random --chain-stack-traces dart pub run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.dart_tool/package_config.json --report-on=lib - - uses: codecov/codecov-action@0cfda1dd0a4ad9efc75517f399d859cd1ea4ced1 # pin@v3 + - uses: codecov/codecov-action@54bcd8715eee62d40e33596ef5e8f0f48dbbccab # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: name: sentry_hive diff --git a/.github/workflows/isar.yml b/.github/workflows/isar.yml index 69f79d3006..48c17e00ce 100644 --- a/.github/workflows/isar.yml +++ b/.github/workflows/isar.yml @@ -93,7 +93,7 @@ jobs: cd isar flutter test -j 1 --coverage --test-randomize-ordering-seed=random - - uses: codecov/codecov-action@0cfda1dd0a4ad9efc75517f399d859cd1ea4ced1 # pin@v3 + - uses: codecov/codecov-action@54bcd8715eee62d40e33596ef5e8f0f48dbbccab # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' with: name: sentry_isar diff --git a/.github/workflows/logging.yml b/.github/workflows/logging.yml index 755ff60043..138364fb31 100644 --- a/.github/workflows/logging.yml +++ b/.github/workflows/logging.yml @@ -52,7 +52,7 @@ jobs: dart test -p vm --coverage=coverage --test-randomize-ordering-seed=random --chain-stack-traces dart pub run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.dart_tool/package_config.json --report-on=lib - - uses: codecov/codecov-action@0cfda1dd0a4ad9efc75517f399d859cd1ea4ced1 # pin@v3 + - uses: codecov/codecov-action@54bcd8715eee62d40e33596ef5e8f0f48dbbccab # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: name: sentry_logging diff --git a/.github/workflows/sqflite.yml b/.github/workflows/sqflite.yml index bbbdf7e12a..4d5f9f9e91 100644 --- a/.github/workflows/sqflite.yml +++ b/.github/workflows/sqflite.yml @@ -93,7 +93,7 @@ jobs: cd sqflite flutter test --coverage --test-randomize-ordering-seed=random - - uses: codecov/codecov-action@0cfda1dd0a4ad9efc75517f399d859cd1ea4ced1 # pin@v3 + - uses: codecov/codecov-action@54bcd8715eee62d40e33596ef5e8f0f48dbbccab # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' with: name: sentry_sqflite From 5cc82a0b7b216bac12872cd053b144a41afe2133 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Mar 2024 16:10:59 +0100 Subject: [PATCH 097/237] build(deps): bump subosito/flutter-action from 2.12.0 to 2.13.0 (#1913) Bumps [subosito/flutter-action](https://github.com/subosito/flutter-action) from 2.12.0 to 2.13.0. - [Release notes](https://github.com/subosito/flutter-action/releases) - [Commits](https://github.com/subosito/flutter-action/compare/2783a3f08e1baf891508463f8c6653c258246225...62f096cacda5168a3bd7b95793373be14fa4fbaf) --- updated-dependencies: - dependency-name: subosito/flutter-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/analyze.yml | 2 +- .github/workflows/drift.yml | 2 +- .github/workflows/flutter.yml | 2 +- .github/workflows/flutter_test.yml | 4 ++-- .github/workflows/format-and-fix.yml | 2 +- .github/workflows/isar.yml | 2 +- .github/workflows/metrics.yml | 2 +- .github/workflows/min_version_test.yml | 6 +++--- .github/workflows/sqflite.yml | 2 +- .github/workflows/web-example-ghpages.yml | 2 +- 10 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/analyze.yml b/.github/workflows/analyze.yml index b14fe35209..dd37d37755 100644 --- a/.github/workflows/analyze.yml +++ b/.github/workflows/analyze.yml @@ -34,7 +34,7 @@ jobs: - uses: actions/checkout@v4 - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 # pin@v1 if: ${{ inputs.sdk == 'dart' }} - - uses: subosito/flutter-action@2783a3f08e1baf891508463f8c6653c258246225 # pin@v2.12.0 + - uses: subosito/flutter-action@62f096cacda5168a3bd7b95793373be14fa4fbaf # pin@v2.13.0 if: ${{ inputs.sdk == 'flutter' }} - run: ${{ inputs.sdk }} pub get diff --git a/.github/workflows/drift.yml b/.github/workflows/drift.yml index 886b93dc55..6e5ea56c07 100644 --- a/.github/workflows/drift.yml +++ b/.github/workflows/drift.yml @@ -77,7 +77,7 @@ jobs: sudo apt install -y network-manager upower if: matrix.os == 'ubuntu-latest' && matrix.target == 'linux' - - uses: subosito/flutter-action@2783a3f08e1baf891508463f8c6653c258246225 # pin@v2.12.0 + - uses: subosito/flutter-action@62f096cacda5168a3bd7b95793373be14fa4fbaf # pin@v2.13.0 with: channel: ${{ matrix.sdk }} diff --git a/.github/workflows/flutter.yml b/.github/workflows/flutter.yml index 040aa2f69e..ae358b3713 100644 --- a/.github/workflows/flutter.yml +++ b/.github/workflows/flutter.yml @@ -82,7 +82,7 @@ jobs: sudo apt install -y network-manager upower if: matrix.os == 'ubuntu-latest' && matrix.target == 'linux' - - uses: subosito/flutter-action@2783a3f08e1baf891508463f8c6653c258246225 # pin@v2.12.0 + - uses: subosito/flutter-action@62f096cacda5168a3bd7b95793373be14fa4fbaf # pin@v2.13.0 with: channel: ${{ matrix.sdk }} diff --git a/.github/workflows/flutter_test.yml b/.github/workflows/flutter_test.yml index 4d60fabca5..375740e5dd 100644 --- a/.github/workflows/flutter_test.yml +++ b/.github/workflows/flutter_test.yml @@ -43,7 +43,7 @@ jobs: distribution: "adopt" java-version: "11" - - uses: subosito/flutter-action@2783a3f08e1baf891508463f8c6653c258246225 # pin@v2.12.0 + - uses: subosito/flutter-action@62f096cacda5168a3bd7b95793373be14fa4fbaf # pin@v2.13.0 with: channel: ${{ matrix.sdk }} @@ -126,7 +126,7 @@ jobs: - name: checkout uses: actions/checkout@v4 - - uses: subosito/flutter-action@2783a3f08e1baf891508463f8c6653c258246225 # pin@v2.12.0 + - uses: subosito/flutter-action@62f096cacda5168a3bd7b95793373be14fa4fbaf # pin@v2.13.0 with: channel: ${{ matrix.sdk }} diff --git a/.github/workflows/format-and-fix.yml b/.github/workflows/format-and-fix.yml index 681514d13d..9aa90f671b 100644 --- a/.github/workflows/format-and-fix.yml +++ b/.github/workflows/format-and-fix.yml @@ -32,7 +32,7 @@ jobs: - uses: actions/checkout@v4 - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 # pin@v1 if: ${{ matrix.package.sdk == 'dart' }} - - uses: subosito/flutter-action@2783a3f08e1baf891508463f8c6653c258246225 # pin@v2.12.0 + - uses: subosito/flutter-action@62f096cacda5168a3bd7b95793373be14fa4fbaf # pin@v2.13.0 if: ${{ matrix.package.sdk == 'flutter' }} - run: ${{ matrix.package.sdk }} pub get diff --git a/.github/workflows/isar.yml b/.github/workflows/isar.yml index 48c17e00ce..26394f7555 100644 --- a/.github/workflows/isar.yml +++ b/.github/workflows/isar.yml @@ -77,7 +77,7 @@ jobs: sudo apt install -y network-manager upower if: matrix.os == 'ubuntu-latest' && matrix.target == 'linux' - - uses: subosito/flutter-action@2783a3f08e1baf891508463f8c6653c258246225 # pin@v2.12.0 + - uses: subosito/flutter-action@62f096cacda5168a3bd7b95793373be14fa4fbaf # pin@v2.13.0 with: channel: ${{ matrix.sdk }} diff --git a/.github/workflows/metrics.yml b/.github/workflows/metrics.yml index 94278a167c..05fa327d35 100644 --- a/.github/workflows/metrics.yml +++ b/.github/workflows/metrics.yml @@ -53,7 +53,7 @@ jobs: echo "flutter=$version" >> "$GITHUB_OUTPUT" - name: Install Flutter v${{ steps.conf.outputs.flutter }} - uses: subosito/flutter-action@2783a3f08e1baf891508463f8c6653c258246225 # pin@v2.12.0 + uses: subosito/flutter-action@62f096cacda5168a3bd7b95793373be14fa4fbaf # pin@v2.13.0 with: flutter-version: ${{ steps.conf.outputs.flutter }} diff --git a/.github/workflows/min_version_test.yml b/.github/workflows/min_version_test.yml index c20f06489d..08d108309b 100644 --- a/.github/workflows/min_version_test.yml +++ b/.github/workflows/min_version_test.yml @@ -34,7 +34,7 @@ jobs: distribution: "adopt" java-version: "11" - - uses: subosito/flutter-action@2783a3f08e1baf891508463f8c6653c258246225 # pin@v2.12.0 + - uses: subosito/flutter-action@62f096cacda5168a3bd7b95793373be14fa4fbaf # pin@v2.13.0 with: flutter-version: "3.0.0" @@ -51,7 +51,7 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: subosito/flutter-action@2783a3f08e1baf891508463f8c6653c258246225 # pin@v2.12.0 + - uses: subosito/flutter-action@62f096cacda5168a3bd7b95793373be14fa4fbaf # pin@v2.13.0 with: flutter-version: "3.0.0" @@ -68,7 +68,7 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: subosito/flutter-action@2783a3f08e1baf891508463f8c6653c258246225 # pin@v2.12.0 + - uses: subosito/flutter-action@62f096cacda5168a3bd7b95793373be14fa4fbaf # pin@v2.13.0 with: flutter-version: "3.0.0" diff --git a/.github/workflows/sqflite.yml b/.github/workflows/sqflite.yml index 4d5f9f9e91..cea7a5ad14 100644 --- a/.github/workflows/sqflite.yml +++ b/.github/workflows/sqflite.yml @@ -77,7 +77,7 @@ jobs: sudo apt install -y network-manager upower if: matrix.os == 'ubuntu-latest' && matrix.target == 'linux' - - uses: subosito/flutter-action@2783a3f08e1baf891508463f8c6653c258246225 # pin@v2.12.0 + - uses: subosito/flutter-action@62f096cacda5168a3bd7b95793373be14fa4fbaf # pin@v2.13.0 with: channel: ${{ matrix.sdk }} diff --git a/.github/workflows/web-example-ghpages.yml b/.github/workflows/web-example-ghpages.yml index 106c52615d..6dcbd84e6f 100644 --- a/.github/workflows/web-example-ghpages.yml +++ b/.github/workflows/web-example-ghpages.yml @@ -14,7 +14,7 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: subosito/flutter-action@2783a3f08e1baf891508463f8c6653c258246225 # pin@v2.12.0 + - uses: subosito/flutter-action@62f096cacda5168a3bd7b95793373be14fa4fbaf # pin@v2.13.0 - uses: bluefireteam/flutter-gh-pages@57815b17b371455ec1a98f075b71b4c6ba0a938c # pin@v8 with: workingDir: flutter/example From f4bda4c6e92c9ca7c5bc583eb39637fb02d84982 Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Wed, 6 Mar 2024 12:05:36 +0100 Subject: [PATCH 098/237] ci: re-enable package analyzer (#1918) * enable again --- .github/workflows/analyze.yml | 63 +++++++++++++++++------------------ 1 file changed, 30 insertions(+), 33 deletions(-) diff --git a/.github/workflows/analyze.yml b/.github/workflows/analyze.yml index dd37d37755..0120603921 100644 --- a/.github/workflows/analyze.yml +++ b/.github/workflows/analyze.yml @@ -51,36 +51,33 @@ jobs: - run: dart doc --dry-run -# Currently Disabled because of git error `detected dubious ownership in repository. -# TODO: check if this is still an issue when git version in github runners is updated -# -# package-analysis: -# # `axel-op/dart-package-analyzer` is using `flutter pub upgrade` instead of `get`, -# # which ignores pubspec.yaml `dependency_overrides`. Because of that, all `release/*` branches are failing, -# # because the package cannot find the "about to be released" version of our sentry-dart package that it depends on. -# if: ${{ !startsWith(github.ref, 'refs/heads/release/') && inputs.panaThreshold > 0 }} -# runs-on: ubuntu-20.04 -# timeout-minutes: 20 -# steps: -# - uses: actions/checkout@v4 -# - name: Apply dependency override -# if: ${{ inputs.package == 'flutter' }} -# working-directory: ${{ inputs.package }} -# run: | -# sed -i.bak 's|sentry:.*|sentry:\n path: /github/workspace/dart|g' pubspec.yaml -# - uses: axel-op/dart-package-analyzer@7a6c3c66bce78d82b729a1ffef2d9458fde6c8d2 # pin@v3 -# id: analysis -# with: -# githubToken: ${{ secrets.GITHUB_TOKEN }} -# relativePath: ${{ inputs.package }} -# - name: Check scores -# env: -# TOTAL: ${{ steps.analysis.outputs.total }} -# TOTAL_MAX: ${{ steps.analysis.outputs.total_max }} -# run: | -# PERCENTAGE=$(( $TOTAL * 100 / $TOTAL_MAX )) -# if (( $PERCENTAGE < ${{ inputs.panaThreshold }} )) -# then -# echo Score too low! -# exit 1 -# fi + package-analysis: + # `axel-op/dart-package-analyzer` is using `flutter pub upgrade` instead of `get`, + # which ignores pubspec.yaml `dependency_overrides`. Because of that, all `release/*` branches are failing, + # because the package cannot find the "about to be released" version of our sentry-dart package that it depends on. + if: ${{ !startsWith(github.ref, 'refs/heads/release/') && inputs.panaThreshold > 0 }} + runs-on: ubuntu-20.04 + timeout-minutes: 20 + steps: + - uses: actions/checkout@v4 + - name: Apply dependency override + if: ${{ inputs.package == 'flutter' }} + working-directory: ${{ inputs.package }} + run: | + sed -i.bak 's|sentry:.*|sentry:\n path: /github/workspace/dart|g' pubspec.yaml + - uses: axel-op/dart-package-analyzer@d9b13539ce28b8a2f85605379ce8670209d571e8 # pin@v3 + id: analysis + with: + githubToken: ${{ secrets.GITHUB_TOKEN }} + relativePath: ${{ inputs.package }} + - name: Check scores + env: + TOTAL: ${{ steps.analysis.outputs.total }} + TOTAL_MAX: ${{ steps.analysis.outputs.total_max }} + run: | + PERCENTAGE=$(( $TOTAL * 100 / $TOTAL_MAX )) + if (( $PERCENTAGE < ${{ inputs.panaThreshold }} )) + then + echo Score too low! + exit 1 + fi From 202b83fbe2be04234709a8daf58ea4290ec01cc6 Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Wed, 6 Mar 2024 12:05:50 +0100 Subject: [PATCH 099/237] fix: transaction timestamp trimming (#1916) * Fix child timestamp trimming * Update CHANGELOG * Run formatting * Update docs * Revert * Update dart/test/sentry_tracer_test.dart Co-authored-by: Philipp Hofmann * change var to final * fix test --------- Co-authored-by: Philipp Hofmann --- CHANGELOG.md | 5 +++++ dart/lib/src/sentry_tracer.dart | 24 +++++++++++++++--------- dart/test/sentry_tracer_test.dart | 22 ++++++++++++++++++++++ 3 files changed, 42 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a7f259f8b0..6442a03abe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ ## Unreleased +### Fixes + +- Fix transaction end timestamp trimming ([#1916](https://github.com/getsentry/sentry-dart/pull/1916)) + - Transaction end timestamps are now correctly trimmed to the latest child span end timestamp + ### Features - Use `recordHttpBreadcrumbs` to set iOS `enableNetworkBreadcrumbs` ([#1884](https://github.com/getsentry/sentry-dart/pull/1884)) diff --git a/dart/lib/src/sentry_tracer.dart b/dart/lib/src/sentry_tracer.dart index c57912fe46..c7f6993ad3 100644 --- a/dart/lib/src/sentry_tracer.dart +++ b/dart/lib/src/sentry_tracer.dart @@ -109,18 +109,24 @@ class SentryTracer extends ISentrySpan { } var _rootEndTimestamp = commonEndTimestamp; + + // Trim the end timestamp of the transaction to the very last timestamp of child spans if (_trimEnd && children.isNotEmpty) { - final childEndTimestamps = children - .where((child) => child.endTimestamp != null) - .map((child) => child.endTimestamp!); - - if (childEndTimestamps.isNotEmpty) { - final oldestChildEndTimestamp = - childEndTimestamps.reduce((a, b) => a.isAfter(b) ? a : b); - if (_rootEndTimestamp.isAfter(oldestChildEndTimestamp)) { - _rootEndTimestamp = oldestChildEndTimestamp; + DateTime? latestEndTime; + + for (final child in children) { + final childEndTimestamp = child.endTimestamp; + if (childEndTimestamp != null) { + if (latestEndTime == null || + childEndTimestamp.isAfter(latestEndTime)) { + latestEndTime = child.endTimestamp; + } } } + + if (latestEndTime != null) { + _rootEndTimestamp = latestEndTime; + } } // the callback should run before because if the span is finished, diff --git a/dart/test/sentry_tracer_test.dart b/dart/test/sentry_tracer_test.dart index 48ff011e82..1a328702d1 100644 --- a/dart/test/sentry_tracer_test.dart +++ b/dart/test/sentry_tracer_test.dart @@ -386,6 +386,28 @@ void main() { expect(sut.endTimestamp, endTimestamp); }); + test('end trimmed to latest child end timestamp', () async { + final sut = fixture.getSut(trimEnd: true); + final rootEndInitial = getUtcDateTime(); + final childAEnd = rootEndInitial; + final childBEnd = rootEndInitial.add(Duration(seconds: 1)); + final childCEnd = rootEndInitial; + + final childA = sut.startChild('operation-a', description: 'description'); + final childB = sut.startChild('operation-b', description: 'description'); + final childC = sut.startChild('operation-c', description: 'description'); + + await childA.finish(endTimestamp: childAEnd); + await childB.finish(endTimestamp: childBEnd); + await childC.finish(endTimestamp: childCEnd); + + await sut.finish(endTimestamp: rootEndInitial); + + expect(sut.endTimestamp, equals(childB.endTimestamp), + reason: + 'The root end timestamp should be updated to match the latest child end timestamp.'); + }); + test('does not add more spans than configured in options', () async { fixture.hub.options.maxSpans = 2; final sut = fixture.getSut(); From cc807145d186a99a58be0997ef14e4f55a27adc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20Andra=C5=A1ec?= Date: Wed, 6 Mar 2024 14:57:47 +0000 Subject: [PATCH 100/237] Add `maxQueueSize` to limit the number of unawaited events sent to Sentry (#1868) * introduce task queue * handle trow in task * handle throwing tasks * Add documentation * add changelog entry --------- Co-authored-by: Giancarlo Buenaflor --- CHANGELOG.md | 1 + dart/lib/src/sentry_client.dart | 10 +- dart/lib/src/sentry_options.dart | 14 +++ dart/lib/src/transport/task_queue.dart | 29 ++++++ dart/test/transport/tesk_queue_test.dart | 118 +++++++++++++++++++++++ 5 files changed, 171 insertions(+), 1 deletion(-) create mode 100644 dart/lib/src/transport/task_queue.dart create mode 100644 dart/test/transport/tesk_queue_test.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index 6442a03abe..15a19c8468 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ ### Features - Use `recordHttpBreadcrumbs` to set iOS `enableNetworkBreadcrumbs` ([#1884](https://github.com/getsentry/sentry-dart/pull/1884)) +- Add `maxQueueSize` to limit the number of unawaited events sent to Sentry ([#1868]((https://github.com/getsentry/sentry-dart/pull/1868)) ### Improvements diff --git a/dart/lib/src/sentry_client.dart b/dart/lib/src/sentry_client.dart index be866d6719..9761a4b349 100644 --- a/dart/lib/src/sentry_client.dart +++ b/dart/lib/src/sentry_client.dart @@ -17,6 +17,7 @@ import 'sentry_stack_trace_factory.dart'; import 'transport/http_transport.dart'; import 'transport/noop_transport.dart'; import 'transport/spotlight_http_transport.dart'; +import 'transport/task_queue.dart'; import 'utils/isolate_utils.dart'; import 'version.dart'; import 'sentry_envelope.dart'; @@ -32,6 +33,10 @@ const _defaultIpAddress = '{{auto}}'; /// Logs crash reports and events to the Sentry.io service. class SentryClient { final SentryOptions _options; + late final _taskQueue = TaskQueue( + _options.maxQueueSize, + _options.logger, + ); final Random? _random; @@ -514,6 +519,9 @@ class SentryClient { Future _attachClientReportsAndSend(SentryEnvelope envelope) { final clientReport = _options.recorder.flush(); envelope.addClientReport(clientReport); - return _options.transport.send(envelope); + return _taskQueue.enqueue( + () => _options.transport.send(envelope), + SentryId.empty(), + ); } } diff --git a/dart/lib/src/sentry_options.dart b/dart/lib/src/sentry_options.dart index 5fa8b793f0..1de3a49d0f 100644 --- a/dart/lib/src/sentry_options.dart +++ b/dart/lib/src/sentry_options.dart @@ -81,6 +81,20 @@ class SentryOptions { _maxSpans = maxSpans; } + int _maxQueueSize = 30; + + /// Returns the max number of events Sentry will send when calling capture + /// methods in a tight loop. Default is 30. + int get maxQueueSize => _maxQueueSize; + + /// Sets how many unawaited events can be sent by Sentry. (e.g. capturing + /// events in a tight loop) at once. If you need to send more, please use the + /// await keyword. + set maxQueueSize(int count) { + assert(count > 0); + _maxQueueSize = count; + } + /// Configures up to which size request bodies should be included in events. /// This does not change whether an event is captured. MaxRequestBodySize maxRequestBodySize = MaxRequestBodySize.never; diff --git a/dart/lib/src/transport/task_queue.dart b/dart/lib/src/transport/task_queue.dart new file mode 100644 index 0000000000..386a4980f2 --- /dev/null +++ b/dart/lib/src/transport/task_queue.dart @@ -0,0 +1,29 @@ +import 'dart:async'; + +import '../../sentry.dart'; + +typedef Task = Future Function(); + +class TaskQueue { + TaskQueue(this._maxQueueSize, this._logger); + + final int _maxQueueSize; + final SentryLogger _logger; + + int _queueCount = 0; + + Future enqueue(Task task, T fallbackResult) async { + if (_queueCount >= _maxQueueSize) { + _logger(SentryLevel.warning, + 'Task dropped due to backpressure. Avoid capturing in a tight loop.'); + return fallbackResult; + } else { + _queueCount++; + try { + return await task(); + } finally { + _queueCount--; + } + } + } +} diff --git a/dart/test/transport/tesk_queue_test.dart b/dart/test/transport/tesk_queue_test.dart new file mode 100644 index 0000000000..80dc97161c --- /dev/null +++ b/dart/test/transport/tesk_queue_test.dart @@ -0,0 +1,118 @@ +import 'dart:async'; + +import 'package:sentry/sentry.dart'; +import 'package:sentry/src/transport/task_queue.dart'; +import 'package:test/test.dart'; + +import '../mocks.dart'; + +void main() { + group("called sync", () { + late Fixture fixture; + + setUp(() { + fixture = Fixture(); + }); + + test("enqueue only executed `maxQueueSize` times when not awaiting", + () async { + final sut = fixture.getSut(maxQueueSize: 5); + + var completedTasks = 0; + + for (int i = 0; i < 10; i++) { + unawaited(sut.enqueue(() async { + print('Task $i'); + await Future.delayed(Duration(milliseconds: 1)); + completedTasks += 1; + return 1 + 1; + }, -1)); + } + + // This will always await the other futures, even if they are running longer, as it was scheduled after them. + print('Started waiting for first 5 tasks'); + await Future.delayed(Duration(milliseconds: 1)); + print('Stopped waiting for first 5 tasks'); + + expect(completedTasks, 5); + }); + + test("enqueue picks up tasks again after await in-between", () async { + final sut = fixture.getSut(maxQueueSize: 5); + + var completedTasks = 0; + + for (int i = 1; i <= 10; i++) { + unawaited(sut.enqueue(() async { + print('Started task $i'); + await Future.delayed(Duration(milliseconds: 1)); + print('Completed task $i'); + completedTasks += 1; + return 1 + 1; + }, -1)); + } + + print('Started waiting for first 5 tasks'); + await Future.delayed(Duration(milliseconds: 1)); + print('Stopped waiting for first 5 tasks'); + + for (int i = 6; i <= 15; i++) { + unawaited(sut.enqueue(() async { + print('Started task $i'); + await Future.delayed(Duration(milliseconds: 1)); + print('Completed task $i'); + completedTasks += 1; + return 1 + 1; + }, -1)); + } + + print('Started waiting for second 5 tasks'); + await Future.delayed(Duration(milliseconds: 5)); + print('Stopped waiting for second 5 tasks'); + + expect(completedTasks, 10); // 10 were dropped + }); + + test("enqueue executes all tasks when awaiting", () async { + final sut = fixture.getSut(maxQueueSize: 5); + + var completedTasks = 0; + + for (int i = 0; i < 10; i++) { + await sut.enqueue(() async { + print('Task $i'); + await Future.delayed(Duration(milliseconds: 1)); + completedTasks += 1; + return 1 + 1; + }, -1); + } + expect(completedTasks, 10); + }); + + test("throwing tasks still execute as expected", () async { + final sut = fixture.getSut(maxQueueSize: 5); + + var completedTasks = 0; + + for (int i = 0; i < 10; i++) { + try { + await sut.enqueue(() async { + completedTasks += 1; + throw Error(); + }, -1); + } catch (_) { + // Ignore + } + } + expect(completedTasks, 10); + }); + }); +} + +class Fixture { + final options = SentryOptions(dsn: fakeDsn); + + TaskQueue getSut({required int maxQueueSize}) { + return TaskQueue(maxQueueSize, options.logger); + } +} From 047697c1ef587cfc589cb312a90f7eb2f70cae9d Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Wed, 6 Mar 2024 16:47:07 +0100 Subject: [PATCH 101/237] Add missing changelog (#1921) --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 15a19c8468..423e2608f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,15 @@ - App start is now fetched within integration instead of event processor ([#1905](https://github.com/getsentry/sentry-dart/pull/1905)) +### Dependencies + +- Bump Cocoa SDK from v8.20.0 to v8.21.0 ([#1909](https://github.com/getsentry/sentry-dart/pull/1909)) + - [changelog](https://github.com/getsentry/sentry-cocoa/blob/main/CHANGELOG.md#8210) + - [diff](https://github.com/getsentry/sentry-cocoa/compare/8.20.0...8.21.0) +- Bump Android SDK from v7.3.0 to v7.5.0 ([#1907](https://github.com/getsentry/sentry-dart/pull/1907)) + - [changelog](https://github.com/getsentry/sentry-java/blob/main/CHANGELOG.md#750) + - [diff](https://github.com/getsentry/sentry-java/compare/7.3.0...7.5.0) + ## 7.16.1 ### Fixes From cd50afa83895ada42e70a069a8faff79fd72bebe Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Wed, 6 Mar 2024 17:03:09 +0100 Subject: [PATCH 102/237] Fix changelog (#1922) --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 423e2608f1..354f875aba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,7 @@ ### Features - Use `recordHttpBreadcrumbs` to set iOS `enableNetworkBreadcrumbs` ([#1884](https://github.com/getsentry/sentry-dart/pull/1884)) -- Add `maxQueueSize` to limit the number of unawaited events sent to Sentry ([#1868]((https://github.com/getsentry/sentry-dart/pull/1868)) +- Add `maxQueueSize` to limit the number of unawaited events sent to Sentry ([#1868](https://github.com/getsentry/sentry-dart/pull/1868)) ### Improvements From bffc2c57d27178214d7b567c9abbf911a4f61801 Mon Sep 17 00:00:00 2001 From: Daniel Varga-Hali Date: Thu, 7 Mar 2024 15:09:43 +0100 Subject: [PATCH 103/237] fix(sentry-dart): remove transitive dart:io reference for web (#1898) * fix(sentry-dart): remove transitive dart:io reference for web TransportUtils imported sentry_io.dart which prevented web projects such as example_web from building when build_runner was used. Resolves getsentry/sentry-dart#1893 * docs(api): update CHANGELOG.md for unreleased fix CHANGELOG.md now includes information about unreleased fix for issue #1893. * test(dart-sentry): add compilation tests for example_web Added tests to check if example_web project can be compiled with build_runner. Resolves getsentry/sentry-dart#1893 * test(dart-sentry): fix failing tests for example_web compilation Test ordering should not have impact on example_web_comopile_test and path handling across platforms was simplified. Resolves getsentry/sentry-dart#1893 * docs(api): update CHANGELOG.md Place entry for #1893 under unreleased fix in CHANGELOG getsentry/sentry-dart#1893 * chore(code-style): code formatting for #1893 --- CHANGELOG.md | 1 + dart/lib/src/utils/transport_utils.dart | 4 +- dart/test/example_web_compile_test.dart | 86 +++++++++++++++++++++++++ 3 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 dart/test/example_web_compile_test.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index 354f875aba..d5fac9c752 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - Fix transaction end timestamp trimming ([#1916](https://github.com/getsentry/sentry-dart/pull/1916)) - Transaction end timestamps are now correctly trimmed to the latest child span end timestamp +- remove transitive dart:io reference for web ([#1898](https://github.com/getsentry/sentry-dart/pull/1898)) ### Features diff --git a/dart/lib/src/utils/transport_utils.dart b/dart/lib/src/utils/transport_utils.dart index 388db8e8d5..fa2f20096a 100644 --- a/dart/lib/src/utils/transport_utils.dart +++ b/dart/lib/src/utils/transport_utils.dart @@ -1,7 +1,9 @@ import 'package:http/http.dart'; -import '../../sentry_io.dart'; import '../client_reports/discard_reason.dart'; +import '../protocol.dart'; +import '../sentry_envelope.dart'; +import '../sentry_options.dart'; import '../transport/data_category.dart'; class TransportUtils { diff --git a/dart/test/example_web_compile_test.dart b/dart/test/example_web_compile_test.dart new file mode 100644 index 0000000000..d327dcaed1 --- /dev/null +++ b/dart/test/example_web_compile_test.dart @@ -0,0 +1,86 @@ +@TestOn('vm') +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; + +import 'package:test/test.dart'; + +// Tests for the following issue +// https://github.com/getsentry/sentry-dart/issues/1893 +void main() { + group('Compile example_web', () { + test( + 'dart pub get and compilation should run successfully', + () async { + final result = await _runProcess('dart pub get', + workingDirectory: _exampleWebWorkingDir); + expect(result.exitCode, 0, + reason: 'Could run `dart pub get` for example_web. ' + 'Likely caused by outdated dependencies'); + // running this test locally require clean working directory + final cleanResult = await _runProcess('dart run build_runner clean', + workingDirectory: _exampleWebWorkingDir); + expect(cleanResult.exitCode, 0); + final compileResult = await _runProcess( + 'dart run build_runner build -r web -o build --delete-conflicting-outputs', + workingDirectory: _exampleWebWorkingDir); + expect(compileResult.exitCode, 0, + reason: 'Could not compile example_web project'); + expect( + compileResult.stdout, + isNot(contains( + 'Skipping compiling sentry_dart_web_example|web/main.dart')), + reason: + 'Could not compile main.dart, likely because of dart:io import.'); + expect( + compileResult.stdout, + contains( + 'build_web_compilers:entrypoint on web/main.dart:Compiled')); + }, + timeout: Timeout(const Duration(minutes: 1)), // double of detault timeout + ); + }); +} + +/// Runs [command] with command's stdout and stderr being forwrarded to +/// test runner's respective streams. It buffers stdout and returns it. +/// +/// Returns [_CommandResult] with exitCode and stdout as a single sting +Future<_CommandResult> _runProcess(String command, + {String workingDirectory = '.'}) async { + final parts = command.split(' '); + assert(parts.isNotEmpty); + final cmd = parts[0]; + final args = parts.skip(1).toList(); + final process = + await Process.start(cmd, args, workingDirectory: workingDirectory); + // forward standard streams + unawaited(stderr.addStream(process.stderr)); + final buffer = []; + final stdoutCompleter = Completer.sync(); + process.stdout.listen( + (units) { + buffer.addAll(units); + stdout.add(units); + }, + cancelOnError: true, + onDone: () { + stdoutCompleter.complete(); + }, + ); + await stdoutCompleter.future; + final processOut = utf8.decode(buffer); + int exitCode = await process.exitCode; + return _CommandResult(exitCode: exitCode, stdout: processOut); +} + +String get _exampleWebWorkingDir { + return '${Directory.current.path}${Platform.pathSeparator}example_web'; +} + +class _CommandResult { + final int exitCode; + final String stdout; + + const _CommandResult({required this.exitCode, required this.stdout}); +} From 1d9ee987caba8514f8389dcd48d0916e24f0740b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20Andra=C5=A1ec?= Date: Thu, 7 Mar 2024 16:02:23 +0000 Subject: [PATCH 104/237] Apply `beforeBreadcrumb` on native iOS crumbs (#1914) * apply beforeBreadcrumb on native iOS crumbs --------- Co-authored-by: Giancarlo Buenaflor --- CHANGELOG.md | 1 + .../load_contexts_integration.dart | 12 ++++++- .../load_contexts_integration_test.dart | 36 +++++++++++++++++++ 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d5fac9c752..cadf415d7a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ ### Features - Use `recordHttpBreadcrumbs` to set iOS `enableNetworkBreadcrumbs` ([#1884](https://github.com/getsentry/sentry-dart/pull/1884)) +- Apply `beforeBreadcrumb` on native iOS crumbs ([#1914](https://github.com/getsentry/sentry-dart/pull/1914)) - Add `maxQueueSize` to limit the number of unawaited events sent to Sentry ([#1868](https://github.com/getsentry/sentry-dart/pull/1868)) ### Improvements diff --git a/flutter/lib/src/integrations/load_contexts_integration.dart b/flutter/lib/src/integrations/load_contexts_integration.dart index 710d7d0924..c77981d35c 100644 --- a/flutter/lib/src/integrations/load_contexts_integration.dart +++ b/flutter/lib/src/integrations/load_contexts_integration.dart @@ -155,13 +155,23 @@ class _LoadContextsIntegrationEventProcessor implements EventProcessor { final breadcrumbsJson = List>.from(breadcrumbsList); final breadcrumbs = []; + final beforeBreadcrumb = _options.beforeBreadcrumb; for (final breadcrumbJson in breadcrumbsJson) { final breadcrumb = Breadcrumb.fromJson( Map.from(breadcrumbJson), ); - breadcrumbs.add(breadcrumb); + + if (beforeBreadcrumb != null) { + final processedBreadcrumb = beforeBreadcrumb(breadcrumb); + if (processedBreadcrumb != null) { + breadcrumbs.add(processedBreadcrumb); + } + } else { + breadcrumbs.add(breadcrumb); + } } + event = event.copyWith(breadcrumbs: breadcrumbs); } diff --git a/flutter/test/integrations/load_contexts_integration_test.dart b/flutter/test/integrations/load_contexts_integration_test.dart index a97b35db77..29aed18027 100644 --- a/flutter/test/integrations/load_contexts_integration_test.dart +++ b/flutter/test/integrations/load_contexts_integration_test.dart @@ -88,6 +88,42 @@ void main() { expect(event.breadcrumbs!.length, 1); expect(event.breadcrumbs!.first.message, 'event'); }); + + test('apply beforeBreadcrumb to native breadcrumbs', () async { + fixture.options.enableScopeSync = true; + fixture.options.beforeBreadcrumb = (breadcrumb, {hint}) { + if (breadcrumb?.message == 'native-mutated') { + return breadcrumb?.copyWith(message: 'native-mutated-applied'); + } else { + return null; + } + }; + + final eventBreadcrumb = Breadcrumb(message: 'event'); + var event = SentryEvent(breadcrumbs: [eventBreadcrumb]); + + final nativeMutatedBreadcrumb = Breadcrumb(message: 'native-mutated'); + final nativeDeletedBreadcrumb = Breadcrumb(message: 'native-deleted'); + Map loadContexts = { + 'breadcrumbs': [ + nativeMutatedBreadcrumb.toJson(), + nativeDeletedBreadcrumb.toJson(), + ] + }; + + final future = Future.value(loadContexts); + when(fixture.methodChannel.invokeMethod('loadContexts')) + .thenAnswer((_) => future); + // ignore: deprecated_member_use + _channel.setMockMethodCallHandler((MethodCall methodCall) async {}); + + final integration = LoadContextsIntegration(fixture.methodChannel); + integration.call(fixture.hub, fixture.options); + event = (await fixture.options.eventProcessors.first.apply(event))!; + + expect(event.breadcrumbs!.length, 1); + expect(event.breadcrumbs!.first.message, 'native-mutated-applied'); + }); }); } From fd348902abe1dd374bd3ca6f19f0712742e127ec Mon Sep 17 00:00:00 2001 From: getsentry-bot Date: Thu, 7 Mar 2024 16:03:26 +0000 Subject: [PATCH 105/237] release: 7.17.0 --- CHANGELOG.md | 2 +- dart/lib/src/version.dart | 2 +- dart/pubspec.yaml | 2 +- dio/lib/src/version.dart | 2 +- dio/pubspec.yaml | 4 ++-- drift/lib/src/version.dart | 2 +- drift/pubspec.yaml | 4 ++-- file/lib/src/version.dart | 2 +- file/pubspec.yaml | 4 ++-- flutter/example/pubspec.yaml | 2 +- flutter/lib/src/version.dart | 2 +- flutter/pubspec.yaml | 4 ++-- hive/lib/src/version.dart | 2 +- hive/pubspec.yaml | 4 ++-- isar/lib/src/version.dart | 2 +- isar/pubspec.yaml | 4 ++-- logging/lib/src/version.dart | 2 +- logging/pubspec.yaml | 4 ++-- sqflite/lib/src/version.dart | 2 +- sqflite/pubspec.yaml | 4 ++-- 20 files changed, 28 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cadf415d7a..89cbc9c754 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## Unreleased +## 7.17.0 ### Fixes diff --git a/dart/lib/src/version.dart b/dart/lib/src/version.dart index 3ad262fa98..cbb5949ed5 100644 --- a/dart/lib/src/version.dart +++ b/dart/lib/src/version.dart @@ -9,7 +9,7 @@ library version; /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.16.1'; +const String sdkVersion = '7.17.0'; String sdkName(bool isWeb) => isWeb ? _browserSdkName : _ioSdkName; diff --git a/dart/pubspec.yaml b/dart/pubspec.yaml index 6021b39df7..013c29b763 100644 --- a/dart/pubspec.yaml +++ b/dart/pubspec.yaml @@ -1,5 +1,5 @@ name: sentry -version: 7.16.1 +version: 7.17.0 description: > A crash reporting library for Dart that sends crash reports to Sentry.io. This library supports Dart VM and Web. For Flutter consider sentry_flutter instead. diff --git a/dio/lib/src/version.dart b/dio/lib/src/version.dart index 46d77d60ec..2301db53a9 100644 --- a/dio/lib/src/version.dart +++ b/dio/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.16.1'; +const String sdkVersion = '7.17.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_dio'; diff --git a/dio/pubspec.yaml b/dio/pubspec.yaml index 82443b5eb1..bc0d739009 100644 --- a/dio/pubspec.yaml +++ b/dio/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_dio description: An integration which adds support for performance tracing for the Dio package. -version: 7.16.1 +version: 7.17.0 homepage: https://docs.sentry.io/platforms/dart/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -11,7 +11,7 @@ environment: dependencies: dio: ^5.0.0 - sentry: 7.16.1 + sentry: 7.17.0 dev_dependencies: meta: ^1.3.0 diff --git a/drift/lib/src/version.dart b/drift/lib/src/version.dart index 7f75ff407a..f2d0fec3bd 100644 --- a/drift/lib/src/version.dart +++ b/drift/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.16.1'; +const String sdkVersion = '7.17.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_drift'; diff --git a/drift/pubspec.yaml b/drift/pubspec.yaml index a4c6fdee08..e60fb873d1 100644 --- a/drift/pubspec.yaml +++ b/drift/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_drift description: An integration which adds support for performance tracing for the drift package. -version: 7.16.1 +version: 7.17.0 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -9,7 +9,7 @@ environment: sdk: '>=2.17.0 <4.0.0' dependencies: - sentry: 7.16.1 + sentry: 7.17.0 meta: ^1.3.0 drift: ^2.13.0 diff --git a/file/lib/src/version.dart b/file/lib/src/version.dart index e04b2f58b0..6b00da4fb7 100644 --- a/file/lib/src/version.dart +++ b/file/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.16.1'; +const String sdkVersion = '7.17.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_file'; diff --git a/file/pubspec.yaml b/file/pubspec.yaml index 8f2208135d..147fd84f33 100644 --- a/file/pubspec.yaml +++ b/file/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_file description: An integration which adds support for performance tracing for dart.io.File. -version: 7.16.1 +version: 7.17.0 homepage: https://docs.sentry.io/platforms/dart/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -10,7 +10,7 @@ environment: sdk: '>=2.19.0 <4.0.0' dependencies: - sentry: 7.16.1 + sentry: 7.17.0 meta: ^1.3.0 dev_dependencies: diff --git a/flutter/example/pubspec.yaml b/flutter/example/pubspec.yaml index 255acb68f4..4215e2ce1d 100644 --- a/flutter/example/pubspec.yaml +++ b/flutter/example/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_flutter_example description: Demonstrates how to use the sentry_flutter plugin. -version: 7.16.1 +version: 7.17.0 publish_to: 'none' # Remove this line if you wish to publish to pub.dev diff --git a/flutter/lib/src/version.dart b/flutter/lib/src/version.dart index 436f5e0a3e..9f513504fd 100644 --- a/flutter/lib/src/version.dart +++ b/flutter/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.16.1'; +const String sdkVersion = '7.17.0'; /// The default SDK name reported to Sentry.io in the submitted events. const String sdkName = 'sentry.dart.flutter'; diff --git a/flutter/pubspec.yaml b/flutter/pubspec.yaml index e2cfbed0e0..e3b07cb26d 100644 --- a/flutter/pubspec.yaml +++ b/flutter/pubspec.yaml @@ -1,5 +1,5 @@ name: sentry_flutter -version: 7.16.1 +version: 7.17.0 description: Sentry SDK for Flutter. This package aims to support different Flutter targets by relying on the many platforms supported by Sentry with native SDKs. homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart @@ -15,7 +15,7 @@ dependencies: sdk: flutter flutter_web_plugins: sdk: flutter - sentry: 7.16.1 + sentry: 7.17.0 package_info_plus: '>=1.0.0 <=5.0.1' meta: ^1.3.0 ffi: ^2.0.0 diff --git a/hive/lib/src/version.dart b/hive/lib/src/version.dart index 2dafd49739..a84bcd2db0 100644 --- a/hive/lib/src/version.dart +++ b/hive/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.16.1'; +const String sdkVersion = '7.17.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_hive'; diff --git a/hive/pubspec.yaml b/hive/pubspec.yaml index abb9cec12a..456b9fb520 100644 --- a/hive/pubspec.yaml +++ b/hive/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_hive description: An integration which adds support for performance tracing for the hive package. -version: 7.16.1 +version: 7.17.0 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -9,7 +9,7 @@ environment: sdk: '>=2.17.0 <4.0.0' dependencies: - sentry: 7.16.1 + sentry: 7.17.0 hive: ^2.2.3 meta: ^1.3.0 diff --git a/isar/lib/src/version.dart b/isar/lib/src/version.dart index 8b6ad5a4c0..e9df915ff7 100644 --- a/isar/lib/src/version.dart +++ b/isar/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.16.1'; +const String sdkVersion = '7.17.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_isar'; diff --git a/isar/pubspec.yaml b/isar/pubspec.yaml index 4e54204063..869fd08835 100644 --- a/isar/pubspec.yaml +++ b/isar/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_isar description: An integration which adds support for performance tracing for the isar package. -version: 7.16.1 +version: 7.17.0 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -12,7 +12,7 @@ environment: dependencies: isar: ^3.1.0 isar_flutter_libs: ^3.1.0 # contains Isar Core - sentry: 7.16.1 + sentry: 7.17.0 meta: ^1.3.0 path: ^1.8.3 diff --git a/logging/lib/src/version.dart b/logging/lib/src/version.dart index 2e858e22d4..2a83deadcc 100644 --- a/logging/lib/src/version.dart +++ b/logging/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.16.1'; +const String sdkVersion = '7.17.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_logging'; diff --git a/logging/pubspec.yaml b/logging/pubspec.yaml index 70b879d98b..3601790850 100644 --- a/logging/pubspec.yaml +++ b/logging/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_logging description: An integration which adds support for recording log from the logging package. -version: 7.16.1 +version: 7.17.0 homepage: https://docs.sentry.io/platforms/dart/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -11,7 +11,7 @@ environment: dependencies: logging: ^1.0.0 - sentry: 7.16.1 + sentry: 7.17.0 dev_dependencies: lints: ^3.0.0 diff --git a/sqflite/lib/src/version.dart b/sqflite/lib/src/version.dart index 0363d9675c..ab2d4a6533 100644 --- a/sqflite/lib/src/version.dart +++ b/sqflite/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.16.1'; +const String sdkVersion = '7.17.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_sqflite'; diff --git a/sqflite/pubspec.yaml b/sqflite/pubspec.yaml index 8ca7ba896b..e743e9e128 100644 --- a/sqflite/pubspec.yaml +++ b/sqflite/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_sqflite description: An integration which adds support for performance tracing for the sqflite package. -version: 7.16.1 +version: 7.17.0 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -10,7 +10,7 @@ environment: flutter: '>=3.3.0' # matching sqflite dependencies: - sentry: 7.16.1 + sentry: 7.17.0 sqflite: ^2.0.0 sqflite_common: ^2.0.0 meta: ^1.3.0 From 31b2afb442b730ab5e1c190ef0de71fbcee6bb38 Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Thu, 7 Mar 2024 17:18:10 +0100 Subject: [PATCH 106/237] feat: ttid (#1910) * Change app start integration in a way that works with ttid as well * Formatting * Update * add visibleForTesting * Update * update * Add app start info test * Remove set app start info null * Review improvements * Add TTID * Improvements * Improvements * Fix integration test * Update * Clear after tracking * Update CHANGELOG * Format * Update * Update * remove import * Update sentry tracer * Add (not all) improvements for pr review * combine transaction handler * Refactor trackAppStart and trackRegularRoute to use private method * Fix dart analyzer * Remove clear * Clear in tearDown * Apply suggestions from code review Co-authored-by: Philipp Hofmann * Apply PR suggestions * fix analyze * update * update * Fix tests * Fix analyze * revert sample * Update * Update * Fix test * Move clear to the beginning of function * Fix start time * Fix analyze * remove comment * Formatting * fix test * add ttid duration assertion and determineEndTime timeout * Rename finish transaction and do an early exit with enableAutoTransactions * Rename function * Remove static and getter for in navigator observer * Expose SentryDisplayWidget as public api and add it to example app * Fix dart analyze * Fix dart doc * Improve tests * Reduce fake frame finishing time and improve tests * Improve test names * Fix tests * Apply formatting * Add extra assertion in tests --------- Co-authored-by: Philipp Hofmann --- CHANGELOG.md | 10 + dart/lib/sentry.dart | 2 + dart/lib/src/sentry_measurement.dart | 7 + dart/lib/src/sentry_span_operations.dart | 7 + dart/lib/src/sentry_trace_origins.dart | 2 + flutter/example/android/app/build.gradle | 2 +- flutter/example/lib/main.dart | 4 +- flutter/lib/sentry_flutter.dart | 1 + .../native_app_start_integration.dart | 2 +- .../src/navigation/sentry_display_widget.dart | 60 ++++++ .../navigation/sentry_navigator_observer.dart | 106 ++++++--- .../navigation/time_to_display_tracker.dart | 34 +++ .../time_to_initial_display_tracker.dart | 136 ++++++++++++ flutter/test/fake_frame_callback_handler.dart | 7 +- .../sentry_display_widget_test.dart | 122 +++++++++++ .../time_to_display_tracker_test.dart | 186 ++++++++++++++++ .../time_to_initial_display_tracker_test.dart | 201 ++++++++++++++++++ .../test/sentry_navigator_observer_test.dart | 144 +++++++++---- 18 files changed, 961 insertions(+), 72 deletions(-) create mode 100644 dart/lib/src/sentry_span_operations.dart create mode 100644 flutter/lib/src/navigation/sentry_display_widget.dart create mode 100644 flutter/lib/src/navigation/time_to_display_tracker.dart create mode 100644 flutter/lib/src/navigation/time_to_initial_display_tracker.dart create mode 100644 flutter/test/navigation/sentry_display_widget_test.dart create mode 100644 flutter/test/navigation/time_to_display_tracker_test.dart create mode 100644 flutter/test/navigation/time_to_initial_display_tracker_test.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index cadf415d7a..aaf3e24ab1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,16 @@ ### Features +- Add TTID (time to initial display), which allows you to measure the time it takes to render the first frame of your screen ([#1910](https://github.com/getsentry/sentry-dart/pull/1910)) + - Requires using the [routing instrumentation](https://docs.sentry.io/platforms/flutter/integrations/routing-instrumentation/). + - Introduces two modes: + - `automatic` mode is enabled by default for all screens and will yield only an approximation result. + - `manual` mode requires manual instrumentation and will yield a more accurate result. + - To use `manual` mode, you need to wrap your desired widget: `SentryDisplayWidget(child: MyScreen())`. + - You can mix and match both modes in your app. + - Other significant fixes + - `didPop` doesn't trigger a new transaction + - Change transaction operation name to `ui.load` instead of `navigation` - Use `recordHttpBreadcrumbs` to set iOS `enableNetworkBreadcrumbs` ([#1884](https://github.com/getsentry/sentry-dart/pull/1884)) - Apply `beforeBreadcrumb` on native iOS crumbs ([#1914](https://github.com/getsentry/sentry-dart/pull/1914)) - Add `maxQueueSize` to limit the number of unawaited events sent to Sentry ([#1868](https://github.com/getsentry/sentry-dart/pull/1868)) diff --git a/dart/lib/sentry.dart b/dart/lib/sentry.dart index 5419aa45b8..f416d0b797 100644 --- a/dart/lib/sentry.dart +++ b/dart/lib/sentry.dart @@ -49,6 +49,8 @@ export 'src/utils/http_header_utils.dart'; // ignore: invalid_export_of_internal_element export 'src/sentry_trace_origins.dart'; // ignore: invalid_export_of_internal_element +export 'src/sentry_span_operations.dart'; +// ignore: invalid_export_of_internal_element export 'src/utils.dart'; // spotlight debugging export 'src/spotlight.dart'; diff --git a/dart/lib/src/sentry_measurement.dart b/dart/lib/src/sentry_measurement.dart index 481c513e9b..b95e506aab 100644 --- a/dart/lib/src/sentry_measurement.dart +++ b/dart/lib/src/sentry_measurement.dart @@ -39,6 +39,13 @@ class SentryMeasurement { value = duration.inMilliseconds, unit = DurationSentryMeasurementUnit.milliSecond; + /// Duration of the time to initial display in milliseconds + SentryMeasurement.timeToInitialDisplay(Duration duration) + : assert(!duration.isNegative), + name = 'time_to_initial_display', + value = duration.inMilliseconds, + unit = DurationSentryMeasurementUnit.milliSecond; + final String name; final num value; final SentryMeasurementUnit? unit; diff --git a/dart/lib/src/sentry_span_operations.dart b/dart/lib/src/sentry_span_operations.dart new file mode 100644 index 0000000000..fca22fc1e9 --- /dev/null +++ b/dart/lib/src/sentry_span_operations.dart @@ -0,0 +1,7 @@ +import 'package:meta/meta.dart'; + +@internal +class SentrySpanOperations { + static const String uiLoad = 'ui.load'; + static const String uiTimeToInitialDisplay = 'ui.load.initial_display'; +} diff --git a/dart/lib/src/sentry_trace_origins.dart b/dart/lib/src/sentry_trace_origins.dart index 5a7c49b339..4377fa2c03 100644 --- a/dart/lib/src/sentry_trace_origins.dart +++ b/dart/lib/src/sentry_trace_origins.dart @@ -27,4 +27,6 @@ class SentryTraceOrigins { static const autoDbDriftQueryExecutor = 'auto.db.drift.query.executor'; static const autoDbDriftTransactionExecutor = 'auto.db.drift.transaction.executor'; + static const autoUiTimeToDisplay = 'auto.ui.time_to_display'; + static const manualUiTimeToDisplay = 'manual.ui.time_to_display'; } diff --git a/flutter/example/android/app/build.gradle b/flutter/example/android/app/build.gradle index b54cd7fdf9..ac4557e2cd 100644 --- a/flutter/example/android/app/build.gradle +++ b/flutter/example/android/app/build.gradle @@ -48,7 +48,7 @@ android { defaultConfig { applicationId "io.sentry.samples.flutter" - minSdkVersion 19 + minSdkVersion flutter.minSdkVersion targetSdkVersion 33 versionCode flutterVersionCode.toInteger() versionName flutterVersionName diff --git a/flutter/example/lib/main.dart b/flutter/example/lib/main.dart index 6a0c0a5b81..19050ec79e 100644 --- a/flutter/example/lib/main.dart +++ b/flutter/example/lib/main.dart @@ -13,6 +13,7 @@ import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:sentry_isar/sentry_isar.dart'; import 'package:sentry_sqflite/sentry_sqflite.dart'; import 'package:sqflite/sqflite.dart'; + // import 'package:sqflite_common_ffi/sqflite_ffi.dart'; // import 'package:sqflite_common_ffi_web/sqflite_ffi_web.dart'; import 'package:universal_platform/universal_platform.dart'; @@ -80,6 +81,7 @@ Future setupSentry( // going to log too much for your app, but can be useful when figuring out // configuration issues, e.g. finding out why your events are not uploaded. options.debug = true; + options.spotlight = Spotlight(enabled: true); options.maxRequestBodySize = MaxRequestBodySize.always; options.maxResponseBodySize = MaxResponseBodySize.always; @@ -732,7 +734,7 @@ void navigateToAutoCloseScreen(BuildContext context) { context, MaterialPageRoute( settings: const RouteSettings(name: 'AutoCloseScreen'), - builder: (context) => const AutoCloseScreen(), + builder: (context) => SentryDisplayWidget(child: const AutoCloseScreen()), ), ); } diff --git a/flutter/lib/sentry_flutter.dart b/flutter/lib/sentry_flutter.dart index 0f43bf741b..d15c8b7a70 100644 --- a/flutter/lib/sentry_flutter.dart +++ b/flutter/lib/sentry_flutter.dart @@ -16,3 +16,4 @@ export 'src/screenshot/sentry_screenshot_quality.dart'; export 'src/user_interaction/sentry_user_interaction_widget.dart'; export 'src/binding_wrapper.dart'; export 'src/sentry_widget.dart'; +export 'src/navigation/sentry_display_widget.dart'; diff --git a/flutter/lib/src/integrations/native_app_start_integration.dart b/flutter/lib/src/integrations/native_app_start_integration.dart index 91d0c01940..0ba5c77c4f 100644 --- a/flutter/lib/src/integrations/native_app_start_integration.dart +++ b/flutter/lib/src/integrations/native_app_start_integration.dart @@ -114,9 +114,9 @@ class AppStartInfo { final AppStartType type; final DateTime start; final DateTime end; + Duration get duration => end.difference(start); SentryMeasurement toMeasurement() { - final duration = end.difference(start); return type == AppStartType.cold ? SentryMeasurement.coldAppStart(duration) : SentryMeasurement.warmAppStart(duration); diff --git a/flutter/lib/src/navigation/sentry_display_widget.dart b/flutter/lib/src/navigation/sentry_display_widget.dart new file mode 100644 index 0000000000..e42f5c4f72 --- /dev/null +++ b/flutter/lib/src/navigation/sentry_display_widget.dart @@ -0,0 +1,60 @@ +import 'package:flutter/cupertino.dart'; +import 'time_to_initial_display_tracker.dart'; + +import '../frame_callback_handler.dart'; + +/// A widget that reports the Time To Initially Displayed (TTID) of its child widget. +/// +/// This widget wraps around another widget to measure and report the time it takes +/// for the child widget to be initially displayed on the screen. This method +/// allows a more accurate measurement than what the default TTID implementation +/// provides. The TTID measurement begins when the route to the widget is pushed and ends +/// when `addPostFramecallback` is triggered. +/// +/// Wrap the widget you want to measure with [SentryDisplayWidget], and ensure that you +/// have set up Sentry's routing instrumentation according to the Sentry documentation. +/// +/// ```dart +/// SentryDisplayWidget( +/// child: MyWidget(), +/// ) +/// ``` +/// +/// Make sure to configure Sentry's routing instrumentation in your app by following +/// the guidelines provided in Sentry's documentation for Flutter integrations: +/// https://docs.sentry.io/platforms/flutter/integrations/routing-instrumentation/ +/// +/// See also: +/// - [Sentry's documentation on Flutter integrations](https://docs.sentry.io/platforms/flutter/) +/// for more information on how to integrate Sentry into your Flutter application. +class SentryDisplayWidget extends StatefulWidget { + final Widget child; + final FrameCallbackHandler _frameCallbackHandler; + + SentryDisplayWidget({ + super.key, + required this.child, + @visibleForTesting FrameCallbackHandler? frameCallbackHandler, + }) : _frameCallbackHandler = + frameCallbackHandler ?? DefaultFrameCallbackHandler(); + + @override + _SentryDisplayWidgetState createState() => _SentryDisplayWidgetState(); +} + +class _SentryDisplayWidgetState extends State { + @override + void initState() { + super.initState(); + TimeToInitialDisplayTracker().markAsManual(); + + widget._frameCallbackHandler.addPostFrameCallback((_) { + TimeToInitialDisplayTracker().completeTracking(); + }); + } + + @override + Widget build(BuildContext context) { + return widget.child; + } +} diff --git a/flutter/lib/src/navigation/sentry_navigator_observer.dart b/flutter/lib/src/navigation/sentry_navigator_observer.dart index 30beaa75bc..5eb7884006 100644 --- a/flutter/lib/src/navigation/sentry_navigator_observer.dart +++ b/flutter/lib/src/navigation/sentry_navigator_observer.dart @@ -1,5 +1,12 @@ +// ignore_for_file: invalid_use_of_internal_member + +import 'dart:async'; + +import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; import 'package:meta/meta.dart'; +import '../integrations/integrations.dart'; +import 'time_to_display_tracker.dart'; import '../../sentry_flutter.dart'; import '../event_processor/flutter_enricher_event_processor.dart'; @@ -19,6 +26,8 @@ typedef AdditionalInfoExtractor = Map? Function( /// This is a navigation observer to record navigational breadcrumbs. /// For now it only records navigation events and no gestures. /// +/// It also records Time to Initial Display (TTID). +/// /// [Route]s can always be null and their [Route.settings] can also always be null. /// For example, if the application starts, there is no previous route. /// The [RouteSettings] is null if a developer has not specified any @@ -44,22 +53,21 @@ typedef AdditionalInfoExtractor = Map? Function( /// ) /// ``` /// -/// See the constructor docs for the argument documentation. +/// The option [enableAutoTransactions] is enabled by default. For every new +/// route a transaction is started. It's automatically finished after +/// [autoFinishAfter] duration or when all child spans are finished, +/// if those happen to take longer. The transaction will be set to [Scope.span] +/// if the latter is empty. +/// +/// Enabling the [setRouteNameAsTransaction] option overrides the current +/// [Scope.transaction] which will also override the name of the current +/// [Scope.span]. So be careful when this is used together with performance +/// monitoring. /// /// See also: /// - [RouteObserver](https://api.flutter.dev/flutter/widgets/RouteObserver-class.html) /// - [Navigating with arguments](https://flutter.dev/docs/cookbook/navigation/navigate-with-arguments) class SentryNavigatorObserver extends RouteObserver> { - /// The option [enableAutoTransactions] is enabled by default. - /// For every new route a transaction is started. It's automatically finished - /// after [autoFinishAfter] duration or when all child spans are - /// finished, if those happen to take longer. - /// The transaction will be set to [Scope.span] if the latter is empty. - /// - /// Enabling the [setRouteNameAsTransaction] option overrides the - /// current [Scope.transaction] which will also override the name of the current - /// [Scope.span]. So be careful when this is used together with performance - /// monitoring. SentryNavigatorObserver({ Hub? hub, bool enableAutoTransactions = true, @@ -67,15 +75,16 @@ class SentryNavigatorObserver extends RouteObserver> { bool setRouteNameAsTransaction = false, RouteNameExtractor? routeNameExtractor, AdditionalInfoExtractor? additionalInfoProvider, + @visibleForTesting TimeToDisplayTracker? timeToDisplayTracker, }) : _hub = hub ?? HubAdapter(), _enableAutoTransactions = enableAutoTransactions, _autoFinishAfter = autoFinishAfter, _setRouteNameAsTransaction = setRouteNameAsTransaction, _routeNameExtractor = routeNameExtractor, _additionalInfoProvider = additionalInfoProvider, - _native = SentryFlutter.native { + _native = SentryFlutter.native, + _timeToDisplayTracker = timeToDisplayTracker ?? TimeToDisplayTracker() { if (enableAutoTransactions) { - // ignore: invalid_use_of_internal_member _hub.options.sdk.addIntegration('UINavigationTracing'); } } @@ -87,6 +96,7 @@ class SentryNavigatorObserver extends RouteObserver> { final RouteNameExtractor? _routeNameExtractor; final AdditionalInfoExtractor? _additionalInfoProvider; final SentryNative? _native; + final TimeToDisplayTracker? _timeToDisplayTracker; ISentrySpan? _transaction; @@ -95,6 +105,12 @@ class SentryNavigatorObserver extends RouteObserver> { @internal static String? get currentRouteName => _currentRouteName; + Completer? _completedDisplayTracking; + + // Since didPush does not have a future, we can keep track of when the display tracking has finished + @visibleForTesting + Completer? get completedDisplayTracking => _completedDisplayTracking; + @override void didPush(Route route, Route? previousRoute) { super.didPush(route, previousRoute); @@ -108,8 +124,8 @@ class SentryNavigatorObserver extends RouteObserver> { to: route.settings, ); - _finishTransaction(); - _startTransaction(route); + _finishTimeToDisplayTracking(); + _startTimeToDisplayTracking(route); } @override @@ -139,8 +155,7 @@ class SentryNavigatorObserver extends RouteObserver> { to: previousRoute?.settings, ); - _finishTransaction(); - _startTransaction(previousRoute); + _finishTimeToDisplayTracking(); } void _addBreadcrumb({ @@ -152,7 +167,6 @@ class SentryNavigatorObserver extends RouteObserver> { navigationType: type, from: _routeNameExtractor?.call(from) ?? from, to: _routeNameExtractor?.call(to) ?? to, - // ignore: invalid_use_of_internal_member timestamp: _hub.options.clock(), data: _additionalInfoProvider?.call(from, to), )); @@ -179,11 +193,8 @@ class SentryNavigatorObserver extends RouteObserver> { } } - Future _startTransaction(Route? route) async { - if (!_enableAutoTransactions) { - return; - } - + Future _startTransaction( + Route? route, DateTime startTimestamp) async { String? name = _getRouteName(route); final arguments = route?.settings.arguments; @@ -196,14 +207,14 @@ class SentryNavigatorObserver extends RouteObserver> { } final transactionContext = SentryTransactionContext( name, - 'navigation', + SentrySpanOperations.uiLoad, transactionNameSource: SentryTransactionNameSource.component, - // ignore: invalid_use_of_internal_member origin: SentryTraceOrigins.autoNavigationRouteObserver, ); _transaction = _hub.startTransactionWithContext( transactionContext, + startTimestamp: startTimestamp, waitForChildren: true, autoFinishAfter: _autoFinishAfter, trimEnd: true, @@ -242,7 +253,9 @@ class SentryNavigatorObserver extends RouteObserver> { await _native?.beginNativeFramesCollection(); } - Future _finishTransaction() async { + Future _finishTimeToDisplayTracking() async { + _timeToDisplayTracker?.clear(); + final transaction = _transaction; _transaction = null; if (transaction == null || transaction.finished) { @@ -251,6 +264,47 @@ class SentryNavigatorObserver extends RouteObserver> { transaction.status ??= SpanStatus.ok(); await transaction.finish(); } + + Future _startTimeToDisplayTracking(Route? route) async { + if (!_enableAutoTransactions) { + return; + } + + _completedDisplayTracking = Completer(); + String? routeName = _currentRouteName; + if (routeName == null) return; + + DateTime startTimestamp = _hub.options.clock(); + DateTime? endTimestamp; + + if (routeName == '/') { + final appStartInfo = await NativeAppStartIntegration.getAppStartInfo(); + if (appStartInfo == null) { + return; + } + + startTimestamp = appStartInfo.start; + endTimestamp = appStartInfo.end; + } + + await _startTransaction(route, startTimestamp); + final transaction = _transaction; + if (transaction == null) { + return; + } + + if (routeName == '/' && endTimestamp != null) { + await _timeToDisplayTracker?.trackAppStartTTD(transaction, + startTimestamp: startTimestamp, endTimestamp: endTimestamp); + } else { + await _timeToDisplayTracker?.trackRegularRouteTTD(transaction, + startTimestamp: startTimestamp); + } + + // Mark the tracking as completed and clear any temporary state. + _completedDisplayTracking?.complete(); + _timeToDisplayTracker?.clear(); + } } /// This class makes it easier to record breadcrumbs for events of Flutters diff --git a/flutter/lib/src/navigation/time_to_display_tracker.dart b/flutter/lib/src/navigation/time_to_display_tracker.dart new file mode 100644 index 0000000000..713bc16ff4 --- /dev/null +++ b/flutter/lib/src/navigation/time_to_display_tracker.dart @@ -0,0 +1,34 @@ +// ignore_for_file: invalid_use_of_internal_member + +import 'dart:async'; + +import 'package:meta/meta.dart'; + +import '../../sentry_flutter.dart'; +import 'time_to_initial_display_tracker.dart'; + +@internal +class TimeToDisplayTracker { + final TimeToInitialDisplayTracker _ttidTracker; + + TimeToDisplayTracker({ + TimeToInitialDisplayTracker? ttidTracker, + }) : _ttidTracker = ttidTracker ?? TimeToInitialDisplayTracker(); + + Future trackAppStartTTD(ISentrySpan transaction, + {required DateTime startTimestamp, + required DateTime endTimestamp}) async { + // We start and immediately finish the spans since we cannot mutate the history of spans. + await _ttidTracker.trackAppStart(transaction, + startTimestamp: startTimestamp, endTimestamp: endTimestamp); + } + + Future trackRegularRouteTTD(ISentrySpan transaction, + {required DateTime startTimestamp}) async { + await _ttidTracker.trackRegularRoute(transaction, startTimestamp); + } + + void clear() { + _ttidTracker.clear(); + } +} diff --git a/flutter/lib/src/navigation/time_to_initial_display_tracker.dart b/flutter/lib/src/navigation/time_to_initial_display_tracker.dart new file mode 100644 index 0000000000..ce2f7b9e9c --- /dev/null +++ b/flutter/lib/src/navigation/time_to_initial_display_tracker.dart @@ -0,0 +1,136 @@ +// ignore_for_file: invalid_use_of_internal_member + +import 'dart:async'; + +import 'package:meta/meta.dart'; + +// ignore: implementation_imports +import 'package:sentry/src/sentry_tracer.dart'; + +import '../../sentry_flutter.dart'; +import '../frame_callback_handler.dart'; + +@internal +class TimeToInitialDisplayTracker { + static final TimeToInitialDisplayTracker _instance = + TimeToInitialDisplayTracker._(); + + factory TimeToInitialDisplayTracker( + {FrameCallbackHandler? frameCallbackHandler}) { + if (frameCallbackHandler != null) { + _instance._frameCallbackHandler = frameCallbackHandler; + } + return _instance; + } + + TimeToInitialDisplayTracker._(); + + FrameCallbackHandler _frameCallbackHandler = DefaultFrameCallbackHandler(); + bool _isManual = false; + Completer? _trackingCompleter; + DateTime? _endTimestamp; + final Duration _determineEndtimeTimeout = Duration(seconds: 5); + + /// This endTimestamp is needed in the [TimeToFullDisplayTracker] class + @internal + DateTime? get endTimestamp => _endTimestamp; + + Future trackRegularRoute( + ISentrySpan transaction, + DateTime startTimestamp, + ) async { + await _trackTimeToInitialDisplay( + transaction: transaction, + startTimestamp: startTimestamp, + ); + } + + Future trackAppStart(ISentrySpan transaction, + {required DateTime startTimestamp, + required DateTime endTimestamp}) async { + await _trackTimeToInitialDisplay( + transaction: transaction, + startTimestamp: startTimestamp, + endTimestamp: endTimestamp, + origin: SentryTraceOrigins.autoUiTimeToDisplay, + ); + + // Store the end timestamp for potential use by TTFD tracking + _endTimestamp = endTimestamp; + } + + Future _trackTimeToInitialDisplay({ + required ISentrySpan transaction, + required DateTime startTimestamp, + DateTime? endTimestamp, + String? origin, + }) async { + final _endTimestamp = endTimestamp ?? await determineEndTime(); + if (_endTimestamp == null) return; + + final tracer = transaction as SentryTracer; + + final ttidSpan = transaction.startChild( + SentrySpanOperations.uiTimeToInitialDisplay, + description: '${tracer.name} initial display', + startTimestamp: startTimestamp, + ); + + ttidSpan.origin = origin ?? + (_isManual + ? SentryTraceOrigins.manualUiTimeToDisplay + : SentryTraceOrigins.autoUiTimeToDisplay); + + final duration = Duration( + milliseconds: _endTimestamp.difference(startTimestamp).inMilliseconds); + final ttidMeasurement = SentryMeasurement.timeToInitialDisplay(duration); + + transaction.setMeasurement(ttidMeasurement.name, ttidMeasurement.value, + unit: ttidMeasurement.unit); + await ttidSpan.finish(endTimestamp: _endTimestamp); + } + + Future? determineEndTime() { + _trackingCompleter = Completer(); + final future = _trackingCompleter?.future.timeout( + _determineEndtimeTimeout, + onTimeout: () { + return Future.value(null); + }, + ); + + // If we already know it's manual we can return the future immediately + if (_isManual) { + return future; + } + + // Schedules a check at the end of the frame to determine if the tracking + // should be completed immediately (approximation mode) or deferred (manual mode). + _frameCallbackHandler.addPostFrameCallback((_) { + if (!_isManual) { + completeTracking(); + } + }); + + return future; + } + + void markAsManual() { + _isManual = true; + } + + void completeTracking() { + if (_trackingCompleter != null && !_trackingCompleter!.isCompleted) { + final endTimestamp = DateTime.now(); + _endTimestamp = endTimestamp; + _trackingCompleter?.complete(endTimestamp); + } + } + + void clear() { + _isManual = false; + _trackingCompleter = null; + // We can't clear the ttid end time stamp here, because it might be needed + // in the [TimeToFullDisplayTracker] class + } +} diff --git a/flutter/test/fake_frame_callback_handler.dart b/flutter/test/fake_frame_callback_handler.dart index 103045d0e2..0dc968f22c 100644 --- a/flutter/test/fake_frame_callback_handler.dart +++ b/flutter/test/fake_frame_callback_handler.dart @@ -4,16 +4,15 @@ import 'package:sentry_flutter/src/frame_callback_handler.dart'; class FakeFrameCallbackHandler implements FrameCallbackHandler { FrameCallback? storedCallback; - final Duration _finishAfterDuration; + final Duration finishAfterDuration; FakeFrameCallbackHandler( - {Duration finishAfterDuration = const Duration(milliseconds: 500)}) - : _finishAfterDuration = finishAfterDuration; + {this.finishAfterDuration = const Duration(milliseconds: 50)}); @override void addPostFrameCallback(FrameCallback callback) async { // ignore: inference_failure_on_instance_creation - await Future.delayed(_finishAfterDuration); + await Future.delayed(finishAfterDuration); callback(Duration.zero); } } diff --git a/flutter/test/navigation/sentry_display_widget_test.dart b/flutter/test/navigation/sentry_display_widget_test.dart new file mode 100644 index 0000000000..6fb61c5b8f --- /dev/null +++ b/flutter/test/navigation/sentry_display_widget_test.dart @@ -0,0 +1,122 @@ +// ignore_for_file: invalid_use_of_internal_member + +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:sentry_flutter/sentry_flutter.dart'; +import 'package:sentry/src/sentry_tracer.dart'; +import 'package:sentry_flutter/src/integrations/integrations.dart'; + +import '../fake_frame_callback_handler.dart'; +import '../mocks.dart'; + +void main() { + PageRoute route(RouteSettings? settings) => PageRouteBuilder( + pageBuilder: (_, __, ___) => Container(), + settings: settings, + ); + + late Fixture fixture; + + setUp(() { + fixture = Fixture(); + }); + + testWidgets('SentryDisplayWidget reports manual ttid span after didPush', + (WidgetTester tester) async { + final currentRoute = route(RouteSettings(name: 'Current Route')); + + await tester.runAsync(() async { + fixture.navigatorObserver.didPush(currentRoute, null); + await tester.pumpWidget(fixture.getSut()); + await fixture.navigatorObserver.completedDisplayTracking?.future; + }); + + final tracer = fixture.hub.getSpan() as SentryTracer; + final spans = tracer.children.where((element) => + element.context.operation == + SentrySpanOperations.uiTimeToInitialDisplay); + + expect(spans, hasLength(1)); + + final ttidSpan = spans.first; + expect(ttidSpan.context.operation, + SentrySpanOperations.uiTimeToInitialDisplay); + expect(ttidSpan.finished, isTrue); + expect(ttidSpan.context.description, 'Current Route initial display'); + expect(ttidSpan.origin, SentryTraceOrigins.manualUiTimeToDisplay); + final ttidSpanDuration = + ttidSpan.endTimestamp!.difference(ttidSpan.startTimestamp); + + expect(tracer.measurements, hasLength(1)); + final measurement = tracer.measurements['time_to_initial_display']; + expect(measurement, isNotNull); + expect(measurement?.unit, DurationSentryMeasurementUnit.milliSecond); + expect(measurement?.value, ttidSpanDuration.inMilliseconds); + }); + + testWidgets('SentryDisplayWidget is ignored for app starts', + (WidgetTester tester) async { + final currentRoute = route(RouteSettings(name: '/')); + final appStartInfo = AppStartInfo( + AppStartType.cold, + start: getUtcDateTime().add(Duration(seconds: 1)), + end: getUtcDateTime().add(Duration(seconds: 2)), + ); + NativeAppStartIntegration.setAppStartInfo(appStartInfo); + + await tester.runAsync(() async { + fixture.navigatorObserver.didPush(currentRoute, null); + await tester.pumpWidget(fixture.getSut()); + await fixture.navigatorObserver.completedDisplayTracking?.future; + }); + + final tracer = fixture.hub.getSpan() as SentryTracer; + final spans = tracer.children.where((element) => + element.context.operation == + SentrySpanOperations.uiTimeToInitialDisplay); + + expect(spans, hasLength(1)); + + final ttidSpan = spans.first; + expect(ttidSpan.context.operation, + SentrySpanOperations.uiTimeToInitialDisplay); + expect(ttidSpan.finished, isTrue); + expect(ttidSpan.context.description, 'root ("/") initial display'); + expect(ttidSpan.origin, SentryTraceOrigins.autoUiTimeToDisplay); + + expect(ttidSpan.startTimestamp, appStartInfo.start); + expect(ttidSpan.endTimestamp, appStartInfo.end); + final ttidSpanDuration = + ttidSpan.endTimestamp!.difference(ttidSpan.startTimestamp); + + expect(tracer.measurements, hasLength(1)); + final measurement = tracer.measurements['time_to_initial_display']; + expect(measurement, isNotNull); + expect(measurement?.value, appStartInfo.duration.inMilliseconds); + expect(measurement?.value, ttidSpanDuration.inMilliseconds); + expect(measurement?.unit, DurationSentryMeasurementUnit.milliSecond); + }); +} + +class Fixture { + final Hub hub = + Hub(SentryFlutterOptions(dsn: fakeDsn)..tracesSampleRate = 1.0); + late final SentryNavigatorObserver navigatorObserver; + final fakeFrameCallbackHandler = FakeFrameCallbackHandler(); + + Fixture() { + SentryFlutter.native = TestMockSentryNative(); + navigatorObserver = SentryNavigatorObserver(hub: hub); + } + + MaterialApp getSut() { + return MaterialApp( + home: SentryDisplayWidget( + frameCallbackHandler: FakeFrameCallbackHandler( + finishAfterDuration: Duration(milliseconds: 50), + ), + child: Text('my text'), + ), + ); + } +} diff --git a/flutter/test/navigation/time_to_display_tracker_test.dart b/flutter/test/navigation/time_to_display_tracker_test.dart new file mode 100644 index 0000000000..942f9ccb35 --- /dev/null +++ b/flutter/test/navigation/time_to_display_tracker_test.dart @@ -0,0 +1,186 @@ +// ignore_for_file: invalid_use_of_internal_member +// ignore_for_file: inference_failure_on_instance_creation + +import 'package:flutter_test/flutter_test.dart'; +import 'package:sentry_flutter/sentry_flutter.dart'; +import 'package:sentry_flutter/src/frame_callback_handler.dart'; +import 'package:sentry_flutter/src/navigation/time_to_display_tracker.dart'; +import 'package:sentry/src/sentry_tracer.dart'; +import 'package:sentry_flutter/src/navigation/time_to_initial_display_tracker.dart'; + +import '../fake_frame_callback_handler.dart'; +import '../mocks.dart'; + +void main() { + late Fixture fixture; + + setUp(() { + TestWidgetsFlutterBinding.ensureInitialized(); + fixture = Fixture(); + }); + + tearDown(() { + fixture.ttidTracker?.clear(); + }); + + group('time to initial display', () { + group('in root screen app start route', () { + test('matches startTimestamp of transaction', () async { + final sut = fixture.getSut(); + + final transaction = fixture.getTransaction(name: '/') as SentryTracer; + await sut.trackRegularRouteTTD(transaction, + startTimestamp: fixture.startTimestamp); + + final ttidSpan = transaction.children + .where((element) => + element.context.operation == + SentrySpanOperations.uiTimeToInitialDisplay) + .first; + expect(transaction, isNotNull); + expect(transaction.context.operation, SentrySpanOperations.uiLoad); + expect(transaction.startTimestamp, ttidSpan.startTimestamp); + }); + + test('finishes ttid span', () async { + SentryFlutter.native = TestMockSentryNative(); + final sut = fixture.getSut(); + final endTimestamp = + fixture.startTimestamp.add(const Duration(milliseconds: 10)); + + final transaction = fixture.getTransaction(name: '/') as SentryTracer; + await sut.trackAppStartTTD(transaction, + startTimestamp: fixture.startTimestamp, endTimestamp: endTimestamp); + + final ttidSpan = transaction.children + .where((element) => + element.context.operation == + SentrySpanOperations.uiTimeToInitialDisplay) + .first; + expect(ttidSpan.context.operation, + SentrySpanOperations.uiTimeToInitialDisplay); + expect(ttidSpan.finished, isTrue); + expect(ttidSpan.origin, SentryTraceOrigins.autoUiTimeToDisplay); + }); + }); + + group('in regular routes', () { + test('matches startTimestamp of transaction', () async { + final sut = fixture.getSut(); + + final transaction = fixture.getTransaction() as SentryTracer; + await sut.trackRegularRouteTTD(transaction, + startTimestamp: fixture.startTimestamp); + + final ttidSpan = transaction.children + .where((element) => + element.context.operation == + SentrySpanOperations.uiTimeToInitialDisplay) + .first; + expect(transaction, isNotNull); + expect(transaction.context.operation, SentrySpanOperations.uiLoad); + expect(transaction.startTimestamp, ttidSpan.startTimestamp); + }); + + group('with approximation strategy', () { + test('finishes ttid span', () async { + final sut = fixture.getSut(); + + final transaction = fixture.getTransaction() as SentryTracer; + await sut.trackRegularRouteTTD(transaction, + startTimestamp: fixture.startTimestamp); + + final ttidSpan = transaction.children + .where((element) => + element.context.operation == + SentrySpanOperations.uiTimeToInitialDisplay) + .first; + expect(ttidSpan.context.operation, + SentrySpanOperations.uiTimeToInitialDisplay); + expect(ttidSpan.finished, isTrue); + expect(ttidSpan.origin, SentryTraceOrigins.autoUiTimeToDisplay); + }); + + test('completes with timeout when not completing the tracking', + () async { + final sut = fixture.getSut(triggerApproximationTimeout: true); + + final transaction = fixture.getTransaction() as SentryTracer; + await sut.trackRegularRouteTTD(transaction, + startTimestamp: fixture.startTimestamp); + }); + }); + + group('with manual strategy', () { + test('finishes ttid span', () async { + final sut = fixture.getSut(); + + Future.delayed(const Duration(milliseconds: 1), () { + fixture.ttidTracker?.markAsManual(); + fixture.ttidTracker?.completeTracking(); + }); + final transaction = fixture.getTransaction() as SentryTracer; + await sut.trackRegularRouteTTD(transaction, + startTimestamp: fixture.startTimestamp); + + final ttidSpan = transaction.children + .where((element) => + element.context.operation == + SentrySpanOperations.uiTimeToInitialDisplay) + .first; + expect(ttidSpan, isNotNull); + expect(ttidSpan.finished, isTrue); + expect(ttidSpan.origin, SentryTraceOrigins.manualUiTimeToDisplay); + }); + + test('completes with timeout when not completing the tracking', + () async { + final sut = fixture.getSut(); + + fixture.ttidTracker?.markAsManual(); + // Not calling completeTracking() triggers the manual timeout + + final transaction = fixture.getTransaction() as SentryTracer; + await sut.trackRegularRouteTTD(transaction, + startTimestamp: fixture.startTimestamp); + }); + }); + }); + }); + + test('screen load tracking creates ui.load transaction', () async { + final sut = fixture.getSut(); + + final transaction = fixture.getTransaction() as SentryTracer; + await sut.trackRegularRouteTTD(transaction, + startTimestamp: fixture.startTimestamp); + + expect(transaction, isNotNull); + expect(transaction.context.operation, SentrySpanOperations.uiLoad); + }); +} + +class Fixture { + final startTimestamp = getUtcDateTime(); + final options = SentryFlutterOptions() + ..dsn = fakeDsn + ..tracesSampleRate = 1.0; + + late final hub = Hub(options); + TimeToInitialDisplayTracker? ttidTracker; + + ISentrySpan getTransaction({String? name = "Current route"}) { + return hub.startTransaction(name!, 'ui.load', + startTimestamp: startTimestamp); + } + + TimeToDisplayTracker getSut({bool triggerApproximationTimeout = false}) { + ttidTracker = TimeToInitialDisplayTracker( + frameCallbackHandler: triggerApproximationTimeout + ? DefaultFrameCallbackHandler() + : FakeFrameCallbackHandler()); + return TimeToDisplayTracker( + ttidTracker: ttidTracker, + ); + } +} diff --git a/flutter/test/navigation/time_to_initial_display_tracker_test.dart b/flutter/test/navigation/time_to_initial_display_tracker_test.dart new file mode 100644 index 0000000000..6e55029572 --- /dev/null +++ b/flutter/test/navigation/time_to_initial_display_tracker_test.dart @@ -0,0 +1,201 @@ +// ignore_for_file: invalid_use_of_internal_member + +import 'package:flutter_test/flutter_test.dart'; +import 'package:sentry_flutter/sentry_flutter.dart'; +import 'package:sentry_flutter/src/frame_callback_handler.dart'; +import 'package:sentry_flutter/src/navigation/time_to_initial_display_tracker.dart'; + +import '../fake_frame_callback_handler.dart'; +import '../mocks.dart'; +import 'package:sentry/src/sentry_tracer.dart'; + +void main() { + late Fixture fixture; + late TimeToInitialDisplayTracker sut; + + setUp(() { + fixture = Fixture(); + sut = fixture.getSut(); + }); + + tearDown(() { + sut.clear(); + }); + + group('app start', () { + test('tracking creates and finishes ttid span with correct measurements', + () async { + final endTimestamp = + fixture.startTimestamp.add(const Duration(milliseconds: 10)); + + final transaction = + fixture.getTransaction(name: 'root ("/")') as SentryTracer; + await sut.trackAppStart(transaction, + startTimestamp: fixture.startTimestamp, endTimestamp: endTimestamp); + + final children = transaction.children; + expect(children, hasLength(1)); + + final ttidSpan = children.first; + expect(ttidSpan.context.operation, + SentrySpanOperations.uiTimeToInitialDisplay); + expect(ttidSpan.finished, isTrue); + expect(ttidSpan.context.description, 'root ("/") initial display'); + expect(ttidSpan.origin, SentryTraceOrigins.autoUiTimeToDisplay); + expect(ttidSpan.startTimestamp, fixture.startTimestamp); + expect(ttidSpan.endTimestamp, endTimestamp); + + final ttidMeasurement = + transaction.measurements['time_to_initial_display']; + expect(ttidMeasurement, isNotNull); + expect(ttidMeasurement?.unit, DurationSentryMeasurementUnit.milliSecond); + expect( + ttidMeasurement?.value, + ttidSpan.endTimestamp! + .difference(ttidSpan.startTimestamp) + .inMilliseconds); + }); + }); + + group('regular route', () { + test( + 'approximation tracking creates and finishes ttid span with correct measurements', + () async { + final transaction = fixture.getTransaction() as SentryTracer; + await sut.trackRegularRoute(transaction, fixture.startTimestamp); + + final children = transaction.children; + expect(children, hasLength(1)); + + final ttidSpan = children.first; + expect(ttidSpan.context.operation, + SentrySpanOperations.uiTimeToInitialDisplay); + expect(ttidSpan.finished, isTrue); + expect(ttidSpan.context.description, 'Regular route initial display'); + expect(ttidSpan.origin, SentryTraceOrigins.autoUiTimeToDisplay); + + final ttidMeasurement = + transaction.measurements['time_to_initial_display']; + expect(ttidMeasurement, isNotNull); + expect(ttidMeasurement?.unit, DurationSentryMeasurementUnit.milliSecond); + expect(ttidMeasurement?.value, + greaterThanOrEqualTo(fixture.finishFrameDuration.inMilliseconds)); + expect( + ttidMeasurement?.value, + ttidSpan.endTimestamp! + .difference(ttidSpan.startTimestamp) + .inMilliseconds); + }); + + test( + 'manual tracking creates and finishes ttid span with correct measurements', + () async { + sut.markAsManual(); + Future.delayed(fixture.finishFrameDuration, () { + sut.completeTracking(); + }); + + final transaction = fixture.getTransaction() as SentryTracer; + await sut.trackRegularRoute(transaction, fixture.startTimestamp); + + final children = transaction.children; + expect(children, hasLength(1)); + + final ttidSpan = children.first; + expect(ttidSpan.context.operation, + SentrySpanOperations.uiTimeToInitialDisplay); + expect(ttidSpan.finished, isTrue); + expect(ttidSpan.context.description, 'Regular route initial display'); + expect(ttidSpan.origin, SentryTraceOrigins.manualUiTimeToDisplay); + final ttidMeasurement = + transaction.measurements['time_to_initial_display']; + expect(ttidMeasurement, isNotNull); + expect(ttidMeasurement?.unit, DurationSentryMeasurementUnit.milliSecond); + expect(ttidMeasurement?.value, + greaterThanOrEqualTo(fixture.finishFrameDuration.inMilliseconds)); + expect( + ttidMeasurement?.value, + ttidSpan.endTimestamp! + .difference(ttidSpan.startTimestamp) + .inMilliseconds); + }); + }); + + group('determineEndtime', () { + test('can complete as null in approximation mode with timeout', () async { + final futureEndTime = await fixture + .getSut(triggerApproximationTimeout: true) + .determineEndTime(); + + expect(futureEndTime, null); + }); + + test('can complete as null in manual mode with timeout', () async { + final sut = fixture.getSut(); + sut.markAsManual(); + // Not calling completeTracking() triggers the manual timeout + + final futureEndTime = await sut.determineEndTime(); + + expect(futureEndTime, null); + }); + + test('can complete automatically in approximation mode', () async { + final futureEndTime = await sut.determineEndTime(); + + expect(futureEndTime, isNotNull); + }); + + test('can complete manually in manual mode', () async { + sut.markAsManual(); + Future.delayed(Duration(milliseconds: 1), () { + sut.completeTracking(); + }); + final futureEndTime = await sut.determineEndTime(); + + expect(futureEndTime, isNotNull); + }); + + test('returns the correct approximation end time', () async { + final endTme = await sut.determineEndTime(); + + expect(endTme?.difference(fixture.startTimestamp).inSeconds, + fixture.finishFrameDuration.inSeconds); + }); + + test('returns the correct manual end time', () async { + sut.markAsManual(); + Future.delayed(fixture.finishFrameDuration, () { + sut.completeTracking(); + }); + + final endTime = await sut.determineEndTime(); + + expect(endTime?.difference(fixture.startTimestamp).inSeconds, + fixture.finishFrameDuration.inSeconds); + }); + }); +} + +class Fixture { + final startTimestamp = getUtcDateTime(); + final hub = Hub(SentryFlutterOptions(dsn: fakeDsn)..tracesSampleRate = 1.0); + late final fakeFrameCallbackHandler = FakeFrameCallbackHandler(); + + ISentrySpan getTransaction({String? name = "Regular route"}) { + return hub.startTransaction(name!, 'ui.load', + bindToScope: true, startTimestamp: startTimestamp); + } + + /// The time it takes until a fake frame has been triggered + Duration get finishFrameDuration => + fakeFrameCallbackHandler.finishAfterDuration; + + TimeToInitialDisplayTracker getSut( + {bool triggerApproximationTimeout = false}) { + return TimeToInitialDisplayTracker( + frameCallbackHandler: triggerApproximationTimeout + ? DefaultFrameCallbackHandler() + : FakeFrameCallbackHandler()); + } +} diff --git a/flutter/test/sentry_navigator_observer_test.dart b/flutter/test/sentry_navigator_observer_test.dart index aca9646c0b..5a7528d904 100644 --- a/flutter/test/sentry_navigator_observer_test.dart +++ b/flutter/test/sentry_navigator_observer_test.dart @@ -5,9 +5,13 @@ import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/mockito.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; +import 'package:sentry_flutter/src/integrations/integrations.dart'; import 'package:sentry_flutter/src/native/sentry_native.dart'; import 'package:sentry/src/sentry_tracer.dart'; +import 'package:sentry_flutter/src/navigation/time_to_display_tracker.dart'; +import 'package:sentry_flutter/src/navigation/time_to_initial_display_tracker.dart'; +import 'fake_frame_callback_handler.dart'; import 'mocks.dart'; import 'mocks.mocks.dart'; @@ -30,10 +34,12 @@ void main() { customSamplingContext: anyNamed('customSamplingContext'), startTimestamp: anyNamed('startTimestamp'), )).thenReturn(thenReturnSpan); + when(mockHub.getSpan()).thenReturn(thenReturnSpan); } setUp(() { fixture = Fixture(); + WidgetsFlutterBinding.ensureInitialized(); }); group('NativeFrames', () { @@ -55,6 +61,12 @@ void main() { final tracer = getMockSentryTracer(); _whenAnyStart(mockHub, tracer); + when(tracer.startChild('ui.load.initial_display', + description: anyNamed('description'), + startTimestamp: anyNamed('startTimestamp'))) + .thenReturn(NoOpSentrySpan()); + when(tracer.finished).thenReturn(false); + when(tracer.status).thenReturn(SpanStatus.ok()); final sut = fixture.getSut(hub: mockHub); @@ -73,13 +85,14 @@ void main() { options.tracesSampleRate = 1; final hub = Hub(options); + mockNativeChannel = MockNativeChannel(); + SentryFlutter.native = + SentryNative(SentryFlutterOptions(dsn: fakeDsn), mockNativeChannel); + final nativeFrames = NativeFrames(3, 2, 1); mockNativeChannel.nativeFrames = nativeFrames; - final sut = fixture.getSut( - hub: hub, - autoFinishAfter: Duration(milliseconds: 50), - ); + final sut = fixture.getSut(hub: hub); sut.didPush(currentRoute, null); @@ -91,13 +104,15 @@ void main() { actualTransaction = scope.span as SentryTracer; }); - await Future.delayed(Duration(milliseconds: 500)); + await sut.completedDisplayTracking?.future; + + await Future.delayed(Duration(milliseconds: 1500)); expect(mockNativeChannel.numberOfEndNativeFramesCalls, 1); final measurements = actualTransaction?.measurements ?? {}; - expect(measurements.length, 3); + expect(measurements.length, 4); final expectedTotal = SentryMeasurement.totalFrames(3); final expectedSlow = SentryMeasurement.slowFrames(2); @@ -117,15 +132,21 @@ void main() { }); group('$SentryNavigatorObserver', () { - test('didPush starts transaction', () { + test('didPush starts transaction', () async { const name = 'Current Route'; final currentRoute = route(RouteSettings(name: name)); - const op = 'navigation'; + const op = 'ui.load'; final hub = _MockHub(); final span = getMockSentryTracer(name: name); when(span.context).thenReturn(SentrySpanContext(operation: op)); _whenAnyStart(hub, span); + when(span.finished).thenReturn(false); + when(span.status).thenReturn(SpanStatus.ok()); + when(span.startChild('ui.load.initial_display', + description: anyNamed('description'), + startTimestamp: anyNamed('startTimestamp'))) + .thenReturn(NoOpSentrySpan()); final sut = fixture.getSut( hub: hub, @@ -136,6 +157,7 @@ void main() { final context = verify(hub.startTransactionWithContext( captureAny, + startTimestamp: anyNamed('startTimestamp'), waitForChildren: true, autoFinishAfter: anyNamed('autoFinishAfter'), trimEnd: true, @@ -157,6 +179,7 @@ void main() { final span = NoOpSentrySpan(); _whenAnyStart(hub, span); + when(hub.getSpan()).thenReturn(null); final sut = fixture.getSut( hub: hub, @@ -167,6 +190,7 @@ void main() { verify(hub.startTransactionWithContext( any, + startTimestamp: anyNamed('startTimestamp'), waitForChildren: true, autoFinishAfter: Duration(seconds: 5), trimEnd: true, @@ -185,6 +209,8 @@ void main() { final hub = _MockHub(); final span = getMockSentryTracer(); when(span.context).thenReturn(SentrySpanContext(operation: 'op')); + when(span.finished).thenReturn(false); + when(span.status).thenReturn(SpanStatus.ok()); _whenAnyStart(hub, span); final sut = fixture.getSut(hub: hub); @@ -193,6 +219,7 @@ void main() { verifyNever(hub.startTransactionWithContext( any, + startTimestamp: anyNamed('startTimestamp'), waitForChildren: true, autoFinishAfter: anyNamed('autoFinishAfter'), trimEnd: true, @@ -211,6 +238,8 @@ void main() { final span = getMockSentryTracer(); when(span.context).thenReturn(SentrySpanContext(operation: 'op')); _whenAnyStart(hub, span); + when(span.finished).thenReturn(false); + when(span.status).thenReturn(SpanStatus.ok()); final sut = fixture.getSut(hub: hub, enableAutoTransactions: false); @@ -218,6 +247,7 @@ void main() { verifyNever(hub.startTransactionWithContext( any, + startTimestamp: anyNamed('startTimestamp'), waitForChildren: true, autoFinishAfter: anyNamed('autoFinishAfter'), trimEnd: true, @@ -237,6 +267,12 @@ void main() { final span = getMockSentryTracer(); when(span.context).thenReturn(SentrySpanContext(operation: 'op')); + when(span.finished).thenReturn(false); + when(span.status).thenReturn(SpanStatus.ok()); + when(span.startChild('ui.load.initial_display', + description: anyNamed('description'), + startTimestamp: anyNamed('startTimestamp'))) + .thenReturn(NoOpSentrySpan()); _whenAnyStart(hub, span); final sut = fixture.getSut(hub: hub); @@ -245,6 +281,7 @@ void main() { verify(hub.startTransactionWithContext( any, + startTimestamp: anyNamed('startTimestamp'), waitForChildren: true, autoFinishAfter: anyNamed('autoFinishAfter'), trimEnd: true, @@ -256,7 +293,7 @@ void main() { }); }); - test('didPush finishes previous transaction', () { + test('didPush finishes previous transaction', () async { final firstRoute = route(RouteSettings(name: 'First Route')); final secondRoute = route(RouteSettings(name: 'Second Route')); @@ -264,6 +301,11 @@ void main() { final span = getMockSentryTracer(finished: false); when(span.context).thenReturn(SentrySpanContext(operation: 'op')); when(span.status).thenReturn(null); + when(span.finished).thenReturn(false); + when(span.startChild('ui.load.initial_display', + description: anyNamed('description'), + startTimestamp: anyNamed('startTimestamp'))) + .thenReturn(NoOpSentrySpan()); _whenAnyStart(hub, span); final sut = fixture.getSut(hub: hub); @@ -282,6 +324,11 @@ void main() { final span = getMockSentryTracer(finished: false); when(span.context).thenReturn(SentrySpanContext(operation: 'op')); when(span.status).thenReturn(null); + when(span.finished).thenReturn(false); + when(span.startChild('ui.load.initial_display', + description: anyNamed('description'), + startTimestamp: anyNamed('startTimestamp'))) + .thenReturn(NoOpSentrySpan()); _whenAnyStart(hub, span); final sut = fixture.getSut(hub: hub); @@ -305,40 +352,13 @@ void main() { final sut = fixture.getSut(hub: hub); sut.didPush(currentRoute, null); + sut.didPop(currentRoute, null); sut.didPop(currentRoute, null); verify(span.finish()).called(1); }); - test('didPop re-starts previous', () { - final previousRoute = route(RouteSettings(name: 'Previous Route')); - final currentRoute = route(RouteSettings(name: 'Current Route')); - - final hub = _MockHub(); - final previousSpan = getMockSentryTracer(); - when(previousSpan.context).thenReturn(SentrySpanContext(operation: 'op')); - when(previousSpan.status).thenReturn(null); - - _whenAnyStart(hub, previousSpan); - - final sut = fixture.getSut(hub: hub); - - sut.didPop(currentRoute, previousRoute); - - verify(hub.startTransactionWithContext( - any, - waitForChildren: true, - autoFinishAfter: anyNamed('autoFinishAfter'), - trimEnd: true, - onFinish: anyNamed('onFinish'), - )); - - hub.configureScope((scope) { - expect(scope.span, previousSpan); - }); - }); - test('route arguments are set on transaction', () { final arguments = {'foo': 'bar'}; final currentRoute = route(RouteSettings( @@ -350,6 +370,11 @@ void main() { final span = getMockSentryTracer(); when(span.context).thenReturn(SentrySpanContext(operation: 'op')); when(span.status).thenReturn(null); + when(span.finished).thenReturn(false); + when(span.startChild('ui.load.initial_display', + description: anyNamed('description'), + startTimestamp: anyNamed('startTimestamp'))) + .thenReturn(NoOpSentrySpan()); _whenAnyStart(hub, span); final sut = fixture.getSut(hub: hub); @@ -359,21 +384,37 @@ void main() { verify(span.setData('route_settings_arguments', arguments)); }); - test('flutter root name is replaced', () { + test('flutter root name is replaced', () async { final rootRoute = route(RouteSettings(name: '/')); + NativeAppStartIntegration.setAppStartInfo( + AppStartInfo( + AppStartType.cold, + start: DateTime.now().add(const Duration(seconds: 1)), + end: DateTime.now().add(const Duration(seconds: 2)), + ), + ); final hub = _MockHub(); final span = getMockSentryTracer(name: '/'); when(span.context).thenReturn(SentrySpanContext(operation: 'op')); + when(span.finished).thenReturn(false); + when(span.status).thenReturn(SpanStatus.ok()); + when(span.startChild('ui.load.initial_display', + description: anyNamed('description'), + startTimestamp: anyNamed('startTimestamp'))) + .thenReturn(NoOpSentrySpan()); _whenAnyStart(hub, span); final sut = fixture.getSut(hub: hub); sut.didPush(rootRoute, null); + await Future.delayed(const Duration(milliseconds: 100)); + final context = verify(hub.startTransactionWithContext( captureAny, waitForChildren: true, + startTimestamp: anyNamed('startTimestamp'), autoFinishAfter: anyNamed('autoFinishAfter'), trimEnd: true, onFinish: anyNamed('onFinish'), @@ -394,6 +435,12 @@ void main() { final hub = _MockHub(); final span = getMockSentryTracer(name: name); when(span.context).thenReturn(SentrySpanContext(operation: op)); + when(span.finished).thenReturn(false); + when(span.status).thenReturn(SpanStatus.ok()); + when(span.startChild('ui.load.initial_display', + description: anyNamed('description'), + startTimestamp: anyNamed('startTimestamp'))) + .thenReturn(NoOpSentrySpan()); _whenAnyStart(hub, span); final sut = fixture.getSut( @@ -416,6 +463,12 @@ void main() { final hub = _MockHub(); final span = getMockSentryTracer(name: oldRouteName); when(span.context).thenReturn(SentrySpanContext(operation: op)); + when(span.finished).thenReturn(false); + when(span.status).thenReturn(SpanStatus.ok()); + when(span.startChild('ui.load.initial_display', + description: anyNamed('description'), + startTimestamp: anyNamed('startTimestamp'))) + .thenReturn(NoOpSentrySpan()); _whenAnyStart(hub, span); final sut = fixture.getSut( @@ -440,6 +493,11 @@ void main() { final span = getMockSentryTracer(name: oldRouteName); when(span.context).thenReturn(SentrySpanContext(operation: op)); when(span.status).thenReturn(null); + when(span.finished).thenReturn(false); + when(span.startChild('ui.load.initial_display', + description: anyNamed('description'), + startTimestamp: anyNamed('startTimestamp'))) + .thenReturn(NoOpSentrySpan()); _whenAnyStart(hub, span); final sut = fixture.getSut( @@ -659,6 +717,7 @@ void main() { final hub = _MockHub(); final observer = fixture.getSut(hub: hub); + when(hub.getSpan()).thenReturn(NoOpSentrySpan()); final to = route(); final previous = route(); @@ -818,11 +877,17 @@ class Fixture { SentryNavigatorObserver getSut({ required Hub hub, bool enableAutoTransactions = true, - Duration autoFinishAfter = const Duration(seconds: 3), + Duration autoFinishAfter = const Duration(seconds: 1), bool setRouteNameAsTransaction = false, RouteNameExtractor? routeNameExtractor, AdditionalInfoExtractor? additionalInfoProvider, }) { + final frameCallbackHandler = FakeFrameCallbackHandler(); + final timeToInitialDisplayTracker = + TimeToInitialDisplayTracker(frameCallbackHandler: frameCallbackHandler); + final timeToDisplayTracker = TimeToDisplayTracker( + ttidTracker: timeToInitialDisplayTracker, + ); return SentryNavigatorObserver( hub: hub, enableAutoTransactions: enableAutoTransactions, @@ -830,6 +895,7 @@ class Fixture { setRouteNameAsTransaction: setRouteNameAsTransaction, routeNameExtractor: routeNameExtractor, additionalInfoProvider: additionalInfoProvider, + timeToDisplayTracker: timeToDisplayTracker, ); } From 6078ddcf85799bf45a037f579fcaa919528483a1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 11 Mar 2024 12:36:22 +0100 Subject: [PATCH 107/237] chore: update flutter/scripts/update-android.sh to 7.6.0 (#1927) Co-authored-by: GitHub --- CHANGELOG.md | 8 ++++++++ flutter/android/build.gradle | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9886fd45c5..cea76a1ea1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## Unreleased + +### Dependencies + +- Bump Android SDK from v7.5.0 to v7.6.0 ([#1927](https://github.com/getsentry/sentry-dart/pull/1927)) + - [changelog](https://github.com/getsentry/sentry-java/blob/main/CHANGELOG.md#760) + - [diff](https://github.com/getsentry/sentry-java/compare/7.5.0...7.6.0) + ## 7.17.0 ### Fixes diff --git a/flutter/android/build.gradle b/flutter/android/build.gradle index 355d42709d..a2c0f7316e 100644 --- a/flutter/android/build.gradle +++ b/flutter/android/build.gradle @@ -60,7 +60,7 @@ android { } dependencies { - api 'io.sentry:sentry-android:7.5.0' + api 'io.sentry:sentry-android:7.6.0' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" // Required -- JUnit 4 framework From 42f6db49481030c388ae42060532e252255a2465 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Mar 2024 16:34:13 +0100 Subject: [PATCH 108/237] build(deps): bump axel-op/dart-package-analyzer (#1930) Bumps [axel-op/dart-package-analyzer](https://github.com/axel-op/dart-package-analyzer) from d9b13539ce28b8a2f85605379ce8670209d571e8 to 56afb7e6737bd2b7cee05382ae7f0e8111138080. - [Release notes](https://github.com/axel-op/dart-package-analyzer/releases) - [Commits](https://github.com/axel-op/dart-package-analyzer/compare/d9b13539ce28b8a2f85605379ce8670209d571e8...56afb7e6737bd2b7cee05382ae7f0e8111138080) --- updated-dependencies: - dependency-name: axel-op/dart-package-analyzer dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/analyze.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/analyze.yml b/.github/workflows/analyze.yml index 0120603921..683aac6c68 100644 --- a/.github/workflows/analyze.yml +++ b/.github/workflows/analyze.yml @@ -65,7 +65,7 @@ jobs: working-directory: ${{ inputs.package }} run: | sed -i.bak 's|sentry:.*|sentry:\n path: /github/workspace/dart|g' pubspec.yaml - - uses: axel-op/dart-package-analyzer@d9b13539ce28b8a2f85605379ce8670209d571e8 # pin@v3 + - uses: axel-op/dart-package-analyzer@56afb7e6737bd2b7cee05382ae7f0e8111138080 # pin@v3 id: analysis with: githubToken: ${{ secrets.GITHUB_TOKEN }} From 25659aa63f37656f579639edbf48722055324b9d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Mar 2024 21:31:26 +0100 Subject: [PATCH 109/237] build(deps): bump VeryGoodOpenSource/very_good_coverage (#1929) Bumps [VeryGoodOpenSource/very_good_coverage](https://github.com/verygoodopensource/very_good_coverage) from 2.2.0 to 3.0.0. - [Release notes](https://github.com/verygoodopensource/very_good_coverage/releases) - [Changelog](https://github.com/VeryGoodOpenSource/very_good_coverage/blob/main/CHANGELOG.md) - [Commits](https://github.com/verygoodopensource/very_good_coverage/compare/3b475421464c564c0714d92ce02742bd81fa9eda...c953fca3e24a915e111cc6f55f03f756dcb3964c) --- updated-dependencies: - dependency-name: VeryGoodOpenSource/very_good_coverage dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor --- .github/workflows/dart.yml | 2 +- .github/workflows/dio.yml | 2 +- .github/workflows/drift.yml | 2 +- .github/workflows/file.yml | 2 +- .github/workflows/flutter.yml | 2 +- .github/workflows/hive.yml | 2 +- .github/workflows/isar.yml | 2 +- .github/workflows/logging.yml | 2 +- .github/workflows/sqflite.yml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml index d0ffb5ebfe..6a26645df1 100644 --- a/.github/workflows/dart.yml +++ b/.github/workflows/dart.yml @@ -74,7 +74,7 @@ jobs: name: sentry files: ./dart/coverage/lcov.info - - uses: VeryGoodOpenSource/very_good_coverage@3b475421464c564c0714d92ce02742bd81fa9eda # pin@v2.2.0 + - uses: VeryGoodOpenSource/very_good_coverage@c953fca3e24a915e111cc6f55f03f756dcb3964c # pin@v3.0.0 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: path: "./dart/coverage/lcov.info" diff --git a/.github/workflows/dio.yml b/.github/workflows/dio.yml index 75b803f978..a7fd996216 100644 --- a/.github/workflows/dio.yml +++ b/.github/workflows/dio.yml @@ -58,7 +58,7 @@ jobs: name: sentry_dio files: ./dio/coverage/lcov.info - - uses: VeryGoodOpenSource/very_good_coverage@3b475421464c564c0714d92ce02742bd81fa9eda # pin@v2.2.0 + - uses: VeryGoodOpenSource/very_good_coverage@c953fca3e24a915e111cc6f55f03f756dcb3964c # pin@v3.0.0 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: path: "./dio/coverage/lcov.info" diff --git a/.github/workflows/drift.yml b/.github/workflows/drift.yml index 6e5ea56c07..dc8aff24f6 100644 --- a/.github/workflows/drift.yml +++ b/.github/workflows/drift.yml @@ -100,7 +100,7 @@ jobs: file: ./drift/coverage/lcov.info functionalities: "search" # remove after https://github.com/codecov/codecov-action/issues/600 - - uses: VeryGoodOpenSource/very_good_coverage@3b475421464c564c0714d92ce02742bd81fa9eda # pin@v2.2.0 + - uses: VeryGoodOpenSource/very_good_coverage@c953fca3e24a915e111cc6f55f03f756dcb3964c # pin@v3.0.0 if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' with: path: "./drift/coverage/lcov.info" diff --git a/.github/workflows/file.yml b/.github/workflows/file.yml index de2841ae20..56356cedc6 100644 --- a/.github/workflows/file.yml +++ b/.github/workflows/file.yml @@ -58,7 +58,7 @@ jobs: name: sentry_file files: ./file/coverage/lcov.info - - uses: VeryGoodOpenSource/very_good_coverage@3b475421464c564c0714d92ce02742bd81fa9eda # pin@v2.2.0 + - uses: VeryGoodOpenSource/very_good_coverage@c953fca3e24a915e111cc6f55f03f756dcb3964c # pin@v3.0.0 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: path: "./file/coverage/lcov.info" diff --git a/.github/workflows/flutter.yml b/.github/workflows/flutter.yml index ae358b3713..ef0ac1d8e1 100644 --- a/.github/workflows/flutter.yml +++ b/.github/workflows/flutter.yml @@ -119,7 +119,7 @@ jobs: file: ./flutter/coverage/lcov.info functionalities: "search" # remove after https://github.com/codecov/codecov-action/issues/600 - - uses: VeryGoodOpenSource/very_good_coverage@3b475421464c564c0714d92ce02742bd81fa9eda # pin@v2.2.0 + - uses: VeryGoodOpenSource/very_good_coverage@c953fca3e24a915e111cc6f55f03f756dcb3964c # pin@v3.0.0 if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' with: path: "./flutter/coverage/lcov.info" diff --git a/.github/workflows/hive.yml b/.github/workflows/hive.yml index 2f4fcebb60..4d2d177b31 100644 --- a/.github/workflows/hive.yml +++ b/.github/workflows/hive.yml @@ -57,7 +57,7 @@ jobs: name: sentry_hive files: ./hive/coverage/lcov.info - - uses: VeryGoodOpenSource/very_good_coverage@3b475421464c564c0714d92ce02742bd81fa9eda # pin@v2.2.0 + - uses: VeryGoodOpenSource/very_good_coverage@c953fca3e24a915e111cc6f55f03f756dcb3964c # pin@v3.0.0 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: path: "./hive/coverage/lcov.info" diff --git a/.github/workflows/isar.yml b/.github/workflows/isar.yml index 26394f7555..afe43d69af 100644 --- a/.github/workflows/isar.yml +++ b/.github/workflows/isar.yml @@ -100,7 +100,7 @@ jobs: file: ./isar/coverage/lcov.info functionalities: "search" # remove after https://github.com/codecov/codecov-action/issues/600 - - uses: VeryGoodOpenSource/very_good_coverage@3b475421464c564c0714d92ce02742bd81fa9eda # pin@v2.2.0 + - uses: VeryGoodOpenSource/very_good_coverage@c953fca3e24a915e111cc6f55f03f756dcb3964c # pin@v3.0.0 if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' with: path: "./isar/coverage/lcov.info" diff --git a/.github/workflows/logging.yml b/.github/workflows/logging.yml index 138364fb31..1dac410e95 100644 --- a/.github/workflows/logging.yml +++ b/.github/workflows/logging.yml @@ -58,7 +58,7 @@ jobs: name: sentry_logging files: ./logging/coverage/lcov.info - - uses: VeryGoodOpenSource/very_good_coverage@3b475421464c564c0714d92ce02742bd81fa9eda # pin@v2.1.0 if: runner.os == 'Linux' && matrix.sdk == 'stable' + - uses: VeryGoodOpenSource/very_good_coverage@c953fca3e24a915e111cc6f55f03f756dcb3964c # pin@v2.1.0 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: path: "./logging/coverage/lcov.info" min_coverage: 90 diff --git a/.github/workflows/sqflite.yml b/.github/workflows/sqflite.yml index cea7a5ad14..57c21613b8 100644 --- a/.github/workflows/sqflite.yml +++ b/.github/workflows/sqflite.yml @@ -100,7 +100,7 @@ jobs: file: ./sqflite/coverage/lcov.info functionalities: "search" # remove after https://github.com/codecov/codecov-action/issues/600 - - uses: VeryGoodOpenSource/very_good_coverage@3b475421464c564c0714d92ce02742bd81fa9eda # pin@v2.2.0 + - uses: VeryGoodOpenSource/very_good_coverage@c953fca3e24a915e111cc6f55f03f756dcb3964c # pin@v3.0.0 if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' with: path: "./sqflite/coverage/lcov.info" From fb06db41bd94b29a1daddf4d61830b3c928190a3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 12 Mar 2024 11:21:47 +0100 Subject: [PATCH 110/237] chore: update metrics/flutter.properties to 3.19.3 (#1925) Co-authored-by: GitHub Co-authored-by: Giancarlo Buenaflor --- metrics/flutter.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/metrics/flutter.properties b/metrics/flutter.properties index f9b46d7c2a..1aa5448f26 100644 --- a/metrics/flutter.properties +++ b/metrics/flutter.properties @@ -1,2 +1,2 @@ -version = 3.19.2 +version = 3.19.3 repo = https://github.com/flutter/flutter From e8603bbc68f19dd756ed1a48a23a88322a594c55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20Andra=C5=A1ec?= Date: Tue, 12 Mar 2024 10:38:53 +0000 Subject: [PATCH 111/237] Add override `captureFailedRequests` option (#1931) --- CHANGELOG.md | 6 ++ .../http_client/failed_request_client.dart | 9 ++- .../src/http_client/sentry_http_client.dart | 5 ++ .../failed_request_client_test.dart | 54 ++++++++++++++--- .../http_client/sentry_http_client_test.dart | 34 ++++++++++- dio/lib/src/failed_request_interceptor.dart | 9 ++- dio/lib/src/sentry_dio_extension.dart | 5 +- dio/test/failed_request_interceptor_test.dart | 34 +++++++++++ dio/test/sentry_dio_extension_test.dart | 58 +++++++++++++++++++ 9 files changed, 195 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cea76a1ea1..fbc60f0891 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ ## Unreleased +## Features + +- Add override `captureFailedRequests` option ([#1931](https://github.com/getsentry/sentry-dart/pull/1931)) + - The `dio` integration and `SentryHttpClient` now take an additional `captureFailedRequests` option. + - This is useful if you want to disable this option on native and only enable it on `dio` for example. + ### Dependencies - Bump Android SDK from v7.5.0 to v7.6.0 ([#1927](https://github.com/getsentry/sentry-dart/pull/1927)) diff --git a/dart/lib/src/http_client/failed_request_client.dart b/dart/lib/src/http_client/failed_request_client.dart index 98df59194f..dc07f407ed 100644 --- a/dart/lib/src/http_client/failed_request_client.dart +++ b/dart/lib/src/http_client/failed_request_client.dart @@ -73,15 +73,18 @@ class FailedRequestClient extends BaseClient { this.failedRequestTargets = SentryHttpClient.defaultFailedRequestTargets, Client? client, Hub? hub, + bool? captureFailedRequests, }) : _hub = hub ?? HubAdapter(), - _client = client ?? Client() { - if (_hub.options.captureFailedRequests) { + _client = client ?? Client(), + _captureFailedRequests = captureFailedRequests { + if (captureFailedRequests ?? _hub.options.captureFailedRequests) { _hub.options.sdk.addIntegration('HTTPClientError'); } } final Client _client; final Hub _hub; + final bool? _captureFailedRequests; /// Describes which HTTP status codes should be considered as a failed /// requests. @@ -129,7 +132,7 @@ class FailedRequestClient extends BaseClient { StackTrace? stackTrace, StreamedResponse? response, Duration duration) async { - if (!_hub.options.captureFailedRequests) { + if (!(_captureFailedRequests ?? _hub.options.captureFailedRequests)) { return; } diff --git a/dart/lib/src/http_client/sentry_http_client.dart b/dart/lib/src/http_client/sentry_http_client.dart index c3b3346fb7..35fcae4b4f 100644 --- a/dart/lib/src/http_client/sentry_http_client.dart +++ b/dart/lib/src/http_client/sentry_http_client.dart @@ -73,6 +73,9 @@ import 'failed_request_client.dart'; /// Remarks: /// HTTP traffic can contain PII (personal identifiable information). /// Read more on data scrubbing [here](https://docs.sentry.io/product/data-management-settings/advanced-datascrubbing/). +/// +/// The constructor parameter `captureFailedRequests` will override what you +/// have configured in options. /// ``` class SentryHttpClient extends BaseClient { static const defaultFailedRequestStatusCodes = [ @@ -86,6 +89,7 @@ class SentryHttpClient extends BaseClient { List failedRequestStatusCodes = defaultFailedRequestStatusCodes, List failedRequestTargets = defaultFailedRequestTargets, + bool? captureFailedRequests, }) { _hub = hub ?? HubAdapter(); @@ -96,6 +100,7 @@ class SentryHttpClient extends BaseClient { failedRequestTargets: failedRequestTargets, hub: _hub, client: innerClient, + captureFailedRequests: captureFailedRequests, ); if (_hub.options.isTracingEnabled()) { diff --git a/dart/test/http_client/failed_request_client_test.dart b/dart/test/http_client/failed_request_client_test.dart index 4e6cac15b1..9c450f8bd2 100644 --- a/dart/test/http_client/failed_request_client_test.dart +++ b/dart/test/http_client/failed_request_client_test.dart @@ -70,7 +70,12 @@ void main() { expect(eventCall.contexts.response, isNull); }); - test('event not reported if disabled', () async { + test( + 'exception does not gets reported if client throws but override disables capture', + () async { + fixture._hub.options.captureFailedRequests = true; + fixture._hub.options.sendDefaultPii = true; + final sut = fixture.getSut( client: createThrowingClient(), captureFailedRequests: false, @@ -84,10 +89,42 @@ void main() { expect(fixture.transport.calls, 0); }); + test('event not reported if disabled', () async { + fixture._hub.options.captureFailedRequests = false; + + final sut = fixture.getSut( + client: createThrowingClient(), + ); + + await expectLater( + () async => await sut.get(requestUri, headers: {'Cookie': 'foo=bar'}), + throwsException, + ); + + expect(fixture.transport.calls, 0); + }); + + test('event reported if disabled but overridden', () async { + fixture._hub.options.captureFailedRequests = false; + + final sut = fixture.getSut( + client: createThrowingClient(), + captureFailedRequests: true, + ); + + await expectLater( + () async => await sut.get(requestUri, headers: {'Cookie': 'foo=bar'}), + throwsException, + ); + + expect(fixture.transport.calls, 1); + }); + test('event not reported if not within the targets', () async { + fixture._hub.options.captureFailedRequests = true; + final sut = fixture.getSut( client: fixture.getClient(statusCode: 500), - captureFailedRequests: true, failedRequestTargets: const ["myapi.com"]); final response = await sut.get(requestUri); @@ -335,17 +372,16 @@ class Fixture { List failedRequestStatusCodes = const [ SentryStatusCode.defaultRange() ], - bool captureFailedRequests = true, List failedRequestTargets = const [".*"], + bool? captureFailedRequests, }) { final mc = client ?? getClient(); - _hub.options.captureFailedRequests = captureFailedRequests; return FailedRequestClient( - client: mc, - hub: _hub, - failedRequestStatusCodes: failedRequestStatusCodes, - failedRequestTargets: failedRequestTargets, - ); + client: mc, + hub: _hub, + failedRequestStatusCodes: failedRequestStatusCodes, + failedRequestTargets: failedRequestTargets, + captureFailedRequests: captureFailedRequests); } MockClient getClient( diff --git a/dart/test/http_client/sentry_http_client_test.dart b/dart/test/http_client/sentry_http_client_test.dart index 5952a02541..be9d8d7bd1 100644 --- a/dart/test/http_client/sentry_http_client_test.dart +++ b/dart/test/http_client/sentry_http_client_test.dart @@ -32,9 +32,10 @@ void main() { }); test('no captured event with default config', () async { + fixture.hub.options.captureFailedRequests = false; + final sut = fixture.getSut( client: createThrowingClient(), - captureFailedRequests: false, ); await expectLater(() async => await sut.get(requestUri), throwsException); @@ -43,6 +44,19 @@ void main() { expect(fixture.hub.addBreadcrumbCalls.length, 1); }); + test('captured event with override', () async { + fixture.hub.options.captureFailedRequests = false; + + final sut = fixture.getSut( + client: createThrowingClient(), + captureFailedRequests: true, + ); + + await expectLater(() async => await sut.get(requestUri), throwsException); + + expect(fixture.hub.captureEventCalls.length, 1); + }); + test('one captured event with when enabling $FailedRequestClient', () async { fixture.hub.options.captureFailedRequests = true; @@ -61,6 +75,20 @@ void main() { expect(fixture.hub.addBreadcrumbCalls.length, 1); }); + test( + 'no captured event with when enabling $FailedRequestClient with override', + () async { + fixture.hub.options.captureFailedRequests = true; + final sut = fixture.getSut( + client: createThrowingClient(), + captureFailedRequests: false, + ); + + await expectLater(() async => await sut.get(requestUri), throwsException); + + expect(fixture.hub.captureEventCalls.length, 0); + }); + test('close does get called for user defined client', () async { final mockHub = MockHub(); @@ -116,14 +144,14 @@ class Fixture { SentryHttpClient getSut({ MockClient? client, List badStatusCodes = const [], - bool captureFailedRequests = true, + bool? captureFailedRequests, }) { final mc = client ?? getClient(); - hub.options.captureFailedRequests = captureFailedRequests; return SentryHttpClient( client: mc, hub: hub, failedRequestStatusCodes: badStatusCodes, + captureFailedRequests: captureFailedRequests, ); } diff --git a/dio/lib/src/failed_request_interceptor.dart b/dio/lib/src/failed_request_interceptor.dart index 60ea4a0133..994da6121e 100644 --- a/dio/lib/src/failed_request_interceptor.dart +++ b/dio/lib/src/failed_request_interceptor.dart @@ -10,13 +10,16 @@ class FailedRequestInterceptor extends Interceptor { SentryHttpClient.defaultFailedRequestStatusCodes, List failedRequestTargets = SentryHttpClient.defaultFailedRequestTargets, + bool? captureFailedRequests, }) : _hub = hub ?? HubAdapter(), _failedRequestStatusCodes = failedRequestStatusCodes, - _failedRequestTargets = failedRequestTargets; + _failedRequestTargets = failedRequestTargets, + _captureFailedRequests = captureFailedRequests; final Hub _hub; final List _failedRequestStatusCodes; final List _failedRequestTargets; + final bool? _captureFailedRequests; @override Future onError( @@ -24,7 +27,7 @@ class FailedRequestInterceptor extends Interceptor { ErrorInterceptorHandler handler, ) async { // ignore: invalid_use_of_internal_member - final captureFailedRequests = _hub.options.captureFailedRequests; + final cfr = _captureFailedRequests ?? _hub.options.captureFailedRequests; final containsStatusCode = _failedRequestStatusCodes.containsStatusCode(err.response?.statusCode); @@ -33,7 +36,7 @@ class FailedRequestInterceptor extends Interceptor { err.requestOptions.path, ); - if (captureFailedRequests && containsStatusCode && containsRequestTarget) { + if (cfr && containsStatusCode && containsRequestTarget) { final mechanism = Mechanism(type: 'SentryDioClientAdapter'); final throwableMechanism = ThrowableMechanism(mechanism, err); diff --git a/dio/lib/src/sentry_dio_extension.dart b/dio/lib/src/sentry_dio_extension.dart index cf49de64d5..6c60b1f7c6 100644 --- a/dio/lib/src/sentry_dio_extension.dart +++ b/dio/lib/src/sentry_dio_extension.dart @@ -42,12 +42,15 @@ extension SentryDioExtension on Dio { /// failedRequestTargets: ['my-api.com'], /// ); /// ``` + /// + /// The captureFailedRequests argument will take precedent over options. void addSentry({ Hub? hub, List failedRequestStatusCodes = SentryHttpClient.defaultFailedRequestStatusCodes, List failedRequestTargets = SentryHttpClient.defaultFailedRequestTargets, + bool? captureFailedRequests, }) { hub = hub ?? HubAdapter(); @@ -71,7 +74,7 @@ extension SentryDioExtension on Dio { } options.sdk.addPackage(packageName, sdkVersion); - if (options.captureFailedRequests) { + if (captureFailedRequests ?? options.captureFailedRequests) { // Add FailedRequestInterceptor at index 0, so it's the first interceptor. // This ensures that it is called and not skipped by any previous interceptor. interceptors.insert( diff --git a/dio/test/failed_request_interceptor_test.dart b/dio/test/failed_request_interceptor_test.dart index e7fb5a63e1..4602180e0c 100644 --- a/dio/test/failed_request_interceptor_test.dart +++ b/dio/test/failed_request_interceptor_test.dart @@ -50,6 +50,38 @@ void main() { expect(fixture.hub.captureExceptionCalls.length, 0); }); + test('do capture if captureFailedRequests override is true', () async { + final requestOptions = RequestOptions(path: 'https://example.com'); + final error = DioError( + requestOptions: requestOptions, + response: Response(statusCode: 500, requestOptions: requestOptions), + ); + + fixture.hub.options.captureFailedRequests = false; + + final sut = fixture.getSut(captureFailedRequests: true); + await sut.onError(error, fixture.errorInterceptorHandler); + + expect(fixture.errorInterceptorHandler.nextWasCalled, true); + expect(fixture.hub.captureExceptionCalls.length, 1); + }); + + test('do not capture if captureFailedRequests override false', () async { + final requestOptions = RequestOptions(path: 'https://example.com'); + final error = DioError( + requestOptions: requestOptions, + response: Response(statusCode: 500, requestOptions: requestOptions), + ); + + fixture.hub.options.captureFailedRequests = true; + + final sut = fixture.getSut(captureFailedRequests: false); + await sut.onError(error, fixture.errorInterceptorHandler); + + expect(fixture.errorInterceptorHandler.nextWasCalled, true); + expect(fixture.hub.captureExceptionCalls.length, 0); + }); + test('capture in range failedRequestStatusCodes', () async { final requestOptions = RequestOptions(path: 'https://example.com'); final error = DioError( @@ -116,11 +148,13 @@ class Fixture { SentryStatusCode.defaultRange(), ], List failedRequestTargets = const ['.*'], + bool? captureFailedRequests, }) { return FailedRequestInterceptor( hub: hub, failedRequestStatusCodes: failedRequestStatusCodes, failedRequestTargets: failedRequestTargets, + captureFailedRequests: captureFailedRequests, ); } } diff --git a/dio/test/sentry_dio_extension_test.dart b/dio/test/sentry_dio_extension_test.dart index e81c3296b5..622dac5442 100644 --- a/dio/test/sentry_dio_extension_test.dart +++ b/dio/test/sentry_dio_extension_test.dart @@ -4,6 +4,7 @@ import 'package:dio/dio.dart'; import 'package:sentry_dio/sentry_dio.dart'; import 'package:sentry_dio/src/dio_error_extractor.dart'; import 'package:sentry_dio/src/dio_stacktrace_extractor.dart'; +import 'package:sentry_dio/src/failed_request_interceptor.dart'; import 'package:sentry_dio/src/sentry_dio_client_adapter.dart'; import 'package:sentry_dio/src/sentry_dio_extension.dart'; import 'package:sentry_dio/src/sentry_transformer.dart'; @@ -48,6 +49,63 @@ void main() { ); }); + test( + 'addSentry adds $FailedRequestInterceptor if captureFailedRequests true', + () { + final dio = fixture.getSut(); + + fixture.hub.options.captureFailedRequests = true; + + dio.addSentry(hub: fixture.hub); + + expect( + dio.interceptors.whereType().length, + 1, + ); + }); + + test( + 'addSentry does not add $FailedRequestInterceptor if captureFailedRequests false', + () { + final dio = fixture.getSut(); + + fixture.hub.options.captureFailedRequests = false; + + dio.addSentry(hub: fixture.hub); + + expect( + dio.interceptors.whereType().length, + 0, + ); + }); + + test('addSentry adds $FailedRequestInterceptor if override true', () { + final dio = fixture.getSut(); + + fixture.hub.options.captureFailedRequests = false; + + dio.addSentry(hub: fixture.hub, captureFailedRequests: true); + + expect( + dio.interceptors.whereType().length, + 1, + ); + }); + + test('addSentry does not add $FailedRequestInterceptor if override false', + () { + final dio = fixture.getSut(); + + fixture.hub.options.captureFailedRequests = true; + + dio.addSentry(hub: fixture.hub, captureFailedRequests: false); + + expect( + dio.interceptors.whereType().length, + 0, + ); + }); + test('addSentry only adds one $DioEventProcessor', () { final dio = fixture.getSut(); From d089990aa16ee19071abb70d6bab8231c452fc13 Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Wed, 13 Mar 2024 12:09:58 +0100 Subject: [PATCH 112/237] feat: ttfd (#1920) * Change app start integration in a way that works with ttid as well * Formatting * Update * add visibleForTesting * Update * update * Add app start info test * Remove set app start info null * Review improvements * Add TTID * Improvements * Improvements * Fix integration test * Update * Clear after tracking * Update CHANGELOG * Format * Update * Update * remove import * Update sentry tracer * Add (not all) improvements for pr review * combine transaction handler * Refactor trackAppStart and trackRegularRoute to use private method * Fix dart analyzer * Remove clear * Clear in tearDown * Apply suggestions from code review Co-authored-by: Philipp Hofmann * Apply PR suggestions * fix analyze * update * update * Fix tests * Fix analyze * revert sample * Update * Update * Fix child timestamp trimming * Update CHANGELOG * Run formatting * Update docs * Revert * Fix test * Move clear to the beginning of function * initial commit * Fix start time * Fix analyze * remove comment * Formatting * update * fix test * Add changelog * Update * Update * fix analyze * fix tests * formatting * add ttid duration assertion and determineEndTime timeout * Rename finish transaction and do an early exit with enableAutoTransactions * Rename function * Remove static and getter for in navigator observer * Expose SentryDisplayWidget as public api and add it to example app * Fix dart analyze * Fix dart doc * Get display tracker as static for reportFullyDisplayed() * Add @internal * Fix test * Improve tests * Reduce fake frame finishing time and improve tests * Improve test names * Fix tests * Apply formatting * Add extra assertion in tests * Improve * Use utc date time * Fix test * Fix dartdoc * Update test * Update test * Fix tests * Fix changelog * Update * Improve * Update * Improve tests * Update * Change function to private * Update CHANGELOG.md * Rename function * add improvements (not all) * Fix tests * Update changelog * Finish after setting scope span to null * update * updaet * update * clear first in didPush * update * update example * add improvements --------- Co-authored-by: Philipp Hofmann --- CHANGELOG.md | 29 +- dart/lib/src/sentry_measurement.dart | 7 + dart/lib/src/sentry_span_operations.dart | 1 + dart/test/sentry_tracer_test.dart | 1 + flutter/example/lib/auto_close_screen.dart | 19 +- flutter/example/lib/main.dart | 1 + .../navigation/sentry_navigator_observer.dart | 141 +++++++--- .../navigation/time_to_display_tracker.dart | 27 +- .../time_to_full_display_tracker.dart | 113 ++++++++ flutter/lib/src/sentry_flutter.dart | 6 + flutter/lib/src/sentry_flutter_options.dart | 6 + flutter/test/mocks.dart | 1 + flutter/test/mocks.mocks.dart | 250 +++++++++++++++++- .../time_to_display_tracker_test.dart | 175 +++++++++--- .../time_to_full_display_tracker_test.dart | 87 ++++++ .../test/sentry_navigator_observer_test.dart | 147 ++++++++-- 16 files changed, 886 insertions(+), 125 deletions(-) create mode 100644 flutter/lib/src/navigation/time_to_full_display_tracker.dart create mode 100644 flutter/test/navigation/time_to_full_display_tracker_test.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index fbc60f0891..04cb41f568 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,24 @@ # Changelog ## Unreleased - + ## Features +- Add TTFD (time to full display), which allows you to measure the time it takes to render the full screen ([#1920](https://github.com/getsentry/sentry-dart/pull/1920)) + - Requires using the [routing instrumentation](https://docs.sentry.io/platforms/flutter/integrations/routing-instrumentation/). + - Set `enableTimeToFullDisplayTracing = true` in your `SentryFlutterOptions` to enable TTFD + - Manually report the end of the full display by calling `SentryFlutter.reportFullyDisplayed()` + - If not reported within 30 seconds, the span will be automatically finish with the status `deadline_exceeded` +- Add TTID (time to initial display), which allows you to measure the time it takes to render the first frame of your screen ([#1910](https://github.com/getsentry/sentry-dart/pull/1910)) + - Requires using the [routing instrumentation](https://docs.sentry.io/platforms/flutter/integrations/routing-instrumentation/). + - Introduces two modes: + - `automatic` mode is enabled by default for all screens and will yield only an approximation result. + - `manual` mode requires manual instrumentation and will yield a more accurate result. + - To use `manual` mode, you need to wrap your desired widget: `SentryDisplayWidget(child: MyScreen())`. + - You can mix and match both modes in your app. + - Other significant fixes + - `didPop` doesn't trigger a new transaction + - Change transaction operation name to `ui.load` instead of `navigation` - Add override `captureFailedRequests` option ([#1931](https://github.com/getsentry/sentry-dart/pull/1931)) - The `dio` integration and `SentryHttpClient` now take an additional `captureFailedRequests` option. - This is useful if you want to disable this option on native and only enable it on `dio` for example. @@ -23,17 +38,7 @@ - remove transitive dart:io reference for web ([#1898](https://github.com/getsentry/sentry-dart/pull/1898)) ### Features - -- Add TTID (time to initial display), which allows you to measure the time it takes to render the first frame of your screen ([#1910](https://github.com/getsentry/sentry-dart/pull/1910)) - - Requires using the [routing instrumentation](https://docs.sentry.io/platforms/flutter/integrations/routing-instrumentation/). - - Introduces two modes: - - `automatic` mode is enabled by default for all screens and will yield only an approximation result. - - `manual` mode requires manual instrumentation and will yield a more accurate result. - - To use `manual` mode, you need to wrap your desired widget: `SentryDisplayWidget(child: MyScreen())`. - - You can mix and match both modes in your app. - - Other significant fixes - - `didPop` doesn't trigger a new transaction - - Change transaction operation name to `ui.load` instead of `navigation` +- - Use `recordHttpBreadcrumbs` to set iOS `enableNetworkBreadcrumbs` ([#1884](https://github.com/getsentry/sentry-dart/pull/1884)) - Apply `beforeBreadcrumb` on native iOS crumbs ([#1914](https://github.com/getsentry/sentry-dart/pull/1914)) - Add `maxQueueSize` to limit the number of unawaited events sent to Sentry ([#1868](https://github.com/getsentry/sentry-dart/pull/1868)) diff --git a/dart/lib/src/sentry_measurement.dart b/dart/lib/src/sentry_measurement.dart index b95e506aab..663197654d 100644 --- a/dart/lib/src/sentry_measurement.dart +++ b/dart/lib/src/sentry_measurement.dart @@ -46,6 +46,13 @@ class SentryMeasurement { value = duration.inMilliseconds, unit = DurationSentryMeasurementUnit.milliSecond; + /// Duration of the time to full display in milliseconds + SentryMeasurement.timeToFullDisplay(Duration duration) + : assert(!duration.isNegative), + name = 'time_to_full_display', + value = duration.inMilliseconds, + unit = DurationSentryMeasurementUnit.milliSecond; + final String name; final num value; final SentryMeasurementUnit? unit; diff --git a/dart/lib/src/sentry_span_operations.dart b/dart/lib/src/sentry_span_operations.dart index fca22fc1e9..27b1d22496 100644 --- a/dart/lib/src/sentry_span_operations.dart +++ b/dart/lib/src/sentry_span_operations.dart @@ -4,4 +4,5 @@ import 'package:meta/meta.dart'; class SentrySpanOperations { static const String uiLoad = 'ui.load'; static const String uiTimeToInitialDisplay = 'ui.load.initial_display'; + static const String uiTimeToFullDisplay = 'ui.load.full_display'; } diff --git a/dart/test/sentry_tracer_test.dart b/dart/test/sentry_tracer_test.dart index 1a328702d1..e57cb415ea 100644 --- a/dart/test/sentry_tracer_test.dart +++ b/dart/test/sentry_tracer_test.dart @@ -389,6 +389,7 @@ void main() { test('end trimmed to latest child end timestamp', () async { final sut = fixture.getSut(trimEnd: true); final rootEndInitial = getUtcDateTime(); + final childAEnd = rootEndInitial; final childBEnd = rootEndInitial.add(Duration(seconds: 1)); final childCEnd = rootEndInitial; diff --git a/flutter/example/lib/auto_close_screen.dart b/flutter/example/lib/auto_close_screen.dart index 15e8fac1fb..6848678b4c 100644 --- a/flutter/example/lib/auto_close_screen.dart +++ b/flutter/example/lib/auto_close_screen.dart @@ -1,5 +1,9 @@ +import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; -import 'package:sentry/sentry.dart'; +import 'package:sentry_dio/sentry_dio.dart'; +import 'package:sentry_flutter/sentry_flutter.dart'; + +import 'main.dart'; /// This screen is only used to demonstrate how route navigation works. /// Init will create a child span and pop the screen after 3 seconds. @@ -21,11 +25,14 @@ class AutoCloseScreenState extends State { } Future _doComplexOperationThenClose() async { - final activeSpan = Sentry.getSpan(); - final childSpan = activeSpan?.startChild('complex operation', - description: 'running a $delayInSeconds seconds operation'); - await Future.delayed(const Duration(seconds: delayInSeconds)); - childSpan?.finish(); + final dio = Dio(); + dio.addSentry(); + try { + await dio.get(exampleUrl); + } catch (exception, stackTrace) { + await Sentry.captureException(exception, stackTrace: stackTrace); + } + SentryFlutter.reportFullyDisplayed(); // ignore: use_build_context_synchronously Navigator.of(context).pop(); } diff --git a/flutter/example/lib/main.dart b/flutter/example/lib/main.dart index 19050ec79e..2a68648ee0 100644 --- a/flutter/example/lib/main.dart +++ b/flutter/example/lib/main.dart @@ -82,6 +82,7 @@ Future setupSentry( // configuration issues, e.g. finding out why your events are not uploaded. options.debug = true; options.spotlight = Spotlight(enabled: true); + options.enableTimeToFullDisplayTracing = true; options.maxRequestBodySize = MaxRequestBodySize.always; options.maxResponseBodySize = MaxResponseBodySize.always; diff --git a/flutter/lib/src/navigation/sentry_navigator_observer.dart b/flutter/lib/src/navigation/sentry_navigator_observer.dart index 5eb7884006..0af0a76381 100644 --- a/flutter/lib/src/navigation/sentry_navigator_observer.dart +++ b/flutter/lib/src/navigation/sentry_navigator_observer.dart @@ -12,6 +12,9 @@ import '../../sentry_flutter.dart'; import '../event_processor/flutter_enricher_event_processor.dart'; import '../native/sentry_native.dart'; +// ignore: implementation_imports +import 'package:sentry/src/sentry_tracer.dart'; + /// This key must be used so that the web interface displays the events nicely /// See https://develop.sentry.dev/sdk/event-payloads/breadcrumbs/ const _navigationKey = 'navigation'; @@ -82,11 +85,23 @@ class SentryNavigatorObserver extends RouteObserver> { _setRouteNameAsTransaction = setRouteNameAsTransaction, _routeNameExtractor = routeNameExtractor, _additionalInfoProvider = additionalInfoProvider, - _native = SentryFlutter.native, - _timeToDisplayTracker = timeToDisplayTracker ?? TimeToDisplayTracker() { + _native = SentryFlutter.native { if (enableAutoTransactions) { _hub.options.sdk.addIntegration('UINavigationTracing'); } + _timeToDisplayTracker = + timeToDisplayTracker ?? _initializeTimeToDisplayTracker(); + } + + /// Initializes the TimeToDisplayTracker with the option to enable time to full display tracing. + TimeToDisplayTracker _initializeTimeToDisplayTracker() { + bool enableTimeToFullDisplayTracing = false; + final options = _hub.options; + if (options is SentryFlutterOptions) { + enableTimeToFullDisplayTracing = options.enableTimeToFullDisplayTracing; + } + return TimeToDisplayTracker( + enableTimeToFullDisplayTracing: enableTimeToFullDisplayTracing); } final Hub _hub; @@ -96,7 +111,11 @@ class SentryNavigatorObserver extends RouteObserver> { final RouteNameExtractor? _routeNameExtractor; final AdditionalInfoExtractor? _additionalInfoProvider; final SentryNative? _native; - final TimeToDisplayTracker? _timeToDisplayTracker; + static TimeToDisplayTracker? _timeToDisplayTracker; + + @internal + static TimeToDisplayTracker? get timeToDisplayTracker => + _timeToDisplayTracker; ISentrySpan? _transaction; @@ -105,7 +124,7 @@ class SentryNavigatorObserver extends RouteObserver> { @internal static String? get currentRouteName => _currentRouteName; - Completer? _completedDisplayTracking; + Completer? _completedDisplayTracking = Completer(); // Since didPush does not have a future, we can keep track of when the display tracking has finished @visibleForTesting @@ -124,6 +143,8 @@ class SentryNavigatorObserver extends RouteObserver> { to: route.settings, ); + // Clearing the display tracker here is safe since didPush happens before the Widget is built + _timeToDisplayTracker?.clear(); _finishTimeToDisplayTracking(); _startTimeToDisplayTracking(route); } @@ -155,7 +176,7 @@ class SentryNavigatorObserver extends RouteObserver> { to: previousRoute?.settings, ); - _finishTimeToDisplayTracking(); + _finishTimeToDisplayTracking(clearAfter: true); } void _addBreadcrumb({ @@ -253,56 +274,96 @@ class SentryNavigatorObserver extends RouteObserver> { await _native?.beginNativeFramesCollection(); } - Future _finishTimeToDisplayTracking() async { - _timeToDisplayTracker?.clear(); - + Future _finishTimeToDisplayTracking({bool clearAfter = false}) async { final transaction = _transaction; _transaction = null; - if (transaction == null || transaction.finished) { - return; + try { + _hub.configureScope((scope) { + if (scope.span == transaction) { + scope.span = null; + } + }); + + if (transaction == null || transaction.finished) { + return; + } + + // Cancel unfinished TTID/TTFD spans, e.g this might happen if the user navigates + // away from the current route before TTFD or TTID is finished. + for (final child in (transaction as SentryTracer).children) { + final isTTIDSpan = child.context.operation == + SentrySpanOperations.uiTimeToInitialDisplay; + final isTTFDSpan = + child.context.operation == SentrySpanOperations.uiTimeToFullDisplay; + if (!child.finished && (isTTIDSpan || isTTFDSpan)) { + await child.finish(status: SpanStatus.deadlineExceeded()); + } + } + } catch (exception, stacktrace) { + _hub.options.logger( + SentryLevel.error, + 'Error while finishing time to display tracking', + exception: exception, + stackTrace: stacktrace, + ); + } finally { + await transaction?.finish(); + if (clearAfter) { + _clear(); + } } - transaction.status ??= SpanStatus.ok(); - await transaction.finish(); } Future _startTimeToDisplayTracking(Route? route) async { - if (!_enableAutoTransactions) { - return; - } + try { + final routeName = _getRouteName(route) ?? _currentRouteName; + if (!_enableAutoTransactions || routeName == null) { + return; + } - _completedDisplayTracking = Completer(); - String? routeName = _currentRouteName; - if (routeName == null) return; + bool isAppStart = routeName == '/'; + DateTime startTimestamp = _hub.options.clock(); + DateTime? endTimestamp; - DateTime startTimestamp = _hub.options.clock(); - DateTime? endTimestamp; + if (isAppStart) { + final appStartInfo = await NativeAppStartIntegration.getAppStartInfo(); + if (appStartInfo == null) return; - if (routeName == '/') { - final appStartInfo = await NativeAppStartIntegration.getAppStartInfo(); - if (appStartInfo == null) { - return; + startTimestamp = appStartInfo.start; + endTimestamp = appStartInfo.end; } - startTimestamp = appStartInfo.start; - endTimestamp = appStartInfo.end; - } + await _startTransaction(route, startTimestamp); - await _startTransaction(route, startTimestamp); - final transaction = _transaction; - if (transaction == null) { - return; - } + final transaction = _transaction; + if (transaction == null) { + return; + } - if (routeName == '/' && endTimestamp != null) { - await _timeToDisplayTracker?.trackAppStartTTD(transaction, - startTimestamp: startTimestamp, endTimestamp: endTimestamp); - } else { - await _timeToDisplayTracker?.trackRegularRouteTTD(transaction, - startTimestamp: startTimestamp); + if (isAppStart && endTimestamp != null) { + await _timeToDisplayTracker?.trackAppStartTTD(transaction, + startTimestamp: startTimestamp, endTimestamp: endTimestamp); + } else { + await _timeToDisplayTracker?.trackRegularRouteTTD(transaction, + startTimestamp: startTimestamp); + } + } catch (exception, stacktrace) { + _hub.options.logger( + SentryLevel.error, + 'Error while tracking time to display', + exception: exception, + stackTrace: stacktrace, + ); + } finally { + _clear(); } + } - // Mark the tracking as completed and clear any temporary state. - _completedDisplayTracking?.complete(); + void _clear() { + if (_completedDisplayTracking?.isCompleted == false) { + _completedDisplayTracking?.complete(); + } + _completedDisplayTracking = Completer(); _timeToDisplayTracker?.clear(); } } diff --git a/flutter/lib/src/navigation/time_to_display_tracker.dart b/flutter/lib/src/navigation/time_to_display_tracker.dart index 713bc16ff4..342e305c75 100644 --- a/flutter/lib/src/navigation/time_to_display_tracker.dart +++ b/flutter/lib/src/navigation/time_to_display_tracker.dart @@ -1,19 +1,25 @@ // ignore_for_file: invalid_use_of_internal_member -import 'dart:async'; - import 'package:meta/meta.dart'; import '../../sentry_flutter.dart'; +import 'time_to_full_display_tracker.dart'; import 'time_to_initial_display_tracker.dart'; @internal class TimeToDisplayTracker { final TimeToInitialDisplayTracker _ttidTracker; + final TimeToFullDisplayTracker? _ttfdTracker; + final bool enableTimeToFullDisplayTracing; TimeToDisplayTracker({ TimeToInitialDisplayTracker? ttidTracker, - }) : _ttidTracker = ttidTracker ?? TimeToInitialDisplayTracker(); + TimeToFullDisplayTracker? ttfdTracker, + required this.enableTimeToFullDisplayTracing, + }) : _ttidTracker = ttidTracker ?? TimeToInitialDisplayTracker(), + _ttfdTracker = enableTimeToFullDisplayTracing + ? ttfdTracker ?? TimeToFullDisplayTracker() + : null; Future trackAppStartTTD(ISentrySpan transaction, {required DateTime startTimestamp, @@ -21,14 +27,29 @@ class TimeToDisplayTracker { // We start and immediately finish the spans since we cannot mutate the history of spans. await _ttidTracker.trackAppStart(transaction, startTimestamp: startTimestamp, endTimestamp: endTimestamp); + await _trackTTFDIfEnabled(transaction, startTimestamp); } Future trackRegularRouteTTD(ISentrySpan transaction, {required DateTime startTimestamp}) async { await _ttidTracker.trackRegularRoute(transaction, startTimestamp); + await _trackTTFDIfEnabled(transaction, startTimestamp); + } + + Future _trackTTFDIfEnabled( + ISentrySpan transaction, DateTime startTimestamp) async { + if (enableTimeToFullDisplayTracing) { + await _ttfdTracker?.track(transaction, startTimestamp); + } + } + + @internal + Future reportFullyDisplayed() async { + return _ttfdTracker?.reportFullyDisplayed(); } void clear() { _ttidTracker.clear(); + _ttfdTracker?.clear(); } } diff --git a/flutter/lib/src/navigation/time_to_full_display_tracker.dart b/flutter/lib/src/navigation/time_to_full_display_tracker.dart new file mode 100644 index 0000000000..385c25c38f --- /dev/null +++ b/flutter/lib/src/navigation/time_to_full_display_tracker.dart @@ -0,0 +1,113 @@ +// ignore_for_file: invalid_use_of_internal_member + +import 'dart:async'; + +import 'package:meta/meta.dart'; + +// ignore: implementation_imports +import 'package:sentry/src/sentry_tracer.dart'; + +import '../../sentry_flutter.dart'; +import 'time_to_initial_display_tracker.dart'; + +@internal +class TimeToFullDisplayTracker { + static final TimeToFullDisplayTracker _instance = + TimeToFullDisplayTracker._(); + + TimeToFullDisplayTracker._(); + + factory TimeToFullDisplayTracker( + {EndTimestampProvider? endTimestampProvider, Duration? autoFinishAfter}) { + if (autoFinishAfter != null) { + _instance._autoFinishAfter = autoFinishAfter; + } + if (endTimestampProvider != null) { + _instance._endTimestampProvider = endTimestampProvider; + } + return _instance; + } + + DateTime? _startTimestamp; + ISentrySpan? _ttfdSpan; + ISentrySpan? _transaction; + Duration _autoFinishAfter = const Duration(seconds: 30); + + // End timestamp provider is only needed when the TTFD timeout is triggered + EndTimestampProvider _endTimestampProvider = ttidEndTimestampProvider(); + Completer _completedTTFDTracking = Completer(); + + Future track(ISentrySpan transaction, DateTime startTimestamp) async { + _startTimestamp = startTimestamp; + _transaction = transaction as SentryTracer; + _ttfdSpan = transaction.startChild(SentrySpanOperations.uiTimeToFullDisplay, + description: '${transaction.name} full display', + startTimestamp: startTimestamp); + _ttfdSpan?.origin = SentryTraceOrigins.manualUiTimeToDisplay; + // Wait for TTFD to finish + await _completedTTFDTracking.future + .timeout(_autoFinishAfter, onTimeout: handleTimeout); + + clear(); + } + + void handleTimeout() { + final ttfdSpan = _ttfdSpan; + final startTimestamp = _startTimestamp; + final endTimestamp = _endTimestampProvider(); + + if (ttfdSpan == null || + ttfdSpan.finished == true || + startTimestamp == null || + endTimestamp == null) { + _completedTTFDTracking.complete(); + return; + } + + _setTTFDMeasurement(startTimestamp, endTimestamp); + ttfdSpan.finish( + status: SpanStatus.deadlineExceeded(), endTimestamp: endTimestamp); + + _completedTTFDTracking.complete(); + } + + Future reportFullyDisplayed() async { + final endTimestamp = getUtcDateTime(); + final startTimestamp = _startTimestamp; + final ttfdSpan = _ttfdSpan; + + if (ttfdSpan?.finished == true || startTimestamp == null) { + _completedTTFDTracking.complete(); + return; + } + + _setTTFDMeasurement(startTimestamp, endTimestamp); + await ttfdSpan?.finish(status: SpanStatus.ok(), endTimestamp: endTimestamp); + + _completedTTFDTracking.complete(); + } + + void _setTTFDMeasurement(DateTime startTimestamp, DateTime endTimestamp) { + final duration = endTimestamp.difference(startTimestamp); + final measurement = SentryMeasurement.timeToFullDisplay(duration); + _transaction?.setMeasurement(measurement.name, measurement.value, + unit: measurement.unit); + } + + void clear() { + _startTimestamp = null; + _ttfdSpan = null; + _transaction = null; + _completedTTFDTracking = Completer(); + } +} + +/// We need to retrieve the end time stamp in case TTFD timeout is triggered. +/// In those cases TTFD end time should match TTID end time. +/// This provider allows us to inject endTimestamps for testing as well. +@internal +typedef EndTimestampProvider = DateTime? Function(); + +@internal +EndTimestampProvider ttidEndTimestampProvider() => + () => TimeToInitialDisplayTracker().endTimestamp; diff --git a/flutter/lib/src/sentry_flutter.dart b/flutter/lib/src/sentry_flutter.dart index 9822b49665..b90bd47ad7 100644 --- a/flutter/lib/src/sentry_flutter.dart +++ b/flutter/lib/src/sentry_flutter.dart @@ -223,6 +223,12 @@ mixin SentryFlutter { options.sdk = sdk; } + /// Reports the time it took for the screen to be fully displayed. + /// This requires the [SentryFlutterOptions.enableTimeToFullDisplayTracing] option to be set to `true`. + static Future reportFullyDisplayed() async { + return SentryNavigatorObserver.timeToDisplayTracker?.reportFullyDisplayed(); + } + @internal static SentryNative? get native => _native; diff --git a/flutter/lib/src/sentry_flutter_options.dart b/flutter/lib/src/sentry_flutter_options.dart index ceda7ef0cc..ae83de611e 100644 --- a/flutter/lib/src/sentry_flutter_options.dart +++ b/flutter/lib/src/sentry_flutter_options.dart @@ -194,6 +194,12 @@ class SentryFlutterOptions extends SentryOptions { /// runApp(SentryUserInteractionWidget(child: App())); bool enableUserInteractionTracing = true; + /// Enable or disable the tracing of time to full display (TTFD). + /// If `SentryFlutter.reportFullyDisplayed()` is not called within 30 seconds + /// after the creation of the TTFD span, it will finish with the status [SpanStatus.deadlineExceeded]. + /// This feature requires using the [Routing Instrumentation](https://docs.sentry.io/platforms/flutter/integrations/routing-instrumentation/). + bool enableTimeToFullDisplayTracing = false; + /// Sets the Proguard uuid for Android platform. String? proguardUuid; diff --git a/flutter/test/mocks.dart b/flutter/test/mocks.dart index 41c3269393..0520a09884 100644 --- a/flutter/test/mocks.dart +++ b/flutter/test/mocks.dart @@ -46,6 +46,7 @@ ISentrySpan startTransactionShim( // ignore: invalid_use_of_internal_member SentryTracer, SentryTransaction, + SentrySpan, MethodChannel, ], customMocks: [ MockSpec(fallbackGenerators: {#startTransaction: startTransactionShim}) diff --git a/flutter/test/mocks.mocks.dart b/flutter/test/mocks.mocks.dart index e2807ef405..d747a3889f 100644 --- a/flutter/test/mocks.mocks.dart +++ b/flutter/test/mocks.mocks.dart @@ -1,4 +1,4 @@ -// Mocks generated by Mockito 5.4.2 from annotations +// Mocks generated by Mockito 5.4.4 from annotations // in sentry_flutter/test/mocks.dart. // Do not manually edit this file. @@ -7,20 +7,23 @@ import 'dart:async' as _i7; import 'package:flutter/src/services/binary_messenger.dart' as _i6; import 'package:flutter/src/services/message_codec.dart' as _i5; -import 'package:flutter/src/services/platform_channel.dart' as _i10; +import 'package:flutter/src/services/platform_channel.dart' as _i11; import 'package:mockito/mockito.dart' as _i1; +import 'package:mockito/src/dummies.dart' as _i9; import 'package:sentry/sentry.dart' as _i2; -import 'package:sentry/src/profiling.dart' as _i9; +import 'package:sentry/src/profiling.dart' as _i10; import 'package:sentry/src/protocol.dart' as _i3; import 'package:sentry/src/sentry_envelope.dart' as _i8; import 'package:sentry/src/sentry_tracer.dart' as _i4; -import 'mocks.dart' as _i11; +import 'mocks.dart' as _i12; // ignore_for_file: type=lint // ignore_for_file: avoid_redundant_argument_values // ignore_for_file: avoid_setters_without_getters // ignore_for_file: comment_references +// ignore_for_file: deprecated_member_use +// ignore_for_file: deprecated_member_use_from_same_package // ignore_for_file: implementation_imports // ignore_for_file: invalid_use_of_visible_for_testing_member // ignore_for_file: prefer_const_constructors @@ -192,7 +195,10 @@ class MockSentryTracer extends _i1.Mock implements _i4.SentryTracer { @override String get name => (super.noSuchMethod( Invocation.getter(#name), - returnValue: '', + returnValue: _i9.dummyValue( + this, + Invocation.getter(#name), + ), ) as String); @override @@ -223,7 +229,7 @@ class MockSentryTracer extends _i1.Mock implements _i4.SentryTracer { ); @override - set profiler(_i9.SentryProfiler? _profiler) => super.noSuchMethod( + set profiler(_i10.SentryProfiler? _profiler) => super.noSuchMethod( Invocation.setter( #profiler, _profiler, @@ -232,7 +238,7 @@ class MockSentryTracer extends _i1.Mock implements _i4.SentryTracer { ); @override - set profileInfo(_i9.SentryProfileInfo? _profileInfo) => super.noSuchMethod( + set profileInfo(_i10.SentryProfileInfo? _profileInfo) => super.noSuchMethod( Invocation.setter( #profileInfo, _profileInfo, @@ -711,10 +717,229 @@ class MockSentryTransaction extends _i1.Mock implements _i3.SentryTransaction { ) as _i3.SentryTransaction); } +/// A class which mocks [SentrySpan]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockSentrySpan extends _i1.Mock implements _i3.SentrySpan { + MockSentrySpan() { + _i1.throwOnMissingStub(this); + } + + @override + set status(_i3.SpanStatus? status) => super.noSuchMethod( + Invocation.setter( + #status, + status, + ), + returnValueForMissingStub: null, + ); + + @override + DateTime get startTimestamp => (super.noSuchMethod( + Invocation.getter(#startTimestamp), + returnValue: _FakeDateTime_1( + this, + Invocation.getter(#startTimestamp), + ), + ) as DateTime); + + @override + _i2.SentrySpanContext get context => (super.noSuchMethod( + Invocation.getter(#context), + returnValue: _FakeSentrySpanContext_0( + this, + Invocation.getter(#context), + ), + ) as _i2.SentrySpanContext); + + @override + set origin(String? origin) => super.noSuchMethod( + Invocation.setter( + #origin, + origin, + ), + returnValueForMissingStub: null, + ); + + @override + bool get finished => (super.noSuchMethod( + Invocation.getter(#finished), + returnValue: false, + ) as bool); + + @override + set throwable(dynamic throwable) => super.noSuchMethod( + Invocation.setter( + #throwable, + throwable, + ), + returnValueForMissingStub: null, + ); + + @override + Map get tags => (super.noSuchMethod( + Invocation.getter(#tags), + returnValue: {}, + ) as Map); + + @override + Map get data => (super.noSuchMethod( + Invocation.getter(#data), + returnValue: {}, + ) as Map); + + @override + _i7.Future finish({ + _i3.SpanStatus? status, + DateTime? endTimestamp, + }) => + (super.noSuchMethod( + Invocation.method( + #finish, + [], + { + #status: status, + #endTimestamp: endTimestamp, + }, + ), + returnValue: _i7.Future.value(), + returnValueForMissingStub: _i7.Future.value(), + ) as _i7.Future); + + @override + void removeData(String? key) => super.noSuchMethod( + Invocation.method( + #removeData, + [key], + ), + returnValueForMissingStub: null, + ); + + @override + void removeTag(String? key) => super.noSuchMethod( + Invocation.method( + #removeTag, + [key], + ), + returnValueForMissingStub: null, + ); + + @override + void setData( + String? key, + dynamic value, + ) => + super.noSuchMethod( + Invocation.method( + #setData, + [ + key, + value, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void setTag( + String? key, + String? value, + ) => + super.noSuchMethod( + Invocation.method( + #setTag, + [ + key, + value, + ], + ), + returnValueForMissingStub: null, + ); + + @override + _i2.ISentrySpan startChild( + String? operation, { + String? description, + DateTime? startTimestamp, + }) => + (super.noSuchMethod( + Invocation.method( + #startChild, + [operation], + { + #description: description, + #startTimestamp: startTimestamp, + }, + ), + returnValue: _FakeISentrySpan_2( + this, + Invocation.method( + #startChild, + [operation], + { + #description: description, + #startTimestamp: startTimestamp, + }, + ), + ), + ) as _i2.ISentrySpan); + + @override + Map toJson() => (super.noSuchMethod( + Invocation.method( + #toJson, + [], + ), + returnValue: {}, + ) as Map); + + @override + _i3.SentryTraceHeader toSentryTrace() => (super.noSuchMethod( + Invocation.method( + #toSentryTrace, + [], + ), + returnValue: _FakeSentryTraceHeader_3( + this, + Invocation.method( + #toSentryTrace, + [], + ), + ), + ) as _i3.SentryTraceHeader); + + @override + void setMeasurement( + String? name, + num? value, { + _i2.SentryMeasurementUnit? unit, + }) => + super.noSuchMethod( + Invocation.method( + #setMeasurement, + [ + name, + value, + ], + {#unit: unit}, + ), + returnValueForMissingStub: null, + ); + + @override + void scheduleFinish() => super.noSuchMethod( + Invocation.method( + #scheduleFinish, + [], + ), + returnValueForMissingStub: null, + ); +} + /// A class which mocks [MethodChannel]. /// /// See the documentation for Mockito's code generation for more information. -class MockMethodChannel extends _i1.Mock implements _i10.MethodChannel { +class MockMethodChannel extends _i1.Mock implements _i11.MethodChannel { MockMethodChannel() { _i1.throwOnMissingStub(this); } @@ -722,7 +947,10 @@ class MockMethodChannel extends _i1.Mock implements _i10.MethodChannel { @override String get name => (super.noSuchMethod( Invocation.getter(#name), - returnValue: '', + returnValue: _i9.dummyValue( + this, + Invocation.getter(#name), + ), ) as String); @override @@ -845,7 +1073,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { ) as _i2.Scope); @override - set profilerFactory(_i9.SentryProfilerFactory? value) => super.noSuchMethod( + set profilerFactory(_i10.SentryProfilerFactory? value) => super.noSuchMethod( Invocation.setter( #profilerFactory, value, @@ -1050,7 +1278,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { #customSamplingContext: customSamplingContext, }, ), - returnValue: _i11.startTransactionShim( + returnValue: _i12.startTransactionShim( name, operation, description: description, diff --git a/flutter/test/navigation/time_to_display_tracker_test.dart b/flutter/test/navigation/time_to_display_tracker_test.dart index 942f9ccb35..ca9d0425a0 100644 --- a/flutter/test/navigation/time_to_display_tracker_test.dart +++ b/flutter/test/navigation/time_to_display_tracker_test.dart @@ -1,11 +1,13 @@ // ignore_for_file: invalid_use_of_internal_member // ignore_for_file: inference_failure_on_instance_creation +import 'package:collection/collection.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:sentry_flutter/src/frame_callback_handler.dart'; import 'package:sentry_flutter/src/navigation/time_to_display_tracker.dart'; import 'package:sentry/src/sentry_tracer.dart'; +import 'package:sentry_flutter/src/navigation/time_to_full_display_tracker.dart'; import 'package:sentry_flutter/src/navigation/time_to_initial_display_tracker.dart'; import '../fake_frame_callback_handler.dart'; @@ -23,6 +25,17 @@ void main() { fixture.ttidTracker?.clear(); }); + ISentrySpan? _getTTIDSpan(SentryTracer transaction) { + return transaction.children.firstWhereOrNull((element) => + element.context.operation == + SentrySpanOperations.uiTimeToInitialDisplay); + } + + ISentrySpan? _getTTFDSpan(SentryTracer transaction) { + return transaction.children.firstWhereOrNull((element) => + element.context.operation == SentrySpanOperations.uiTimeToFullDisplay); + } + group('time to initial display', () { group('in root screen app start route', () { test('matches startTimestamp of transaction', () async { @@ -32,14 +45,10 @@ void main() { await sut.trackRegularRouteTTD(transaction, startTimestamp: fixture.startTimestamp); - final ttidSpan = transaction.children - .where((element) => - element.context.operation == - SentrySpanOperations.uiTimeToInitialDisplay) - .first; + final ttidSpan = _getTTIDSpan(transaction); expect(transaction, isNotNull); expect(transaction.context.operation, SentrySpanOperations.uiLoad); - expect(transaction.startTimestamp, ttidSpan.startTimestamp); + expect(transaction.startTimestamp, ttidSpan?.startTimestamp); }); test('finishes ttid span', () async { @@ -52,15 +61,11 @@ void main() { await sut.trackAppStartTTD(transaction, startTimestamp: fixture.startTimestamp, endTimestamp: endTimestamp); - final ttidSpan = transaction.children - .where((element) => - element.context.operation == - SentrySpanOperations.uiTimeToInitialDisplay) - .first; - expect(ttidSpan.context.operation, + final ttidSpan = _getTTIDSpan(transaction); + expect(ttidSpan?.context.operation, SentrySpanOperations.uiTimeToInitialDisplay); - expect(ttidSpan.finished, isTrue); - expect(ttidSpan.origin, SentryTraceOrigins.autoUiTimeToDisplay); + expect(ttidSpan?.finished, isTrue); + expect(ttidSpan?.origin, SentryTraceOrigins.autoUiTimeToDisplay); }); }); @@ -72,14 +77,10 @@ void main() { await sut.trackRegularRouteTTD(transaction, startTimestamp: fixture.startTimestamp); - final ttidSpan = transaction.children - .where((element) => - element.context.operation == - SentrySpanOperations.uiTimeToInitialDisplay) - .first; + final ttidSpan = _getTTIDSpan(transaction); expect(transaction, isNotNull); expect(transaction.context.operation, SentrySpanOperations.uiLoad); - expect(transaction.startTimestamp, ttidSpan.startTimestamp); + expect(transaction.startTimestamp, ttidSpan?.startTimestamp); }); group('with approximation strategy', () { @@ -90,15 +91,11 @@ void main() { await sut.trackRegularRouteTTD(transaction, startTimestamp: fixture.startTimestamp); - final ttidSpan = transaction.children - .where((element) => - element.context.operation == - SentrySpanOperations.uiTimeToInitialDisplay) - .first; - expect(ttidSpan.context.operation, + final ttidSpan = _getTTIDSpan(transaction); + expect(ttidSpan?.context.operation, SentrySpanOperations.uiTimeToInitialDisplay); - expect(ttidSpan.finished, isTrue); - expect(ttidSpan.origin, SentryTraceOrigins.autoUiTimeToDisplay); + expect(ttidSpan?.finished, isTrue); + expect(ttidSpan?.origin, SentryTraceOrigins.autoUiTimeToDisplay); }); test('completes with timeout when not completing the tracking', @@ -123,14 +120,10 @@ void main() { await sut.trackRegularRouteTTD(transaction, startTimestamp: fixture.startTimestamp); - final ttidSpan = transaction.children - .where((element) => - element.context.operation == - SentrySpanOperations.uiTimeToInitialDisplay) - .first; + final ttidSpan = _getTTIDSpan(transaction); expect(ttidSpan, isNotNull); - expect(ttidSpan.finished, isTrue); - expect(ttidSpan.origin, SentryTraceOrigins.manualUiTimeToDisplay); + expect(ttidSpan?.finished, isTrue); + expect(ttidSpan?.origin, SentryTraceOrigins.manualUiTimeToDisplay); }); test('completes with timeout when not completing the tracking', @@ -148,6 +141,108 @@ void main() { }); }); + group('time to full display', () { + setUp(() { + fixture.options.enableTimeToFullDisplayTracing = true; + }); + + group('in regular routes', () { + test( + 'finishes span after timeout with deadline exceeded and ttid matching end time', + () async { + final sut = fixture.getSut(); + final transaction = fixture.getTransaction() as SentryTracer; + + await sut.trackRegularRouteTTD(transaction, + startTimestamp: fixture.startTimestamp); + + final ttidSpan = _getTTIDSpan(transaction); + expect(ttidSpan, isNotNull); + + final ttfdSpan = _getTTFDSpan(transaction); + expect(ttfdSpan?.finished, isTrue); + expect(ttfdSpan?.status, SpanStatus.deadlineExceeded()); + expect(ttfdSpan?.endTimestamp, ttidSpan?.endTimestamp); + expect(ttfdSpan?.startTimestamp, ttidSpan?.startTimestamp); + }); + }); + + group('in root screen app start route', () { + test( + 'finishes span after timeout with deadline exceeded and ttid matching end time', + () async { + final sut = fixture.getSut(); + final transaction = + fixture.getTransaction(name: 'root ("/")') as SentryTracer; + final endTimestamp = + fixture.startTimestamp.add(const Duration(milliseconds: 10)); + + await sut.trackAppStartTTD(transaction, + startTimestamp: fixture.startTimestamp, endTimestamp: endTimestamp); + + final ttidSpan = _getTTIDSpan(transaction); + expect(ttidSpan, isNotNull); + + final ttfdSpan = _getTTFDSpan(transaction); + expect(ttfdSpan, isNotNull); + + expect(ttfdSpan?.finished, isTrue); + expect(ttfdSpan?.status, SpanStatus.deadlineExceeded()); + expect(ttfdSpan?.endTimestamp, ttidSpan?.endTimestamp); + expect(ttfdSpan?.startTimestamp, ttidSpan?.startTimestamp); + }); + }); + + test('multiple ttfd timeouts have correct ttid matching end time', + () async { + final sut = fixture.getSut(); + final transaction = fixture.getTransaction() as SentryTracer; + + // First ttfd timeout + await sut.trackRegularRouteTTD(transaction, + startTimestamp: fixture.startTimestamp); + + final ttidSpanA = _getTTIDSpan(transaction); + expect(ttidSpanA, isNotNull); + + final ttfdSpanA = _getTTFDSpan(transaction); + expect(ttfdSpanA?.finished, isTrue); + expect(ttfdSpanA?.status, SpanStatus.deadlineExceeded()); + expect(ttfdSpanA?.endTimestamp, ttidSpanA?.endTimestamp); + expect(ttfdSpanA?.startTimestamp, ttidSpanA?.startTimestamp); + + // Second ttfd timeout + await sut.trackRegularRouteTTD(transaction, + startTimestamp: fixture.startTimestamp); + + final ttidSpanB = _getTTIDSpan(transaction); + expect(ttidSpanB, isNotNull); + + final ttfdSpanB = _getTTFDSpan(transaction); + expect(ttfdSpanB?.finished, isTrue); + expect(ttfdSpanB?.status, SpanStatus.deadlineExceeded()); + expect(ttfdSpanB?.endTimestamp, ttidSpanB?.endTimestamp); + expect(ttfdSpanB?.startTimestamp, ttidSpanB?.startTimestamp); + }); + + test('does not create ttfd span when not enabled', () async { + fixture.options.enableTimeToFullDisplayTracing = false; + + SentryFlutter.native = TestMockSentryNative(); + final sut = fixture.getSut(); + + final transaction = fixture.getTransaction() as SentryTracer; + + await sut.trackRegularRouteTTD(transaction, + startTimestamp: fixture.startTimestamp); + + final ttfdSpan = transaction.children.firstWhereOrNull((element) => + element.context.operation == + SentrySpanOperations.uiTimeToFullDisplay); + expect(ttfdSpan, isNull); + }); + }); + test('screen load tracking creates ui.load transaction', () async { final sut = fixture.getSut(); @@ -165,9 +260,11 @@ class Fixture { final options = SentryFlutterOptions() ..dsn = fakeDsn ..tracesSampleRate = 1.0; - + late final endTimeProvider = ttidEndTimestampProvider(); late final hub = Hub(options); + TimeToInitialDisplayTracker? ttidTracker; + TimeToFullDisplayTracker? ttfdTracker; ISentrySpan getTransaction({String? name = "Current route"}) { return hub.startTransaction(name!, 'ui.load', @@ -179,8 +276,14 @@ class Fixture { frameCallbackHandler: triggerApproximationTimeout ? DefaultFrameCallbackHandler() : FakeFrameCallbackHandler()); + ttfdTracker = TimeToFullDisplayTracker( + autoFinishAfter: Duration(seconds: 2), + endTimestampProvider: endTimeProvider, + ); return TimeToDisplayTracker( ttidTracker: ttidTracker, + ttfdTracker: ttfdTracker, + enableTimeToFullDisplayTracing: options.enableTimeToFullDisplayTracing, ); } } diff --git a/flutter/test/navigation/time_to_full_display_tracker_test.dart b/flutter/test/navigation/time_to_full_display_tracker_test.dart new file mode 100644 index 0000000000..50609f2692 --- /dev/null +++ b/flutter/test/navigation/time_to_full_display_tracker_test.dart @@ -0,0 +1,87 @@ +// ignore_for_file: invalid_use_of_internal_member + +import 'package:flutter_test/flutter_test.dart'; +import 'package:sentry_flutter/sentry_flutter.dart'; +import 'package:sentry_flutter/src/navigation/time_to_full_display_tracker.dart'; +import 'package:sentry/src/sentry_tracer.dart'; + +import '../mocks.dart'; + +void main() { + late Fixture fixture; + + setUp(() { + fixture = Fixture(); + }); + + test('reportFullyDisplayed() finishes span', () async { + final sut = fixture.getSut(); + final transaction = fixture.getTransaction() as SentryTracer; + const finishAfterDuration = Duration(seconds: 1); + + Future.delayed(finishAfterDuration, () { + sut.reportFullyDisplayed(); + }); + + await sut.track(transaction, fixture.startTimestamp); + + final ttfdSpan = transaction.children.first; + expect(transaction.children, hasLength(1)); + expect(ttfdSpan.context.operation, + equals(SentrySpanOperations.uiTimeToFullDisplay)); + expect(ttfdSpan.finished, isTrue); + expect(ttfdSpan.context.description, equals('Current route full display')); + expect(ttfdSpan.origin, equals(SentryTraceOrigins.manualUiTimeToDisplay)); + expect(ttfdSpan.startTimestamp, equals(fixture.startTimestamp)); + + // Ensure endTimestamp is within an acceptable range + final expectedEndTimestamp = + fixture.startTimestamp.add(finishAfterDuration); + final actualEndTimestamp = ttfdSpan.endTimestamp!; + final differenceInSeconds = + actualEndTimestamp.difference(expectedEndTimestamp).inSeconds.abs(); + expect(differenceInSeconds, lessThanOrEqualTo(1)); + }); + + test( + 'span finishes automatically after timeout with deadline_exceeded status', + () async { + final sut = fixture.getSut(); + final transaction = fixture.getTransaction() as SentryTracer; + + await sut.track(transaction, fixture.startTimestamp); + + final ttfdSpan = transaction.children.first; + expect(transaction.children, hasLength(1)); + expect(ttfdSpan.endTimestamp, equals(fixture.endTimestampProvider())); + expect(ttfdSpan.context.operation, + equals(SentrySpanOperations.uiTimeToFullDisplay)); + expect(ttfdSpan.finished, isTrue); + expect(ttfdSpan.status, equals(SpanStatus.deadlineExceeded())); + expect(ttfdSpan.context.description, equals('Current route full display')); + expect(ttfdSpan.origin, equals(SentryTraceOrigins.manualUiTimeToDisplay)); + }); +} + +class Fixture { + final startTimestamp = getUtcDateTime(); + final hub = Hub(SentryFlutterOptions(dsn: fakeDsn)..tracesSampleRate = 1.0); + final autoFinishAfter = const Duration(seconds: 2); + late final endTimestampProvider = fakeTTIDEndTimestampProvider(); + + ISentrySpan getTransaction({String? name = "Current route"}) { + return hub.startTransaction(name!, SentrySpanOperations.uiLoad, + bindToScope: true, startTimestamp: startTimestamp); + } + + EndTimestampProvider fakeTTIDEndTimestampProvider() => + () => startTimestamp.add(const Duration(seconds: 1)); + + TimeToFullDisplayTracker getSut( + {EndTimestampProvider? endTimestampProvider}) { + endTimestampProvider ??= this.endTimestampProvider; + return TimeToFullDisplayTracker( + endTimestampProvider: endTimestampProvider, + autoFinishAfter: autoFinishAfter); + } +} diff --git a/flutter/test/sentry_navigator_observer_test.dart b/flutter/test/sentry_navigator_observer_test.dart index 5a7528d904..a14255392e 100644 --- a/flutter/test/sentry_navigator_observer_test.dart +++ b/flutter/test/sentry_navigator_observer_test.dart @@ -1,3 +1,5 @@ +// ignore_for_file: invalid_use_of_internal_member + import 'dart:async'; import 'package:flutter/material.dart'; @@ -71,6 +73,7 @@ void main() { final sut = fixture.getSut(hub: mockHub); sut.didPush(currentRoute, null); + await sut.completedDisplayTracking?.future; // Handle internal async method calls. await Future.delayed(const Duration(milliseconds: 10), () { @@ -95,17 +98,15 @@ void main() { final sut = fixture.getSut(hub: hub); sut.didPush(currentRoute, null); + await sut.completedDisplayTracking?.future; // Get ref to created transaction - // ignore: invalid_use_of_internal_member SentryTracer? actualTransaction; hub.configureScope((scope) { - // ignore: invalid_use_of_internal_member actualTransaction = scope.span as SentryTracer; }); - await sut.completedDisplayTracking?.future; - + // Wait for the transaction to finish the async native frame fetching await Future.delayed(Duration(milliseconds: 1500)); expect(mockNativeChannel.numberOfEndNativeFramesCalls, 1); @@ -154,6 +155,7 @@ void main() { ); sut.didPush(currentRoute, null); + await sut.completedDisplayTracking?.future; final context = verify(hub.startTransactionWithContext( captureAny, @@ -172,7 +174,7 @@ void main() { }); }); - test('do not bind transaction to scope if no op', () { + test('do not bind transaction to scope if no op', () async { final currentRoute = route(RouteSettings(name: 'Current Route')); final hub = _MockHub(); @@ -187,6 +189,7 @@ void main() { ); sut.didPush(currentRoute, null); + await sut.completedDisplayTracking?.future; verify(hub.startTransactionWithContext( any, @@ -203,7 +206,7 @@ void main() { }); }); - test('route with empty name does not start transaction', () { + test('route with empty name does not start transaction', () async { final currentRoute = route(null); final hub = _MockHub(); @@ -216,6 +219,7 @@ void main() { final sut = fixture.getSut(hub: hub); sut.didPush(currentRoute, null); + await Future.delayed(const Duration(milliseconds: 100)); verifyNever(hub.startTransactionWithContext( any, @@ -231,7 +235,7 @@ void main() { }); }); - test('no transaction on opt-out', () { + test('no transaction on opt-out', () async { final currentRoute = route(RouteSettings(name: 'Current Route')); final hub = _MockHub(); @@ -298,7 +302,7 @@ void main() { final secondRoute = route(RouteSettings(name: 'Second Route')); final hub = _MockHub(); - final span = getMockSentryTracer(finished: false); + final span = getMockSentryTracer(finished: false) as SentryTracer; when(span.context).thenReturn(SentrySpanContext(operation: 'op')); when(span.status).thenReturn(null); when(span.finished).thenReturn(false); @@ -306,22 +310,27 @@ void main() { description: anyNamed('description'), startTimestamp: anyNamed('startTimestamp'))) .thenReturn(NoOpSentrySpan()); + when(span.children).thenReturn([]); _whenAnyStart(hub, span); final sut = fixture.getSut(hub: hub); sut.didPush(firstRoute, null); sut.didPush(secondRoute, firstRoute); + sut.didPop(secondRoute, null); + + hub.configureScope((scope) { + expect(scope.span, null); + }); - verify(span.status = SpanStatus.ok()); - verify(span.finish()); + verify(span.finish()).called(2); }); test('didPop finishes transaction', () async { final currentRoute = route(RouteSettings(name: 'Current Route')); final hub = _MockHub(); - final span = getMockSentryTracer(finished: false); + final span = getMockSentryTracer(finished: false) as SentryTracer; when(span.context).thenReturn(SentrySpanContext(operation: 'op')); when(span.status).thenReturn(null); when(span.finished).thenReturn(false); @@ -330,36 +339,136 @@ void main() { startTimestamp: anyNamed('startTimestamp'))) .thenReturn(NoOpSentrySpan()); _whenAnyStart(hub, span); + when(span.children).thenReturn([]); final sut = fixture.getSut(hub: hub); sut.didPush(currentRoute, null); sut.didPop(currentRoute, null); - verify(span.status = SpanStatus.ok()); - verify(span.finish()); + hub.configureScope((scope) { + expect(scope.span, null); + }); + + verify(span.finish()).called(1); }); - test('multiple didPop only finish transaction once', () { + test('multiple didPop only finish transaction once', () async { final currentRoute = route(RouteSettings(name: 'Current Route')); final hub = _MockHub(); - final span = getMockSentryTracer(finished: false); + final span = getMockSentryTracer(finished: false) as SentryTracer; when(span.context).thenReturn(SentrySpanContext(operation: 'op')); when(span.status).thenReturn(null); + when(span.children).thenReturn([]); + when(span.startChild('ui.load.initial_display', + description: anyNamed('description'), + startTimestamp: anyNamed('startTimestamp'))) + .thenReturn(NoOpSentrySpan()); _whenAnyStart(hub, span); final sut = fixture.getSut(hub: hub); sut.didPush(currentRoute, null); + await sut.completedDisplayTracking?.future; sut.didPop(currentRoute, null); sut.didPop(currentRoute, null); + hub.configureScope((scope) { + expect(scope.span, null); + }); + verify(span.finish()).called(1); }); - test('route arguments are set on transaction', () { + test( + 'unfinished children will be finished with deadline_exceeded on didPush', + () async { + final currentRoute = route(RouteSettings(name: 'Current Route')); + + final hub = _MockHub(); + final span = getMockSentryTracer(finished: false) as SentryTracer; + final mockChildA = MockSentrySpan(); + final mockChildB = MockSentrySpan(); + when(span.children).thenReturn([ + mockChildB, + mockChildA, + ]); + when(mockChildA.finished).thenReturn(false); + when(mockChildB.finished).thenReturn(false); + when(mockChildA.context).thenReturn(SentrySpanContext( + operation: SentrySpanOperations.uiTimeToInitialDisplay)); + when(mockChildB.context).thenReturn(SentrySpanContext( + operation: SentrySpanOperations.uiTimeToFullDisplay)); + when(span.context).thenReturn(SentrySpanContext(operation: 'op')); + when(span.status).thenReturn(null); + when(span.startChild('ui.load.initial_display', + description: anyNamed('description'), + startTimestamp: anyNamed('startTimestamp'))) + .thenReturn(NoOpSentrySpan()); + _whenAnyStart(hub, span); + + final sut = fixture.getSut(hub: hub); + + // Push to new screen, e.g app start / root screen + sut.didPush(currentRoute, null); + + // Push to screen e.g root to user screen + sut.didPush(currentRoute, null); + + await Future.delayed(const Duration(milliseconds: 100)); + + verify(mockChildA.finish(status: SpanStatus.deadlineExceeded())) + .called(1); + verify(mockChildB.finish(status: SpanStatus.deadlineExceeded())) + .called(1); + }); + + test( + 'unfinished children will be finished with deadline_exceeded on didPop', + () async { + final currentRoute = route(RouteSettings(name: 'Current Route')); + + final hub = _MockHub(); + final span = getMockSentryTracer(finished: false) as SentryTracer; + final mockChildA = MockSentrySpan(); + final mockChildB = MockSentrySpan(); + when(span.children).thenReturn([ + mockChildB, + mockChildA, + ]); + when(mockChildA.finished).thenReturn(false); + when(mockChildB.finished).thenReturn(false); + when(mockChildA.context).thenReturn(SentrySpanContext( + operation: SentrySpanOperations.uiTimeToInitialDisplay)); + when(mockChildB.context).thenReturn(SentrySpanContext( + operation: SentrySpanOperations.uiTimeToFullDisplay)); + when(span.context).thenReturn(SentrySpanContext(operation: 'op')); + when(span.status).thenReturn(null); + when(span.startChild('ui.load.initial_display', + description: anyNamed('description'), + startTimestamp: anyNamed('startTimestamp'))) + .thenReturn(NoOpSentrySpan()); + _whenAnyStart(hub, span); + + final sut = fixture.getSut(hub: hub); + + // Push to new screen, e.g root to user screen + sut.didPush(currentRoute, null); + + // Pop back e.g user to root screen + sut.didPop(currentRoute, null); + + await Future.delayed(const Duration(milliseconds: 100)); + + verify(mockChildA.finish(status: SpanStatus.deadlineExceeded())) + .called(1); + verify(mockChildB.finish(status: SpanStatus.deadlineExceeded())) + .called(1); + }); + + test('route arguments are set on transaction', () async { final arguments = {'foo': 'bar'}; final currentRoute = route(RouteSettings( name: 'Current Route', @@ -380,6 +489,7 @@ void main() { final sut = fixture.getSut(hub: hub); sut.didPush(currentRoute, null); + await sut.completedDisplayTracking?.future; verify(span.setData('route_settings_arguments', arguments)); }); @@ -427,7 +537,7 @@ void main() { }); }); - test('didPush sets current route name', () { + test('didPush sets current route name', () async { const name = 'Current Route'; final currentRoute = route(RouteSettings(name: name)); @@ -449,6 +559,7 @@ void main() { ); sut.didPush(currentRoute, null); + await sut.completedDisplayTracking?.future; expect(SentryNavigatorObserver.currentRouteName, 'Current Route'); }); @@ -881,12 +992,14 @@ class Fixture { bool setRouteNameAsTransaction = false, RouteNameExtractor? routeNameExtractor, AdditionalInfoExtractor? additionalInfoProvider, + bool enableTimeToFullDisplayTracing = false, }) { final frameCallbackHandler = FakeFrameCallbackHandler(); final timeToInitialDisplayTracker = TimeToInitialDisplayTracker(frameCallbackHandler: frameCallbackHandler); final timeToDisplayTracker = TimeToDisplayTracker( ttidTracker: timeToInitialDisplayTracker, + enableTimeToFullDisplayTracing: enableTimeToFullDisplayTracing, ); return SentryNavigatorObserver( hub: hub, From 3d30a22249004507db207dc2805210789e8e4b31 Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Wed, 13 Mar 2024 13:58:57 +0100 Subject: [PATCH 113/237] Update token usage (#1933) --- .github/workflows/e2e_dart.yml | 2 +- e2e_test/bin/e2e_test.dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/e2e_dart.yml b/.github/workflows/e2e_dart.yml index 64a2644940..8fb62ce108 100644 --- a/.github/workflows/e2e_dart.yml +++ b/.github/workflows/e2e_dart.yml @@ -13,7 +13,7 @@ on: - "e2e_test/**" env: - SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} + SENTRY_AUTH_TOKEN_E2E: ${{ secrets.SENTRY_AUTH_TOKEN_E2E }} SENTRY_DIST: 1 jobs: diff --git a/e2e_test/bin/e2e_test.dart b/e2e_test/bin/e2e_test.dart index d8d315c5e3..fff4d320ee 100644 --- a/e2e_test/bin/e2e_test.dart +++ b/e2e_test/bin/e2e_test.dart @@ -10,7 +10,7 @@ const _exampleDsn = const _org = 'sentry-sdks'; const _projectSlug = 'sentry-flutter'; -final _token = Platform.environment['SENTRY_AUTH_TOKEN'] ?? ''; +final _token = Platform.environment['SENTRY_AUTH_TOKEN_E2E'] ?? ''; void main(List arguments) async { print('Starting'); From e3d907610f0ed42d69327a69823a52e93a8b18be Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Wed, 13 Mar 2024 17:22:59 +0100 Subject: [PATCH 114/237] Update root name (#1934) * Update root name * Update root name * update --- CHANGELOG.md | 7 ++++++- flutter/lib/src/navigation/sentry_navigator_observer.dart | 2 +- flutter/test/navigation/sentry_display_widget_test.dart | 2 +- flutter/test/sentry_navigator_observer_test.dart | 2 +- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 04cb41f568..2308bf0d97 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## Unreleased -## Features +### Features - Add TTFD (time to full display), which allows you to measure the time it takes to render the full screen ([#1920](https://github.com/getsentry/sentry-dart/pull/1920)) - Requires using the [routing instrumentation](https://docs.sentry.io/platforms/flutter/integrations/routing-instrumentation/). @@ -23,6 +23,11 @@ - The `dio` integration and `SentryHttpClient` now take an additional `captureFailedRequests` option. - This is useful if you want to disable this option on native and only enable it on `dio` for example. +### Improvements + +- Update root name for navigator observer ([#1934](https://github.com/getsentry/sentry-dart/pull/1934)) + - The root name for transactions is now `root /` instead of `root ("/")`. + ### Dependencies - Bump Android SDK from v7.5.0 to v7.6.0 ([#1927](https://github.com/getsentry/sentry-dart/pull/1927)) diff --git a/flutter/lib/src/navigation/sentry_navigator_observer.dart b/flutter/lib/src/navigation/sentry_navigator_observer.dart index 0af0a76381..aaa4c86889 100644 --- a/flutter/lib/src/navigation/sentry_navigator_observer.dart +++ b/flutter/lib/src/navigation/sentry_navigator_observer.dart @@ -224,7 +224,7 @@ class SentryNavigatorObserver extends RouteObserver> { } if (name == '/') { - name = 'root ("/")'; + name = 'root /'; } final transactionContext = SentryTransactionContext( name, diff --git a/flutter/test/navigation/sentry_display_widget_test.dart b/flutter/test/navigation/sentry_display_widget_test.dart index 6fb61c5b8f..b9c2eb37cb 100644 --- a/flutter/test/navigation/sentry_display_widget_test.dart +++ b/flutter/test/navigation/sentry_display_widget_test.dart @@ -81,7 +81,7 @@ void main() { expect(ttidSpan.context.operation, SentrySpanOperations.uiTimeToInitialDisplay); expect(ttidSpan.finished, isTrue); - expect(ttidSpan.context.description, 'root ("/") initial display'); + expect(ttidSpan.context.description, 'root / initial display'); expect(ttidSpan.origin, SentryTraceOrigins.autoUiTimeToDisplay); expect(ttidSpan.startTimestamp, appStartInfo.start); diff --git a/flutter/test/sentry_navigator_observer_test.dart b/flutter/test/sentry_navigator_observer_test.dart index a14255392e..1b41833e20 100644 --- a/flutter/test/sentry_navigator_observer_test.dart +++ b/flutter/test/sentry_navigator_observer_test.dart @@ -530,7 +530,7 @@ void main() { onFinish: anyNamed('onFinish'), )).captured.single as SentryTransactionContext; - expect(context.name, 'root ("/")'); + expect(context.name, 'root /'); hub.configureScope((scope) { expect(scope.span, span); From 7a03d7b5fe0c0caaea3e0f2e221c320af51b0ba5 Mon Sep 17 00:00:00 2001 From: getsentry-bot Date: Wed, 13 Mar 2024 16:23:49 +0000 Subject: [PATCH 115/237] release: 7.18.0 --- CHANGELOG.md | 4 ++-- dart/lib/src/version.dart | 2 +- dart/pubspec.yaml | 2 +- dio/lib/src/version.dart | 2 +- dio/pubspec.yaml | 4 ++-- drift/lib/src/version.dart | 2 +- drift/pubspec.yaml | 4 ++-- file/lib/src/version.dart | 2 +- file/pubspec.yaml | 4 ++-- flutter/example/pubspec.yaml | 2 +- flutter/lib/src/version.dart | 2 +- flutter/pubspec.yaml | 4 ++-- hive/lib/src/version.dart | 2 +- hive/pubspec.yaml | 4 ++-- isar/lib/src/version.dart | 2 +- isar/pubspec.yaml | 4 ++-- logging/lib/src/version.dart | 2 +- logging/pubspec.yaml | 4 ++-- sqflite/lib/src/version.dart | 2 +- sqflite/pubspec.yaml | 4 ++-- 20 files changed, 29 insertions(+), 29 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2308bf0d97..377e11c086 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog -## Unreleased - +## 7.18.0 + ### Features - Add TTFD (time to full display), which allows you to measure the time it takes to render the full screen ([#1920](https://github.com/getsentry/sentry-dart/pull/1920)) diff --git a/dart/lib/src/version.dart b/dart/lib/src/version.dart index cbb5949ed5..4f568f22fe 100644 --- a/dart/lib/src/version.dart +++ b/dart/lib/src/version.dart @@ -9,7 +9,7 @@ library version; /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.17.0'; +const String sdkVersion = '7.18.0'; String sdkName(bool isWeb) => isWeb ? _browserSdkName : _ioSdkName; diff --git a/dart/pubspec.yaml b/dart/pubspec.yaml index 013c29b763..077d25aefa 100644 --- a/dart/pubspec.yaml +++ b/dart/pubspec.yaml @@ -1,5 +1,5 @@ name: sentry -version: 7.17.0 +version: 7.18.0 description: > A crash reporting library for Dart that sends crash reports to Sentry.io. This library supports Dart VM and Web. For Flutter consider sentry_flutter instead. diff --git a/dio/lib/src/version.dart b/dio/lib/src/version.dart index 2301db53a9..cea3633864 100644 --- a/dio/lib/src/version.dart +++ b/dio/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.17.0'; +const String sdkVersion = '7.18.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_dio'; diff --git a/dio/pubspec.yaml b/dio/pubspec.yaml index bc0d739009..4ef132dbb7 100644 --- a/dio/pubspec.yaml +++ b/dio/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_dio description: An integration which adds support for performance tracing for the Dio package. -version: 7.17.0 +version: 7.18.0 homepage: https://docs.sentry.io/platforms/dart/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -11,7 +11,7 @@ environment: dependencies: dio: ^5.0.0 - sentry: 7.17.0 + sentry: 7.18.0 dev_dependencies: meta: ^1.3.0 diff --git a/drift/lib/src/version.dart b/drift/lib/src/version.dart index f2d0fec3bd..3cd30a54ba 100644 --- a/drift/lib/src/version.dart +++ b/drift/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.17.0'; +const String sdkVersion = '7.18.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_drift'; diff --git a/drift/pubspec.yaml b/drift/pubspec.yaml index e60fb873d1..5fe411b5f1 100644 --- a/drift/pubspec.yaml +++ b/drift/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_drift description: An integration which adds support for performance tracing for the drift package. -version: 7.17.0 +version: 7.18.0 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -9,7 +9,7 @@ environment: sdk: '>=2.17.0 <4.0.0' dependencies: - sentry: 7.17.0 + sentry: 7.18.0 meta: ^1.3.0 drift: ^2.13.0 diff --git a/file/lib/src/version.dart b/file/lib/src/version.dart index 6b00da4fb7..c2a34fa8c9 100644 --- a/file/lib/src/version.dart +++ b/file/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.17.0'; +const String sdkVersion = '7.18.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_file'; diff --git a/file/pubspec.yaml b/file/pubspec.yaml index 147fd84f33..cc7adacc4e 100644 --- a/file/pubspec.yaml +++ b/file/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_file description: An integration which adds support for performance tracing for dart.io.File. -version: 7.17.0 +version: 7.18.0 homepage: https://docs.sentry.io/platforms/dart/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -10,7 +10,7 @@ environment: sdk: '>=2.19.0 <4.0.0' dependencies: - sentry: 7.17.0 + sentry: 7.18.0 meta: ^1.3.0 dev_dependencies: diff --git a/flutter/example/pubspec.yaml b/flutter/example/pubspec.yaml index 4215e2ce1d..3d09b42741 100644 --- a/flutter/example/pubspec.yaml +++ b/flutter/example/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_flutter_example description: Demonstrates how to use the sentry_flutter plugin. -version: 7.17.0 +version: 7.18.0 publish_to: 'none' # Remove this line if you wish to publish to pub.dev diff --git a/flutter/lib/src/version.dart b/flutter/lib/src/version.dart index 9f513504fd..d44390a826 100644 --- a/flutter/lib/src/version.dart +++ b/flutter/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.17.0'; +const String sdkVersion = '7.18.0'; /// The default SDK name reported to Sentry.io in the submitted events. const String sdkName = 'sentry.dart.flutter'; diff --git a/flutter/pubspec.yaml b/flutter/pubspec.yaml index e3b07cb26d..74231742ab 100644 --- a/flutter/pubspec.yaml +++ b/flutter/pubspec.yaml @@ -1,5 +1,5 @@ name: sentry_flutter -version: 7.17.0 +version: 7.18.0 description: Sentry SDK for Flutter. This package aims to support different Flutter targets by relying on the many platforms supported by Sentry with native SDKs. homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart @@ -15,7 +15,7 @@ dependencies: sdk: flutter flutter_web_plugins: sdk: flutter - sentry: 7.17.0 + sentry: 7.18.0 package_info_plus: '>=1.0.0 <=5.0.1' meta: ^1.3.0 ffi: ^2.0.0 diff --git a/hive/lib/src/version.dart b/hive/lib/src/version.dart index a84bcd2db0..89edc4dc0b 100644 --- a/hive/lib/src/version.dart +++ b/hive/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.17.0'; +const String sdkVersion = '7.18.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_hive'; diff --git a/hive/pubspec.yaml b/hive/pubspec.yaml index 456b9fb520..4d65143ac2 100644 --- a/hive/pubspec.yaml +++ b/hive/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_hive description: An integration which adds support for performance tracing for the hive package. -version: 7.17.0 +version: 7.18.0 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -9,7 +9,7 @@ environment: sdk: '>=2.17.0 <4.0.0' dependencies: - sentry: 7.17.0 + sentry: 7.18.0 hive: ^2.2.3 meta: ^1.3.0 diff --git a/isar/lib/src/version.dart b/isar/lib/src/version.dart index e9df915ff7..bd4ec9f9f2 100644 --- a/isar/lib/src/version.dart +++ b/isar/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.17.0'; +const String sdkVersion = '7.18.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_isar'; diff --git a/isar/pubspec.yaml b/isar/pubspec.yaml index 869fd08835..3cfdb66795 100644 --- a/isar/pubspec.yaml +++ b/isar/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_isar description: An integration which adds support for performance tracing for the isar package. -version: 7.17.0 +version: 7.18.0 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -12,7 +12,7 @@ environment: dependencies: isar: ^3.1.0 isar_flutter_libs: ^3.1.0 # contains Isar Core - sentry: 7.17.0 + sentry: 7.18.0 meta: ^1.3.0 path: ^1.8.3 diff --git a/logging/lib/src/version.dart b/logging/lib/src/version.dart index 2a83deadcc..6e8151ee32 100644 --- a/logging/lib/src/version.dart +++ b/logging/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.17.0'; +const String sdkVersion = '7.18.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_logging'; diff --git a/logging/pubspec.yaml b/logging/pubspec.yaml index 3601790850..f9f6d86e50 100644 --- a/logging/pubspec.yaml +++ b/logging/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_logging description: An integration which adds support for recording log from the logging package. -version: 7.17.0 +version: 7.18.0 homepage: https://docs.sentry.io/platforms/dart/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -11,7 +11,7 @@ environment: dependencies: logging: ^1.0.0 - sentry: 7.17.0 + sentry: 7.18.0 dev_dependencies: lints: ^3.0.0 diff --git a/sqflite/lib/src/version.dart b/sqflite/lib/src/version.dart index ab2d4a6533..6b0a9b5b24 100644 --- a/sqflite/lib/src/version.dart +++ b/sqflite/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.17.0'; +const String sdkVersion = '7.18.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_sqflite'; diff --git a/sqflite/pubspec.yaml b/sqflite/pubspec.yaml index e743e9e128..bdf8a4441a 100644 --- a/sqflite/pubspec.yaml +++ b/sqflite/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_sqflite description: An integration which adds support for performance tracing for the sqflite package. -version: 7.17.0 +version: 7.18.0 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -10,7 +10,7 @@ environment: flutter: '>=3.3.0' # matching sqflite dependencies: - sentry: 7.17.0 + sentry: 7.18.0 sqflite: ^2.0.0 sqflite_common: ^2.0.0 meta: ^1.3.0 From df926cb312cf6fde805618bb0caa0799c956d19d Mon Sep 17 00:00:00 2001 From: Karl Heinz Struggl Date: Wed, 13 Mar 2024 10:02:35 -0700 Subject: [PATCH 116/237] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 377e11c086..7f2888c43e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,7 +43,7 @@ - remove transitive dart:io reference for web ([#1898](https://github.com/getsentry/sentry-dart/pull/1898)) ### Features -- + - Use `recordHttpBreadcrumbs` to set iOS `enableNetworkBreadcrumbs` ([#1884](https://github.com/getsentry/sentry-dart/pull/1884)) - Apply `beforeBreadcrumb` on native iOS crumbs ([#1914](https://github.com/getsentry/sentry-dart/pull/1914)) - Add `maxQueueSize` to limit the number of unawaited events sent to Sentry ([#1868](https://github.com/getsentry/sentry-dart/pull/1868)) From 29297d43a910bfd6a6932ecb456e70aac411508a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20Andra=C5=A1ec?= Date: Mon, 25 Mar 2024 13:52:28 +0000 Subject: [PATCH 117/237] Set `sentry_flutter.podspec` version from `pubspec.yaml` (#1941) --- CHANGELOG.md | 6 ++++++ flutter/ios/sentry_flutter.podspec | 6 +++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f2888c43e..7dd320dab5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## Unreleased + +### Improvements + +- Set `sentry_flutter.podspec` version from `pubspec.yaml` ([#1941](https://github.com/getsentry/sentry-dart/pull/1941)) + ## 7.18.0 ### Features diff --git a/flutter/ios/sentry_flutter.podspec b/flutter/ios/sentry_flutter.podspec index dd9e94d81c..c55470dc37 100644 --- a/flutter/ios/sentry_flutter.podspec +++ b/flutter/ios/sentry_flutter.podspec @@ -1,6 +1,10 @@ +require 'yaml' +pubspec = YAML.load_file('./../pubspec.yaml') +version = pubspec['version'].to_s + Pod::Spec.new do |s| s.name = 'sentry_flutter' - s.version = '0.0.1' + s.version = version s.summary = 'Sentry SDK for Flutter.' s.description = <<-DESC Sentry SDK for Flutter with support to native through sentry-cocoa. From 5152a56dc09336dbdb96a3058feadeba3e3bb02c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20Andra=C5=A1ec?= Date: Tue, 26 Mar 2024 15:37:50 +0000 Subject: [PATCH 118/237] Bump `package_info_plus` (#1948) --- flutter/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flutter/pubspec.yaml b/flutter/pubspec.yaml index 74231742ab..1627f1260c 100644 --- a/flutter/pubspec.yaml +++ b/flutter/pubspec.yaml @@ -16,7 +16,7 @@ dependencies: flutter_web_plugins: sdk: flutter sentry: 7.18.0 - package_info_plus: '>=1.0.0 <=5.0.1' + package_info_plus: '>=1.0.0 <7.0.0' meta: ^1.3.0 ffi: ^2.0.0 From 517cde554116b57e6ad0e8e7bc3ebbfe0f6ba561 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Apr 2024 10:48:28 +0200 Subject: [PATCH 119/237] build(deps): bump subosito/flutter-action from 2.13.0 to 2.15.0 (#1964) Bumps [subosito/flutter-action](https://github.com/subosito/flutter-action) from 2.13.0 to 2.15.0. - [Release notes](https://github.com/subosito/flutter-action/releases) - [Commits](https://github.com/subosito/flutter-action/compare/62f096cacda5168a3bd7b95793373be14fa4fbaf...3d804929922b667a63a229bc59037807f969e885) --- updated-dependencies: - dependency-name: subosito/flutter-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/analyze.yml | 2 +- .github/workflows/drift.yml | 2 +- .github/workflows/flutter.yml | 2 +- .github/workflows/flutter_test.yml | 4 ++-- .github/workflows/format-and-fix.yml | 2 +- .github/workflows/isar.yml | 2 +- .github/workflows/metrics.yml | 2 +- .github/workflows/min_version_test.yml | 6 +++--- .github/workflows/sqflite.yml | 2 +- .github/workflows/web-example-ghpages.yml | 2 +- 10 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/analyze.yml b/.github/workflows/analyze.yml index 683aac6c68..97e903647f 100644 --- a/.github/workflows/analyze.yml +++ b/.github/workflows/analyze.yml @@ -34,7 +34,7 @@ jobs: - uses: actions/checkout@v4 - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 # pin@v1 if: ${{ inputs.sdk == 'dart' }} - - uses: subosito/flutter-action@62f096cacda5168a3bd7b95793373be14fa4fbaf # pin@v2.13.0 + - uses: subosito/flutter-action@3d804929922b667a63a229bc59037807f969e885 # pin@v2.15.0 if: ${{ inputs.sdk == 'flutter' }} - run: ${{ inputs.sdk }} pub get diff --git a/.github/workflows/drift.yml b/.github/workflows/drift.yml index dc8aff24f6..d86a5138cb 100644 --- a/.github/workflows/drift.yml +++ b/.github/workflows/drift.yml @@ -77,7 +77,7 @@ jobs: sudo apt install -y network-manager upower if: matrix.os == 'ubuntu-latest' && matrix.target == 'linux' - - uses: subosito/flutter-action@62f096cacda5168a3bd7b95793373be14fa4fbaf # pin@v2.13.0 + - uses: subosito/flutter-action@3d804929922b667a63a229bc59037807f969e885 # pin@v2.15.0 with: channel: ${{ matrix.sdk }} diff --git a/.github/workflows/flutter.yml b/.github/workflows/flutter.yml index ef0ac1d8e1..3e78309c73 100644 --- a/.github/workflows/flutter.yml +++ b/.github/workflows/flutter.yml @@ -82,7 +82,7 @@ jobs: sudo apt install -y network-manager upower if: matrix.os == 'ubuntu-latest' && matrix.target == 'linux' - - uses: subosito/flutter-action@62f096cacda5168a3bd7b95793373be14fa4fbaf # pin@v2.13.0 + - uses: subosito/flutter-action@3d804929922b667a63a229bc59037807f969e885 # pin@v2.15.0 with: channel: ${{ matrix.sdk }} diff --git a/.github/workflows/flutter_test.yml b/.github/workflows/flutter_test.yml index 375740e5dd..f3bd5dfb8b 100644 --- a/.github/workflows/flutter_test.yml +++ b/.github/workflows/flutter_test.yml @@ -43,7 +43,7 @@ jobs: distribution: "adopt" java-version: "11" - - uses: subosito/flutter-action@62f096cacda5168a3bd7b95793373be14fa4fbaf # pin@v2.13.0 + - uses: subosito/flutter-action@3d804929922b667a63a229bc59037807f969e885 # pin@v2.15.0 with: channel: ${{ matrix.sdk }} @@ -126,7 +126,7 @@ jobs: - name: checkout uses: actions/checkout@v4 - - uses: subosito/flutter-action@62f096cacda5168a3bd7b95793373be14fa4fbaf # pin@v2.13.0 + - uses: subosito/flutter-action@3d804929922b667a63a229bc59037807f969e885 # pin@v2.15.0 with: channel: ${{ matrix.sdk }} diff --git a/.github/workflows/format-and-fix.yml b/.github/workflows/format-and-fix.yml index 9aa90f671b..ad9d2fef9b 100644 --- a/.github/workflows/format-and-fix.yml +++ b/.github/workflows/format-and-fix.yml @@ -32,7 +32,7 @@ jobs: - uses: actions/checkout@v4 - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 # pin@v1 if: ${{ matrix.package.sdk == 'dart' }} - - uses: subosito/flutter-action@62f096cacda5168a3bd7b95793373be14fa4fbaf # pin@v2.13.0 + - uses: subosito/flutter-action@3d804929922b667a63a229bc59037807f969e885 # pin@v2.15.0 if: ${{ matrix.package.sdk == 'flutter' }} - run: ${{ matrix.package.sdk }} pub get diff --git a/.github/workflows/isar.yml b/.github/workflows/isar.yml index afe43d69af..94d08f9cdc 100644 --- a/.github/workflows/isar.yml +++ b/.github/workflows/isar.yml @@ -77,7 +77,7 @@ jobs: sudo apt install -y network-manager upower if: matrix.os == 'ubuntu-latest' && matrix.target == 'linux' - - uses: subosito/flutter-action@62f096cacda5168a3bd7b95793373be14fa4fbaf # pin@v2.13.0 + - uses: subosito/flutter-action@3d804929922b667a63a229bc59037807f969e885 # pin@v2.15.0 with: channel: ${{ matrix.sdk }} diff --git a/.github/workflows/metrics.yml b/.github/workflows/metrics.yml index 05fa327d35..2af1f3989a 100644 --- a/.github/workflows/metrics.yml +++ b/.github/workflows/metrics.yml @@ -53,7 +53,7 @@ jobs: echo "flutter=$version" >> "$GITHUB_OUTPUT" - name: Install Flutter v${{ steps.conf.outputs.flutter }} - uses: subosito/flutter-action@62f096cacda5168a3bd7b95793373be14fa4fbaf # pin@v2.13.0 + uses: subosito/flutter-action@3d804929922b667a63a229bc59037807f969e885 # pin@v2.15.0 with: flutter-version: ${{ steps.conf.outputs.flutter }} diff --git a/.github/workflows/min_version_test.yml b/.github/workflows/min_version_test.yml index 08d108309b..b2f6376d90 100644 --- a/.github/workflows/min_version_test.yml +++ b/.github/workflows/min_version_test.yml @@ -34,7 +34,7 @@ jobs: distribution: "adopt" java-version: "11" - - uses: subosito/flutter-action@62f096cacda5168a3bd7b95793373be14fa4fbaf # pin@v2.13.0 + - uses: subosito/flutter-action@3d804929922b667a63a229bc59037807f969e885 # pin@v2.15.0 with: flutter-version: "3.0.0" @@ -51,7 +51,7 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: subosito/flutter-action@62f096cacda5168a3bd7b95793373be14fa4fbaf # pin@v2.13.0 + - uses: subosito/flutter-action@3d804929922b667a63a229bc59037807f969e885 # pin@v2.15.0 with: flutter-version: "3.0.0" @@ -68,7 +68,7 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: subosito/flutter-action@62f096cacda5168a3bd7b95793373be14fa4fbaf # pin@v2.13.0 + - uses: subosito/flutter-action@3d804929922b667a63a229bc59037807f969e885 # pin@v2.15.0 with: flutter-version: "3.0.0" diff --git a/.github/workflows/sqflite.yml b/.github/workflows/sqflite.yml index 57c21613b8..39e51d80e4 100644 --- a/.github/workflows/sqflite.yml +++ b/.github/workflows/sqflite.yml @@ -77,7 +77,7 @@ jobs: sudo apt install -y network-manager upower if: matrix.os == 'ubuntu-latest' && matrix.target == 'linux' - - uses: subosito/flutter-action@62f096cacda5168a3bd7b95793373be14fa4fbaf # pin@v2.13.0 + - uses: subosito/flutter-action@3d804929922b667a63a229bc59037807f969e885 # pin@v2.15.0 with: channel: ${{ matrix.sdk }} diff --git a/.github/workflows/web-example-ghpages.yml b/.github/workflows/web-example-ghpages.yml index 6dcbd84e6f..ce18da720e 100644 --- a/.github/workflows/web-example-ghpages.yml +++ b/.github/workflows/web-example-ghpages.yml @@ -14,7 +14,7 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: subosito/flutter-action@62f096cacda5168a3bd7b95793373be14fa4fbaf # pin@v2.13.0 + - uses: subosito/flutter-action@3d804929922b667a63a229bc59037807f969e885 # pin@v2.15.0 - uses: bluefireteam/flutter-gh-pages@57815b17b371455ec1a98f075b71b4c6ba0a938c # pin@v8 with: workingDir: flutter/example From 5b5f839ef09c791cab57ff3dc142b0491e52f5b1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Apr 2024 12:43:40 +0200 Subject: [PATCH 120/237] build(deps): bump codecov/codecov-action from 4.1.0 to 4.1.1 (#1963) Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 4.1.0 to 4.1.1. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/54bcd8715eee62d40e33596ef5e8f0f48dbbccab...c16abc29c95fcf9174b58eb7e1abf4c866893bc8) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Stefano --- .github/workflows/dart.yml | 2 +- .github/workflows/dio.yml | 2 +- .github/workflows/drift.yml | 2 +- .github/workflows/file.yml | 2 +- .github/workflows/flutter.yml | 2 +- .github/workflows/hive.yml | 2 +- .github/workflows/isar.yml | 2 +- .github/workflows/logging.yml | 2 +- .github/workflows/sqflite.yml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml index 6a26645df1..28a4ecb093 100644 --- a/.github/workflows/dart.yml +++ b/.github/workflows/dart.yml @@ -68,7 +68,7 @@ jobs: dart pub get webdev build - - uses: codecov/codecov-action@54bcd8715eee62d40e33596ef5e8f0f48dbbccab # pin@v3 + - uses: codecov/codecov-action@c16abc29c95fcf9174b58eb7e1abf4c866893bc8 # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: name: sentry diff --git a/.github/workflows/dio.yml b/.github/workflows/dio.yml index a7fd996216..e2dfaa8a67 100644 --- a/.github/workflows/dio.yml +++ b/.github/workflows/dio.yml @@ -52,7 +52,7 @@ jobs: dart test -p vm --coverage=coverage --test-randomize-ordering-seed=random --chain-stack-traces dart pub run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.dart_tool/package_config.json --report-on=lib - - uses: codecov/codecov-action@54bcd8715eee62d40e33596ef5e8f0f48dbbccab # pin@v3 + - uses: codecov/codecov-action@c16abc29c95fcf9174b58eb7e1abf4c866893bc8 # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: name: sentry_dio diff --git a/.github/workflows/drift.yml b/.github/workflows/drift.yml index d86a5138cb..79f9ee9a5a 100644 --- a/.github/workflows/drift.yml +++ b/.github/workflows/drift.yml @@ -93,7 +93,7 @@ jobs: cd drift flutter test --coverage --test-randomize-ordering-seed=random - - uses: codecov/codecov-action@54bcd8715eee62d40e33596ef5e8f0f48dbbccab # pin@v3 + - uses: codecov/codecov-action@c16abc29c95fcf9174b58eb7e1abf4c866893bc8 # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' with: name: sentry_drift diff --git a/.github/workflows/file.yml b/.github/workflows/file.yml index 56356cedc6..7caf2b2f78 100644 --- a/.github/workflows/file.yml +++ b/.github/workflows/file.yml @@ -52,7 +52,7 @@ jobs: dart test -p vm --coverage=coverage --test-randomize-ordering-seed=random --chain-stack-traces dart pub run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.dart_tool/package_config.json --report-on=lib - - uses: codecov/codecov-action@54bcd8715eee62d40e33596ef5e8f0f48dbbccab # pin@v3 + - uses: codecov/codecov-action@c16abc29c95fcf9174b58eb7e1abf4c866893bc8 # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: name: sentry_file diff --git a/.github/workflows/flutter.yml b/.github/workflows/flutter.yml index 3e78309c73..96db102fcc 100644 --- a/.github/workflows/flutter.yml +++ b/.github/workflows/flutter.yml @@ -112,7 +112,7 @@ jobs: flutter test --coverage --test-randomize-ordering-seed=random dart run remove_from_coverage -f coverage/lcov.info -r 'binding.dart' - - uses: codecov/codecov-action@54bcd8715eee62d40e33596ef5e8f0f48dbbccab # pin@v3 + - uses: codecov/codecov-action@c16abc29c95fcf9174b58eb7e1abf4c866893bc8 # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' with: name: sentry_flutter diff --git a/.github/workflows/hive.yml b/.github/workflows/hive.yml index 4d2d177b31..da903ef0c8 100644 --- a/.github/workflows/hive.yml +++ b/.github/workflows/hive.yml @@ -51,7 +51,7 @@ jobs: dart test -p vm --coverage=coverage --test-randomize-ordering-seed=random --chain-stack-traces dart pub run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.dart_tool/package_config.json --report-on=lib - - uses: codecov/codecov-action@54bcd8715eee62d40e33596ef5e8f0f48dbbccab # pin@v3 + - uses: codecov/codecov-action@c16abc29c95fcf9174b58eb7e1abf4c866893bc8 # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: name: sentry_hive diff --git a/.github/workflows/isar.yml b/.github/workflows/isar.yml index 94d08f9cdc..4687defc4d 100644 --- a/.github/workflows/isar.yml +++ b/.github/workflows/isar.yml @@ -93,7 +93,7 @@ jobs: cd isar flutter test -j 1 --coverage --test-randomize-ordering-seed=random - - uses: codecov/codecov-action@54bcd8715eee62d40e33596ef5e8f0f48dbbccab # pin@v3 + - uses: codecov/codecov-action@c16abc29c95fcf9174b58eb7e1abf4c866893bc8 # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' with: name: sentry_isar diff --git a/.github/workflows/logging.yml b/.github/workflows/logging.yml index 1dac410e95..b46dc9ce37 100644 --- a/.github/workflows/logging.yml +++ b/.github/workflows/logging.yml @@ -52,7 +52,7 @@ jobs: dart test -p vm --coverage=coverage --test-randomize-ordering-seed=random --chain-stack-traces dart pub run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.dart_tool/package_config.json --report-on=lib - - uses: codecov/codecov-action@54bcd8715eee62d40e33596ef5e8f0f48dbbccab # pin@v3 + - uses: codecov/codecov-action@c16abc29c95fcf9174b58eb7e1abf4c866893bc8 # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: name: sentry_logging diff --git a/.github/workflows/sqflite.yml b/.github/workflows/sqflite.yml index 39e51d80e4..9aca1fe6fa 100644 --- a/.github/workflows/sqflite.yml +++ b/.github/workflows/sqflite.yml @@ -93,7 +93,7 @@ jobs: cd sqflite flutter test --coverage --test-randomize-ordering-seed=random - - uses: codecov/codecov-action@54bcd8715eee62d40e33596ef5e8f0f48dbbccab # pin@v3 + - uses: codecov/codecov-action@c16abc29c95fcf9174b58eb7e1abf4c866893bc8 # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' with: name: sentry_sqflite From 37410e31a730ab515a093cf61c728b71dfbcbea3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Apr 2024 13:01:13 +0200 Subject: [PATCH 121/237] build(deps): bump natiginfo/action-detekt-all from 1.23.5 to 1.23.6 (#1962) Bumps [natiginfo/action-detekt-all](https://github.com/natiginfo/action-detekt-all) from 1.23.5 to 1.23.6. - [Release notes](https://github.com/natiginfo/action-detekt-all/releases) - [Commits](https://github.com/natiginfo/action-detekt-all/compare/60495f27089d3432d83335c1f14e46ba61de5637...b9daaf58ff7a4885ff92ba612c3ea72bf1abeadb) --- updated-dependencies: - dependency-name: natiginfo/action-detekt-all dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Stefano --- .github/workflows/flutter.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/flutter.yml b/.github/workflows/flutter.yml index 96db102fcc..ab4bd3dd75 100644 --- a/.github/workflows/flutter.yml +++ b/.github/workflows/flutter.yml @@ -207,6 +207,6 @@ jobs: steps: - uses: actions/checkout@v4 # To recreate baseline run: detekt -i flutter/android,flutter/example/android -b flutter/config/detekt-bl.xml -cb - - uses: natiginfo/action-detekt-all@60495f27089d3432d83335c1f14e46ba61de5637 # pin@1.23.5 + - uses: natiginfo/action-detekt-all@b9daaf58ff7a4885ff92ba612c3ea72bf1abeadb # pin@1.23.6 with: args: -i flutter/android,flutter/example/android --baseline flutter/config/detekt-bl.xml --jvm-target 1.8 --build-upon-default-config --all-rules From 38b25e6f63b2950d169f0d8d10b1bdd5e45e94d4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 3 Apr 2024 13:18:13 +0200 Subject: [PATCH 122/237] chore: update metrics/flutter.properties to 3.19.5 (#1959) Co-authored-by: GitHub Co-authored-by: Stefano --- metrics/flutter.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/metrics/flutter.properties b/metrics/flutter.properties index 1aa5448f26..c570b4b0f2 100644 --- a/metrics/flutter.properties +++ b/metrics/flutter.properties @@ -1,2 +1,2 @@ -version = 3.19.3 +version = 3.19.5 repo = https://github.com/flutter/flutter From c687d6477079c3ccd00e9b0bd4e8aa52038f750a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 3 Apr 2024 13:20:10 +0200 Subject: [PATCH 123/237] chore: update scripts/update-symbol-collector.sh to 1.16.0 (#1935) Co-authored-by: GitHub --- .../flutter_symbol_collector/lib/src/symbol_collector_cli.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/flutter_symbol_collector/lib/src/symbol_collector_cli.dart b/scripts/flutter_symbol_collector/lib/src/symbol_collector_cli.dart index c3ab23ee83..e4ab2d8906 100644 --- a/scripts/flutter_symbol_collector/lib/src/symbol_collector_cli.dart +++ b/scripts/flutter_symbol_collector/lib/src/symbol_collector_cli.dart @@ -19,7 +19,7 @@ class SymbolCollectorCli { // https://github.com/getsentry/symbol-collector/releases @internal - static const version = '1.15.0'; + static const version = '1.16.0'; @internal late final String cli; From d445f33dddb759d7d0a43780e9a8984d4c8f9b6d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Apr 2024 10:26:07 +0200 Subject: [PATCH 124/237] build(deps): bump subosito/flutter-action from 2.15.0 to 2.16.0 (#1970) Bumps [subosito/flutter-action](https://github.com/subosito/flutter-action) from 2.15.0 to 2.16.0. - [Release notes](https://github.com/subosito/flutter-action/releases) - [Commits](https://github.com/subosito/flutter-action/compare/3d804929922b667a63a229bc59037807f969e885...44ac965b96f18d999802d4b807e3256d5a3f9fa1) --- updated-dependencies: - dependency-name: subosito/flutter-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/analyze.yml | 2 +- .github/workflows/drift.yml | 2 +- .github/workflows/flutter.yml | 2 +- .github/workflows/flutter_test.yml | 4 ++-- .github/workflows/format-and-fix.yml | 2 +- .github/workflows/isar.yml | 2 +- .github/workflows/metrics.yml | 2 +- .github/workflows/min_version_test.yml | 6 +++--- .github/workflows/sqflite.yml | 2 +- .github/workflows/web-example-ghpages.yml | 2 +- 10 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/analyze.yml b/.github/workflows/analyze.yml index 97e903647f..b9988c0b92 100644 --- a/.github/workflows/analyze.yml +++ b/.github/workflows/analyze.yml @@ -34,7 +34,7 @@ jobs: - uses: actions/checkout@v4 - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 # pin@v1 if: ${{ inputs.sdk == 'dart' }} - - uses: subosito/flutter-action@3d804929922b667a63a229bc59037807f969e885 # pin@v2.15.0 + - uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 # pin@v2.16.0 if: ${{ inputs.sdk == 'flutter' }} - run: ${{ inputs.sdk }} pub get diff --git a/.github/workflows/drift.yml b/.github/workflows/drift.yml index 79f9ee9a5a..918a447d71 100644 --- a/.github/workflows/drift.yml +++ b/.github/workflows/drift.yml @@ -77,7 +77,7 @@ jobs: sudo apt install -y network-manager upower if: matrix.os == 'ubuntu-latest' && matrix.target == 'linux' - - uses: subosito/flutter-action@3d804929922b667a63a229bc59037807f969e885 # pin@v2.15.0 + - uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 # pin@v2.16.0 with: channel: ${{ matrix.sdk }} diff --git a/.github/workflows/flutter.yml b/.github/workflows/flutter.yml index ab4bd3dd75..73f64f363a 100644 --- a/.github/workflows/flutter.yml +++ b/.github/workflows/flutter.yml @@ -82,7 +82,7 @@ jobs: sudo apt install -y network-manager upower if: matrix.os == 'ubuntu-latest' && matrix.target == 'linux' - - uses: subosito/flutter-action@3d804929922b667a63a229bc59037807f969e885 # pin@v2.15.0 + - uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 # pin@v2.16.0 with: channel: ${{ matrix.sdk }} diff --git a/.github/workflows/flutter_test.yml b/.github/workflows/flutter_test.yml index f3bd5dfb8b..d56b64a94a 100644 --- a/.github/workflows/flutter_test.yml +++ b/.github/workflows/flutter_test.yml @@ -43,7 +43,7 @@ jobs: distribution: "adopt" java-version: "11" - - uses: subosito/flutter-action@3d804929922b667a63a229bc59037807f969e885 # pin@v2.15.0 + - uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 # pin@v2.16.0 with: channel: ${{ matrix.sdk }} @@ -126,7 +126,7 @@ jobs: - name: checkout uses: actions/checkout@v4 - - uses: subosito/flutter-action@3d804929922b667a63a229bc59037807f969e885 # pin@v2.15.0 + - uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 # pin@v2.16.0 with: channel: ${{ matrix.sdk }} diff --git a/.github/workflows/format-and-fix.yml b/.github/workflows/format-and-fix.yml index ad9d2fef9b..86711b626f 100644 --- a/.github/workflows/format-and-fix.yml +++ b/.github/workflows/format-and-fix.yml @@ -32,7 +32,7 @@ jobs: - uses: actions/checkout@v4 - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 # pin@v1 if: ${{ matrix.package.sdk == 'dart' }} - - uses: subosito/flutter-action@3d804929922b667a63a229bc59037807f969e885 # pin@v2.15.0 + - uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 # pin@v2.16.0 if: ${{ matrix.package.sdk == 'flutter' }} - run: ${{ matrix.package.sdk }} pub get diff --git a/.github/workflows/isar.yml b/.github/workflows/isar.yml index 4687defc4d..87a4513825 100644 --- a/.github/workflows/isar.yml +++ b/.github/workflows/isar.yml @@ -77,7 +77,7 @@ jobs: sudo apt install -y network-manager upower if: matrix.os == 'ubuntu-latest' && matrix.target == 'linux' - - uses: subosito/flutter-action@3d804929922b667a63a229bc59037807f969e885 # pin@v2.15.0 + - uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 # pin@v2.16.0 with: channel: ${{ matrix.sdk }} diff --git a/.github/workflows/metrics.yml b/.github/workflows/metrics.yml index 2af1f3989a..201d0a64ea 100644 --- a/.github/workflows/metrics.yml +++ b/.github/workflows/metrics.yml @@ -53,7 +53,7 @@ jobs: echo "flutter=$version" >> "$GITHUB_OUTPUT" - name: Install Flutter v${{ steps.conf.outputs.flutter }} - uses: subosito/flutter-action@3d804929922b667a63a229bc59037807f969e885 # pin@v2.15.0 + uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 # pin@v2.16.0 with: flutter-version: ${{ steps.conf.outputs.flutter }} diff --git a/.github/workflows/min_version_test.yml b/.github/workflows/min_version_test.yml index b2f6376d90..10d5e73bf5 100644 --- a/.github/workflows/min_version_test.yml +++ b/.github/workflows/min_version_test.yml @@ -34,7 +34,7 @@ jobs: distribution: "adopt" java-version: "11" - - uses: subosito/flutter-action@3d804929922b667a63a229bc59037807f969e885 # pin@v2.15.0 + - uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 # pin@v2.16.0 with: flutter-version: "3.0.0" @@ -51,7 +51,7 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: subosito/flutter-action@3d804929922b667a63a229bc59037807f969e885 # pin@v2.15.0 + - uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 # pin@v2.16.0 with: flutter-version: "3.0.0" @@ -68,7 +68,7 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: subosito/flutter-action@3d804929922b667a63a229bc59037807f969e885 # pin@v2.15.0 + - uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 # pin@v2.16.0 with: flutter-version: "3.0.0" diff --git a/.github/workflows/sqflite.yml b/.github/workflows/sqflite.yml index 9aca1fe6fa..c635f750e2 100644 --- a/.github/workflows/sqflite.yml +++ b/.github/workflows/sqflite.yml @@ -77,7 +77,7 @@ jobs: sudo apt install -y network-manager upower if: matrix.os == 'ubuntu-latest' && matrix.target == 'linux' - - uses: subosito/flutter-action@3d804929922b667a63a229bc59037807f969e885 # pin@v2.15.0 + - uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 # pin@v2.16.0 with: channel: ${{ matrix.sdk }} diff --git a/.github/workflows/web-example-ghpages.yml b/.github/workflows/web-example-ghpages.yml index ce18da720e..afdcb154c6 100644 --- a/.github/workflows/web-example-ghpages.yml +++ b/.github/workflows/web-example-ghpages.yml @@ -14,7 +14,7 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: subosito/flutter-action@3d804929922b667a63a229bc59037807f969e885 # pin@v2.15.0 + - uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 # pin@v2.16.0 - uses: bluefireteam/flutter-gh-pages@57815b17b371455ec1a98f075b71b4c6ba0a938c # pin@v8 with: workingDir: flutter/example From 3f17dac65a712d3144d7fb3e8ae0ec43387fd1e8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Apr 2024 12:07:25 +0200 Subject: [PATCH 125/237] build(deps): bump codecov/codecov-action from 4.1.1 to 4.2.0 (#1971) Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 4.1.1 to 4.2.0. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/c16abc29c95fcf9174b58eb7e1abf4c866893bc8...7afa10ed9b269c561c2336fd862446844e0cbf71) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/dart.yml | 2 +- .github/workflows/dio.yml | 2 +- .github/workflows/drift.yml | 2 +- .github/workflows/file.yml | 2 +- .github/workflows/flutter.yml | 2 +- .github/workflows/hive.yml | 2 +- .github/workflows/isar.yml | 2 +- .github/workflows/logging.yml | 2 +- .github/workflows/sqflite.yml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml index 28a4ecb093..46a82a54af 100644 --- a/.github/workflows/dart.yml +++ b/.github/workflows/dart.yml @@ -68,7 +68,7 @@ jobs: dart pub get webdev build - - uses: codecov/codecov-action@c16abc29c95fcf9174b58eb7e1abf4c866893bc8 # pin@v3 + - uses: codecov/codecov-action@7afa10ed9b269c561c2336fd862446844e0cbf71 # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: name: sentry diff --git a/.github/workflows/dio.yml b/.github/workflows/dio.yml index e2dfaa8a67..7da74c1017 100644 --- a/.github/workflows/dio.yml +++ b/.github/workflows/dio.yml @@ -52,7 +52,7 @@ jobs: dart test -p vm --coverage=coverage --test-randomize-ordering-seed=random --chain-stack-traces dart pub run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.dart_tool/package_config.json --report-on=lib - - uses: codecov/codecov-action@c16abc29c95fcf9174b58eb7e1abf4c866893bc8 # pin@v3 + - uses: codecov/codecov-action@7afa10ed9b269c561c2336fd862446844e0cbf71 # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: name: sentry_dio diff --git a/.github/workflows/drift.yml b/.github/workflows/drift.yml index 918a447d71..f45a7df266 100644 --- a/.github/workflows/drift.yml +++ b/.github/workflows/drift.yml @@ -93,7 +93,7 @@ jobs: cd drift flutter test --coverage --test-randomize-ordering-seed=random - - uses: codecov/codecov-action@c16abc29c95fcf9174b58eb7e1abf4c866893bc8 # pin@v3 + - uses: codecov/codecov-action@7afa10ed9b269c561c2336fd862446844e0cbf71 # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' with: name: sentry_drift diff --git a/.github/workflows/file.yml b/.github/workflows/file.yml index 7caf2b2f78..6e677f59bb 100644 --- a/.github/workflows/file.yml +++ b/.github/workflows/file.yml @@ -52,7 +52,7 @@ jobs: dart test -p vm --coverage=coverage --test-randomize-ordering-seed=random --chain-stack-traces dart pub run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.dart_tool/package_config.json --report-on=lib - - uses: codecov/codecov-action@c16abc29c95fcf9174b58eb7e1abf4c866893bc8 # pin@v3 + - uses: codecov/codecov-action@7afa10ed9b269c561c2336fd862446844e0cbf71 # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: name: sentry_file diff --git a/.github/workflows/flutter.yml b/.github/workflows/flutter.yml index 73f64f363a..8572cd1394 100644 --- a/.github/workflows/flutter.yml +++ b/.github/workflows/flutter.yml @@ -112,7 +112,7 @@ jobs: flutter test --coverage --test-randomize-ordering-seed=random dart run remove_from_coverage -f coverage/lcov.info -r 'binding.dart' - - uses: codecov/codecov-action@c16abc29c95fcf9174b58eb7e1abf4c866893bc8 # pin@v3 + - uses: codecov/codecov-action@7afa10ed9b269c561c2336fd862446844e0cbf71 # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' with: name: sentry_flutter diff --git a/.github/workflows/hive.yml b/.github/workflows/hive.yml index da903ef0c8..be2fc02951 100644 --- a/.github/workflows/hive.yml +++ b/.github/workflows/hive.yml @@ -51,7 +51,7 @@ jobs: dart test -p vm --coverage=coverage --test-randomize-ordering-seed=random --chain-stack-traces dart pub run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.dart_tool/package_config.json --report-on=lib - - uses: codecov/codecov-action@c16abc29c95fcf9174b58eb7e1abf4c866893bc8 # pin@v3 + - uses: codecov/codecov-action@7afa10ed9b269c561c2336fd862446844e0cbf71 # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: name: sentry_hive diff --git a/.github/workflows/isar.yml b/.github/workflows/isar.yml index 87a4513825..6b037c1c5a 100644 --- a/.github/workflows/isar.yml +++ b/.github/workflows/isar.yml @@ -93,7 +93,7 @@ jobs: cd isar flutter test -j 1 --coverage --test-randomize-ordering-seed=random - - uses: codecov/codecov-action@c16abc29c95fcf9174b58eb7e1abf4c866893bc8 # pin@v3 + - uses: codecov/codecov-action@7afa10ed9b269c561c2336fd862446844e0cbf71 # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' with: name: sentry_isar diff --git a/.github/workflows/logging.yml b/.github/workflows/logging.yml index b46dc9ce37..b1a692e044 100644 --- a/.github/workflows/logging.yml +++ b/.github/workflows/logging.yml @@ -52,7 +52,7 @@ jobs: dart test -p vm --coverage=coverage --test-randomize-ordering-seed=random --chain-stack-traces dart pub run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.dart_tool/package_config.json --report-on=lib - - uses: codecov/codecov-action@c16abc29c95fcf9174b58eb7e1abf4c866893bc8 # pin@v3 + - uses: codecov/codecov-action@7afa10ed9b269c561c2336fd862446844e0cbf71 # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: name: sentry_logging diff --git a/.github/workflows/sqflite.yml b/.github/workflows/sqflite.yml index c635f750e2..b4b8c682a8 100644 --- a/.github/workflows/sqflite.yml +++ b/.github/workflows/sqflite.yml @@ -93,7 +93,7 @@ jobs: cd sqflite flutter test --coverage --test-randomize-ordering-seed=random - - uses: codecov/codecov-action@c16abc29c95fcf9174b58eb7e1abf4c866893bc8 # pin@v3 + - uses: codecov/codecov-action@7afa10ed9b269c561c2336fd862446844e0cbf71 # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' with: name: sentry_sqflite From 2bcc96c6f1ca68839642ffed450a7b96598cd394 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Apr 2024 12:08:43 +0200 Subject: [PATCH 126/237] build(deps): bump gradle/gradle-build-action from 3.1.0 to 3.2.0 (#1972) Bumps [gradle/gradle-build-action](https://github.com/gradle/gradle-build-action) from 3.1.0 to 3.2.0. - [Release notes](https://github.com/gradle/gradle-build-action/releases) - [Commits](https://github.com/gradle/gradle-build-action/compare/29c0906b64b8fc82467890bfb7a0a7ef34bda89e...fe59895742b4f984530980e4f693943577526b61) --- updated-dependencies: - dependency-name: gradle/gradle-build-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/flutter_test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/flutter_test.yml b/.github/workflows/flutter_test.yml index d56b64a94a..c2423ce3db 100644 --- a/.github/workflows/flutter_test.yml +++ b/.github/workflows/flutter_test.yml @@ -54,7 +54,7 @@ jobs: run: flutter pub get - name: Gradle cache - uses: gradle/gradle-build-action@29c0906b64b8fc82467890bfb7a0a7ef34bda89e + uses: gradle/gradle-build-action@fe59895742b4f984530980e4f693943577526b61 - name: AVD cache uses: actions/cache@v4 From fda497fffd70d0c9de75c07f56c3668a2f1f4814 Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Tue, 9 Apr 2024 15:47:08 +0200 Subject: [PATCH 127/237] Update CHANGELOG.md (#1976) --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7dd320dab5..1930e71df6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Dependencies + +- Expand `package_info_plus` version range to `6.0.0` ([#1948](https://github.com/getsentry/sentry-dart/pull/1948)) + ### Improvements - Set `sentry_flutter.podspec` version from `pubspec.yaml` ([#1941](https://github.com/getsentry/sentry-dart/pull/1941)) From 61e71ec84d02fc022b00615b4d0bae341a641502 Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Tue, 9 Apr 2024 16:47:59 +0200 Subject: [PATCH 128/237] ci: fix metrics workflow for android (#1978) * Update metrics ci --- .github/workflows/metrics.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/metrics.yml b/.github/workflows/metrics.yml index 201d0a64ea..c4249f186e 100644 --- a/.github/workflows/metrics.yml +++ b/.github/workflows/metrics.yml @@ -60,7 +60,7 @@ jobs: - uses: actions/setup-java@v4 if: ${{ matrix.platform == 'android' }} with: - java-version: "11" + java-version: "17" distribution: "adopt" - run: ./metrics/prepare.sh From 84bc635491698e6b3f3cfe8b60c67ca9b489b6b6 Mon Sep 17 00:00:00 2001 From: Stefano Date: Tue, 9 Apr 2024 17:12:01 +0200 Subject: [PATCH 129/237] Metrics Part 1 - Add Counter Metric API (#1940) Add Counter Metric API (part 1) (#1940) * added Counter Metric API * added Metric Aggregation, with hub/client integration and close * added metric tag normalization * added send of statsd envelope type Add other metric types and weight (part 2) (#1949) * added crc32_utils.dart, taken from archive library * added Gauge, Distribution and Set metrics * added weight to Metrics and auto flush when weight is too much Add timing metric and beforeMetric callback (part 3) (#1954) * added SentryOptions.beforeMetricCallback * added beforeMetricCallback logic in metrics_aggregator.dart * added timing metric api with span auto start * timing api uses span duration as value for the emitted metric if possible Add metrics span summary (part 4) (#1958) * added local_metrics_aggregator.dart to spans * metrics_aggregator.dart now adds to current span's localMetricsAggregator * added metric_summary.dart * added metricSummary to spans and transaction JSONs Add rate limit (part 5) (#1973) * added metric_bucket data category for rate limits * updated metric normalization rules * added rate limit for metrics --- CHANGELOG.md | 15 + dart/lib/src/hub.dart | 48 ++ dart/lib/src/hub_adapter.dart | 15 + .../src/metrics/local_metrics_aggregator.dart | 37 ++ dart/lib/src/metrics/metric.dart | 291 +++++++++++ dart/lib/src/metrics/metrics_aggregator.dart | 205 ++++++++ dart/lib/src/metrics/metrics_api.dart | 180 +++++++ dart/lib/src/noop_hub.dart | 23 +- dart/lib/src/noop_sentry_client.dart | 14 + dart/lib/src/noop_sentry_span.dart | 4 + dart/lib/src/protocol.dart | 1 + dart/lib/src/protocol/metric_summary.dart | 43 ++ dart/lib/src/protocol/sentry_span.dart | 20 + dart/lib/src/protocol/sentry_transaction.dart | 18 + dart/lib/src/sentry.dart | 4 + dart/lib/src/sentry_client.dart | 29 +- dart/lib/src/sentry_envelope.dart | 21 +- dart/lib/src/sentry_envelope_item.dart | 42 +- dart/lib/src/sentry_item_type.dart | 1 + dart/lib/src/sentry_options.dart | 53 ++ dart/lib/src/sentry_span_interface.dart | 4 + dart/lib/src/sentry_tracer.dart | 5 + dart/lib/src/transport/data_category.dart | 5 + dart/lib/src/transport/rate_limit.dart | 4 +- dart/lib/src/transport/rate_limit_parser.dart | 13 +- dart/lib/src/transport/rate_limiter.dart | 9 + dart/lib/src/utils/crc32_utils.dart | 313 +++++++++++ dart/test/hub_test.dart | 80 ++- .../local_metrics_aggregator_test.dart | 40 ++ dart/test/metrics/metric_test.dart | 315 +++++++++++ .../test/metrics/metrics_aggregator_test.dart | 493 ++++++++++++++++++ dart/test/metrics/metrics_api_test.dart | 150 ++++++ dart/test/mocks.dart | 32 ++ dart/test/mocks/mock_hub.dart | 16 + dart/test/mocks/mock_sentry_client.dart | 14 + dart/test/mocks/mock_transport.dart | 15 +- .../test/protocol/rate_limit_parser_test.dart | 39 ++ dart/test/protocol/rate_limiter_test.dart | 112 ++++ dart/test/sentry_client_test.dart | 64 ++- dart/test/sentry_envelope_item_test.dart | 46 ++ dart/test/sentry_envelope_test.dart | 57 ++ dart/test/sentry_options_test.dart | 51 ++ dart/test/sentry_span_test.dart | 39 ++ dart/test/sentry_test.dart | 28 +- dart/test/sentry_tracer_test.dart | 15 + dart/test/sentry_transaction_test.dart | 46 +- flutter/example/lib/main.dart | 31 ++ flutter/test/mocks.mocks.dart | 2 + 48 files changed, 3021 insertions(+), 81 deletions(-) create mode 100644 dart/lib/src/metrics/local_metrics_aggregator.dart create mode 100644 dart/lib/src/metrics/metric.dart create mode 100644 dart/lib/src/metrics/metrics_aggregator.dart create mode 100644 dart/lib/src/metrics/metrics_api.dart create mode 100644 dart/lib/src/protocol/metric_summary.dart create mode 100644 dart/lib/src/utils/crc32_utils.dart create mode 100644 dart/test/metrics/local_metrics_aggregator_test.dart create mode 100644 dart/test/metrics/metric_test.dart create mode 100644 dart/test/metrics/metrics_aggregator_test.dart create mode 100644 dart/test/metrics/metrics_api_test.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index 1930e71df6..57c0ba848b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,21 @@ ## Unreleased +### Features + +- Experimental: Add support for Sentry Developer Metrics ([#1940](https://github.com/getsentry/sentry-dart/pull/1940), [#1949](https://github.com/getsentry/sentry-dart/pull/1949), [#1954](https://github.com/getsentry/sentry-dart/pull/1954), [#1958](https://github.com/getsentry/sentry-dart/pull/1958)) + Use the Metrics API to track processing time, download sizes, user signups, and conversion rates and correlate them back to tracing data in order to get deeper insights and solve issues faster. Our API supports counters, distributions, sets, gauges and timers, and it's easy to get started: + ```dart + Sentry.metrics() + .increment( + 'button_login_click', // key + value: 1.0, + unit: null, + tags: {"provider": "e-mail"} + ); + ``` + To learn more about Sentry Developer Metrics, head over to our [Dart](https://docs.sentry.io/platforms/dart/metrics/) and [Flutter](https://docs.sentry.io/platforms/flutter/metrics/) docs page. + ### Dependencies - Expand `package_info_plus` version range to `6.0.0` ([#1948](https://github.com/getsentry/sentry-dart/pull/1948)) diff --git a/dart/lib/src/hub.dart b/dart/lib/src/hub.dart index 42291d1c87..a8e06e28ed 100644 --- a/dart/lib/src/hub.dart +++ b/dart/lib/src/hub.dart @@ -2,6 +2,9 @@ import 'dart:async'; import 'dart:collection'; import 'package:meta/meta.dart'; +import 'metrics/metric.dart'; +import 'metrics/metrics_aggregator.dart'; +import 'metrics/metrics_api.dart'; import 'profiling.dart'; import 'propagation_context.dart'; import 'transport/data_category.dart'; @@ -38,6 +41,14 @@ class Hub { late final _WeakMap _throwableToSpan; + late final MetricsApi _metricsApi; + + @internal + MetricsApi get metricsApi => _metricsApi; + + @internal + MetricsAggregator? get metricsAggregator => _peek().client.metricsAggregator; + factory Hub(SentryOptions options) { _validateOptions(options); @@ -49,6 +60,7 @@ class Hub { _stack.add(_StackItem(_getClient(_options), Scope(_options))); _isEnabled = true; _throwableToSpan = _WeakMap(_options); + _metricsApi = MetricsApi(hub: this); } static void _validateOptions(SentryOptions options) { @@ -554,6 +566,42 @@ class Hub { return sentryId; } + @internal + Future captureMetrics( + Map> metricsBuckets) async { + var sentryId = SentryId.empty(); + + if (!_isEnabled) { + _options.logger( + SentryLevel.warning, + "Instance is disabled and this 'captureMetrics' call is a no-op.", + ); + } else if (!_options.enableMetrics) { + _options.logger( + SentryLevel.info, + "Metrics are disabled and this 'captureMetrics' call is a no-op.", + ); + } else if (metricsBuckets.isEmpty) { + _options.logger( + SentryLevel.info, + "Metrics are empty and this 'captureMetrics' call is a no-op.", + ); + } else { + final item = _peek(); + try { + sentryId = await item.client.captureMetrics(metricsBuckets); + } catch (exception, stackTrace) { + _options.logger( + SentryLevel.error, + 'Error while capturing metrics.', + exception: exception, + stackTrace: stackTrace, + ); + } + } + return sentryId; + } + @internal void setSpanContext( dynamic throwable, diff --git a/dart/lib/src/hub_adapter.dart b/dart/lib/src/hub_adapter.dart index 8a9107ae54..6b2ece3c53 100644 --- a/dart/lib/src/hub_adapter.dart +++ b/dart/lib/src/hub_adapter.dart @@ -4,6 +4,9 @@ import 'package:meta/meta.dart'; import 'hint.dart'; import 'hub.dart'; +import 'metrics/metric.dart'; +import 'metrics/metrics_aggregator.dart'; +import 'metrics/metrics_api.dart'; import 'profiling.dart'; import 'protocol.dart'; import 'scope.dart'; @@ -23,6 +26,10 @@ class HubAdapter implements Hub { @internal SentryOptions get options => Sentry.currentHub.options; + @override + @internal + MetricsApi get metricsApi => Sentry.currentHub.metricsApi; + factory HubAdapter() { return _instance; } @@ -181,4 +188,12 @@ class HubAdapter implements Hub { @override Scope get scope => Sentry.currentHub.scope; + + @override + Future captureMetrics(Map> metricsBuckets) => + Sentry.currentHub.captureMetrics(metricsBuckets); + + @override + MetricsAggregator? get metricsAggregator => + Sentry.currentHub.metricsAggregator; } diff --git a/dart/lib/src/metrics/local_metrics_aggregator.dart b/dart/lib/src/metrics/local_metrics_aggregator.dart new file mode 100644 index 0000000000..92076ef807 --- /dev/null +++ b/dart/lib/src/metrics/local_metrics_aggregator.dart @@ -0,0 +1,37 @@ +import 'dart:core'; +import 'package:meta/meta.dart'; +import '../protocol/metric_summary.dart'; +import 'metric.dart'; + +@internal +class LocalMetricsAggregator { + // format: > + final Map> _buckets = {}; + + void add(final Metric metric, final num value) { + final bucket = + _buckets.putIfAbsent(metric.getSpanAggregationKey(), () => {}); + + bucket.update(metric.getCompositeKey(), (m) => m..add(value), + ifAbsent: () => Metric.fromType( + type: MetricType.gauge, + key: metric.key, + value: value, + unit: metric.unit, + tags: metric.tags) as GaugeMetric); + } + + Map> getSummaries() { + final Map> summaries = {}; + for (final entry in _buckets.entries) { + final String exportKey = entry.key; + + final metricSummaries = entry.value.values + .map((gauge) => MetricSummary.fromGauge(gauge)) + .toList(); + + summaries[exportKey] = metricSummaries; + } + return summaries; + } +} diff --git a/dart/lib/src/metrics/metric.dart b/dart/lib/src/metrics/metric.dart new file mode 100644 index 0000000000..fdea81cbf4 --- /dev/null +++ b/dart/lib/src/metrics/metric.dart @@ -0,0 +1,291 @@ +import 'dart:math'; + +import 'package:meta/meta.dart'; + +import '../../sentry.dart'; + +final RegExp unitRegex = RegExp('[^\\w]+'); +final RegExp nameRegex = RegExp('[^\\w-.]+'); +final RegExp tagKeyRegex = RegExp('[^\\w-./]+'); + +/// Base class for metrics. +/// Each metric is identified by a [key]. Its [type] describes its behaviour. +/// A [unit] (defaults to [SentryMeasurementUnit.none]) describes the values +/// being tracked. Optional [tags] can be added. The [timestamp] is the time +/// when the metric was emitted. +@internal +abstract class Metric { + final MetricType type; + final String key; + final SentryMeasurementUnit unit; + final Map tags; + + Metric({ + required this.type, + required this.key, + required this.unit, + required this.tags, + }); + + factory Metric.fromType({ + required final MetricType type, + required final String key, + required final num value, + required final SentryMeasurementUnit unit, + required final Map tags, + }) { + switch (type) { + case MetricType.counter: + return CounterMetric._(value: value, key: key, unit: unit, tags: tags); + case MetricType.gauge: + return GaugeMetric._(value: value, key: key, unit: unit, tags: tags); + case MetricType.set: + return SetMetric._(value: value, key: key, unit: unit, tags: tags); + case MetricType.distribution: + return DistributionMetric._( + value: value, key: key, unit: unit, tags: tags); + } + } + + /// Add a value to the metric. + add(num value); + + /// Return the weight of the current metric. + int getWeight(); + + /// Serialize the value into a list of Objects to be converted into a String. + Iterable _serializeValue(); + + /// Encodes the metric in the statsd format + /// See github.com/statsd/statsd#usage and + /// getsentry.github.io/relay/relay_metrics/index.html + /// for more details about the format. + /// + /// Example format: key@none:1|c|#myTag:myValue|T1710844170 + /// key@unit:value1:value2|type|#tagKey1:tagValue1,tagKey2:tagValue2,|TbucketKey + /// + /// [bucketKey] is the key of the metric bucket that will be sent to Sentry, + /// and it's appended at the end of the encoded metric. + String encodeToStatsd(int bucketKey) { + final buffer = StringBuffer(); + buffer.write(_sanitizeName(key)); + buffer.write("@"); + + final sanitizeUnitName = _sanitizeUnit(unit.name); + buffer.write(sanitizeUnitName); + + for (final value in _serializeValue()) { + buffer.write(":"); + buffer.write(value.toString()); + } + + buffer.write("|"); + buffer.write(type.statsdType); + + if (tags.isNotEmpty) { + buffer.write("|#"); + final serializedTags = tags.entries + .map((tag) => + '${_sanitizeTagKey(tag.key)}:${_sanitizeTagValue(tag.value)}') + .join(','); + buffer.write(serializedTags); + } + + buffer.write("|T"); + buffer.write(bucketKey); + + return buffer.toString(); + } + + /// Return a key created by [key], [type], [unit] and [tags]. + /// This key should be used to retrieve the metric to update in aggregation. + String getCompositeKey() { + final String serializedTags = tags.entries.map((e) { + // We escape the ',' from the key and the value, as we will join the tags + // with a ',' to create the composite key. + String escapedKey = e.key.replaceAll(',', '\\,'); + String escapedValue = e.value.replaceAll(',', '\\,'); + return '$escapedKey=$escapedValue'; + }).join(','); + + return ('${type.statsdType}_${key}_${unit.name}_$serializedTags'); + } + + /// Return a key created by [key], [type] and [unit]. + /// This key should be used to aggregate the metric locally in a span. + String getSpanAggregationKey() => '${type.statsdType}:$key@${unit.name}'; + + /// Remove forbidden characters from the metric key and tag key. + String _sanitizeName(String input) => input.replaceAll(nameRegex, '_'); + + /// Remove forbidden characters from the tag value. + String _sanitizeTagKey(String input) => input.replaceAll(tagKeyRegex, ''); + + /// Remove forbidden characters from the metric unit. + String _sanitizeUnit(String input) => input.replaceAll(unitRegex, ''); + + String _sanitizeTagValue(String input) { + // see https://develop.sentry.dev/sdk/metrics/#tag-values-replacement-map + // Line feed -> \n + // Carriage return -> \r + // Tab -> \t + // Backslash -> \\ + // Pipe -> \\u{7c} + // Comma -> \\u{2c} + final buffer = StringBuffer(); + for (int i = 0; i < input.length; i++) { + final ch = input[i]; + if (ch == '\n') { + buffer.write("\\n"); + } else if (ch == '\r') { + buffer.write("\\r"); + } else if (ch == '\t') { + buffer.write("\\t"); + } else if (ch == '\\') { + buffer.write("\\\\"); + } else if (ch == '|') { + buffer.write("\\u{7c}"); + } else if (ch == ',') { + buffer.write("\\u{2c}"); + } else { + buffer.write(ch); + } + } + return buffer.toString(); + } +} + +/// Metric [MetricType.counter] that tracks a value that can only be incremented. +@internal +class CounterMetric extends Metric { + num value; + + CounterMetric._({ + required this.value, + required super.key, + required super.unit, + required super.tags, + }) : super(type: MetricType.counter); + + @override + add(num value) => this.value += value; + + @override + Iterable _serializeValue() => [value]; + + @override + int getWeight() => 1; +} + +/// Metric [MetricType.gauge] that tracks a value that can go up and down. +@internal +class GaugeMetric extends Metric { + num _last; + num _minimum; + num _maximum; + num _sum; + int _count; + + GaugeMetric._({ + required num value, + required super.key, + required super.unit, + required super.tags, + }) : _last = value, + _minimum = value, + _maximum = value, + _sum = value, + _count = 1, + super(type: MetricType.gauge); + + @override + add(num value) { + _last = value; + _minimum = min(_minimum, value); + _maximum = max(_maximum, value); + _sum += value; + _count++; + } + + @override + Iterable _serializeValue() => + [_last, _minimum, _maximum, _sum, _count]; + + @override + int getWeight() => 5; + + @visibleForTesting + num get last => _last; + num get minimum => _minimum; + num get maximum => _maximum; + num get sum => _sum; + int get count => _count; +} + +/// Metric [MetricType.set] that tracks a set of values on which you can perform +/// aggregations such as count_unique. +@internal +class SetMetric extends Metric { + final Set _values = {}; + + SetMetric._( + {required num value, + required super.key, + required super.unit, + required super.tags}) + : super(type: MetricType.set) { + add(value); + } + + @override + add(num value) => _values.add(value.toInt()); + + @override + Iterable _serializeValue() => _values; + + @override + int getWeight() => _values.length; + + @visibleForTesting + Set get values => _values; +} + +/// Metric [MetricType.distribution] that tracks a list of values. +@internal +class DistributionMetric extends Metric { + final List _values = []; + + DistributionMetric._( + {required num value, + required super.key, + required super.unit, + required super.tags}) + : super(type: MetricType.distribution) { + add(value); + } + + @override + add(num value) => _values.add(value); + + @override + Iterable _serializeValue() => _values; + + @override + int getWeight() => _values.length; + + @visibleForTesting + List get values => _values; +} + +/// The metric type and its associated statsd encoded value. +@internal +enum MetricType { + counter('c'), + gauge('g'), + distribution('d'), + set('s'); + + final String statsdType; + + const MetricType(this.statsdType); +} diff --git a/dart/lib/src/metrics/metrics_aggregator.dart b/dart/lib/src/metrics/metrics_aggregator.dart new file mode 100644 index 0000000000..2dd9cb2c91 --- /dev/null +++ b/dart/lib/src/metrics/metrics_aggregator.dart @@ -0,0 +1,205 @@ +import 'dart:async'; +import 'dart:collection'; +import 'dart:math'; + +import 'package:meta/meta.dart'; + +import '../../sentry.dart'; +import 'metric.dart'; + +/// Class that aggregates all metrics into time buckets and sends them. +@internal +class MetricsAggregator { + static final _defaultFlushShiftMs = + (Random().nextDouble() * (_rollupInSeconds * 1000)).toInt(); + static const _defaultFlushInterval = Duration(seconds: 5); + static const _defaultMaxWeight = 100000; + static const int _rollupInSeconds = 10; + + final Duration _flushInterval; + final int _flushShiftMs; + final SentryOptions _options; + final Hub _hub; + final int _maxWeight; + int _totalWeight = 0; + bool _isClosed = false; + Completer? _flushCompleter; + Timer? _flushTimer; + + /// The key for this map is the timestamp of the bucket, rounded down to the + /// nearest RollupInSeconds. So it aggregates all the metrics over a certain + /// time period. The Value is a map of the metrics, each of which has a key + /// that uniquely identifies it within the time period. + /// The [SplayTreeMap] is used so that bucket keys are ordered. + final SplayTreeMap> _buckets = SplayTreeMap(); + + MetricsAggregator({ + required SentryOptions options, + Hub? hub, + @visibleForTesting Duration? flushInterval, + @visibleForTesting int? flushShiftMs, + @visibleForTesting int? maxWeight, + }) : _options = options, + _hub = hub ?? HubAdapter(), + _flushInterval = flushInterval ?? _defaultFlushInterval, + _flushShiftMs = flushShiftMs ?? _defaultFlushShiftMs, + _maxWeight = maxWeight ?? _defaultMaxWeight; + + /// Creates or update an existing Counter metric with [value]. + /// The metric to update is identified using [key], [unit] and [tags]. + /// The [timestamp] represents when the metric was emitted. + void emit( + MetricType metricType, + String key, + num value, + SentryMeasurementUnit unit, + Map tags, + ) { + if (_isClosed) { + return; + } + + // run before metric callback if set + if (_options.beforeMetricCallback != null) { + try { + final shouldEmit = _options.beforeMetricCallback!(key, tags: tags); + if (!shouldEmit) { + _options.logger( + SentryLevel.info, + 'Metric was dropped by beforeMetric', + ); + return; + } + } catch (exception, stackTrace) { + _options.logger( + SentryLevel.error, + 'The BeforeMetric callback threw an exception', + exception: exception, + stackTrace: stackTrace, + ); + if (_options.automatedTestMode) { + rethrow; + } + } + } + + final bucketKey = _getBucketKey(_options.clock()); + final bucket = _buckets.putIfAbsent(bucketKey, () => {}); + final metric = Metric.fromType( + type: metricType, key: key, value: value, unit: unit, tags: tags); + + final oldWeight = bucket[metric.getCompositeKey()]?.getWeight() ?? 0; + final addedWeight = metric.getWeight(); + _totalWeight += addedWeight - oldWeight; + + // Update the existing metric in the bucket. + // If absent, add the newly created metric to the bucket. + bucket.update( + metric.getCompositeKey(), + (m) => m..add(value), + ifAbsent: () => metric, + ); + + // For sets, we only record that a value has been added to the set but not which one. + // See develop docs: https://develop.sentry.dev/sdk/metrics/#sets + _hub + .getSpan() + ?.localMetricsAggregator + ?.add(metric, metricType == MetricType.set ? addedWeight : value); + + // Schedule the metrics flushing. + _scheduleFlush(); + } + + void _scheduleFlush() { + if (!_isClosed && _buckets.isNotEmpty) { + if (_isOverWeight()) { + _flushTimer?.cancel(); + _flush(false); + return; + } + if (_flushTimer?.isActive != true) { + _flushCompleter = Completer(); + _flushTimer = Timer(_flushInterval, () => _flush(false)); + } + } + } + + bool _isOverWeight() => _totalWeight >= _maxWeight; + + int getBucketWeight(final Map bucket) { + int weight = 0; + for (final metric in bucket.values) { + weight += metric.getWeight(); + } + return weight; + } + + /// Flush the metrics, then schedule next flush again. + void _flush(bool force) async { + if (!force && _isOverWeight()) { + _options.logger(SentryLevel.info, + "Metrics: total weight exceeded, flushing all buckets"); + force = true; + } + + final flushableBucketKeys = _getFlushableBucketKeys(force); + if (flushableBucketKeys.isEmpty) { + _options.logger(SentryLevel.debug, 'Metrics: nothing to flush'); + } else { + final Map> bucketsToFlush = {}; + + for (final flushableBucketKey in flushableBucketKeys) { + final bucket = _buckets.remove(flushableBucketKey); + if (bucket != null && bucket.isNotEmpty) { + _totalWeight -= getBucketWeight(bucket); + bucketsToFlush[flushableBucketKey] = bucket.values; + } + } + await _hub.captureMetrics(bucketsToFlush); + } + + // Notify flush completed and reschedule flushing + _flushTimer?.cancel(); + _flushTimer = null; + flushCompleter?.complete(null); + _flushCompleter = null; + _scheduleFlush(); + } + + /// Return a list of bucket keys to flush. + List _getFlushableBucketKeys(bool force) { + if (force) { + return buckets.keys.toList(); + } + // Flushable buckets are all buckets with timestamp lower than the current + // one (so now - rollupInSeconds), minus a random duration (flushShiftMs). + final maxTimestampToFlush = _options.clock().subtract(Duration( + seconds: _rollupInSeconds, + milliseconds: _flushShiftMs, + )); + final maxKeyToFlush = _getBucketKey(maxTimestampToFlush); + + // takeWhile works because we use a SplayTreeMap and keys are ordered. + // toList() is needed because takeWhile is lazy and we want to remove items + // from the buckets with these keys. + return _buckets.keys.takeWhile((value) => value <= maxKeyToFlush).toList(); + } + + /// The timestamp of the bucket, rounded down to the nearest RollupInSeconds. + int _getBucketKey(DateTime timestamp) { + final seconds = timestamp.millisecondsSinceEpoch ~/ 1000; + return (seconds ~/ _rollupInSeconds) * _rollupInSeconds; + } + + @visibleForTesting + SplayTreeMap> get buckets => _buckets; + + @visibleForTesting + Completer? get flushCompleter => _flushCompleter; + + void close() { + _flush(true); + _isClosed = true; + } +} diff --git a/dart/lib/src/metrics/metrics_api.dart b/dart/lib/src/metrics/metrics_api.dart new file mode 100644 index 0000000000..1ef8df77c3 --- /dev/null +++ b/dart/lib/src/metrics/metrics_api.dart @@ -0,0 +1,180 @@ +import 'dart:async'; +import 'dart:convert'; +import '../../sentry.dart'; +import '../utils/crc32_utils.dart'; +import 'metric.dart'; + +/// Public APIs to emit Sentry metrics. +class MetricsApi { + MetricsApi({Hub? hub}) : _hub = hub ?? HubAdapter(); + + final Hub _hub; + + /// Emits a Counter metric, identified by [key], increasing it by [value]. + /// Counters track a value that can only be incremented. + /// You can set the [unit] and the optional [tags] to associate to the metric. + void increment(final String key, + {final double value = 1.0, + final SentryMeasurementUnit? unit, + final Map? tags}) { + _hub.metricsAggregator?.emit( + MetricType.counter, + key, + value, + unit ?? SentryMeasurementUnit.none, + _enrichWithDefaultTags(tags), + ); + } + + /// Emits a Gauge metric, identified by [key], adding [value] to it. + /// Gauges track a value that can go up and down. + /// You can set the [unit] and the optional [tags] to associate to the metric. + void gauge(final String key, + {required final double value, + final SentryMeasurementUnit? unit, + final Map? tags}) { + _hub.metricsAggregator?.emit( + MetricType.gauge, + key, + value, + unit ?? SentryMeasurementUnit.none, + _enrichWithDefaultTags(tags), + ); + } + + /// Emits a Distribution metric, identified by [key], adding [value] to it. + /// Distributions track a list of values. + /// You can set the [unit] and the optional [tags] to associate to the metric. + void distribution(final String key, + {required final double value, + final SentryMeasurementUnit? unit, + final Map? tags}) { + _hub.metricsAggregator?.emit( + MetricType.distribution, + key, + value, + unit ?? SentryMeasurementUnit.none, + _enrichWithDefaultTags(tags), + ); + } + + /// Emits a Set metric, identified by [key], adding [value] or the CRC32 + /// checksum of [stringValue] to it. + /// Providing both [value] and [stringValue] adds both values to the metric. + /// Sets track a set of values to perform aggregations such as count_unique. + /// You can set the [unit] and the optional [tags] to associate to the metric. + void set(final String key, + {final int? value, + final String? stringValue, + final SentryMeasurementUnit? unit, + final Map? tags}) { + if (value != null) { + _hub.metricsAggregator?.emit( + MetricType.set, + key, + value, + unit ?? SentryMeasurementUnit.none, + _enrichWithDefaultTags(tags), + ); + } + if (stringValue != null && stringValue.isNotEmpty) { + final intValue = Crc32Utils.getCrc32(utf8.encode(stringValue)); + + _hub.metricsAggregator?.emit( + MetricType.set, + key, + intValue, + unit ?? SentryMeasurementUnit.none, + _enrichWithDefaultTags(tags), + ); + } + if (value == null && (stringValue == null || stringValue.isEmpty)) { + _hub.options.logger( + SentryLevel.info, 'No value provided. No metric will be emitted.'); + } + } + + /// Enrich user tags adding default tags + /// + /// Currently adds release, environment and transaction. + Map _enrichWithDefaultTags(Map? userTags) { + // We create another map, in case the userTags is unmodifiable. + final Map tags = Map.from(userTags ?? {}); + if (!_hub.options.enableDefaultTagsForMetrics) { + return tags; + } + // Enrich tags with default values (without overwriting user values) + _putIfAbsentIfNotNull(tags, 'release', _hub.options.release); + _putIfAbsentIfNotNull(tags, 'environment', _hub.options.environment); + _putIfAbsentIfNotNull(tags, 'transaction', _hub.scope.transaction); + return tags; + } + + /// Call [map.putIfAbsent] with [key] and [value] if [value] is not null. + _putIfAbsentIfNotNull(Map map, K key, V? value) { + if (value != null) { + map.putIfAbsent(key, () => value); + } + } + + /// Emits a Distribution metric, identified by [key], with the time it takes + /// to run [function]. + /// You can set the [unit] and the optional [tags] to associate to the metric. + void timing(final String key, + {required FutureOr Function() function, + final DurationSentryMeasurementUnit unit = + DurationSentryMeasurementUnit.second, + final Map? tags}) async { + // Start a span for the metric + final span = _hub.getSpan()?.startChild('metric.timing', description: key); + // Set the user tags to the span as well + if (span != null && tags != null) { + for (final entry in tags.entries) { + span.setTag(entry.key, entry.value); + } + } + final before = _hub.options.clock(); + try { + if (function is Future Function()) { + await function(); + } else { + function(); + } + } finally { + final after = _hub.options.clock(); + Duration duration = after.difference(before); + // If we have a span, we use its duration as value for the emitted metric + if (span != null) { + await span.finish(); + duration = + span.endTimestamp?.difference(span.startTimestamp) ?? duration; + } + final value = _convertMicrosTo(unit, duration.inMicroseconds); + + _hub.metricsAggregator?.emit(MetricType.distribution, key, value, unit, + _enrichWithDefaultTags(tags)); + } + } + + double _convertMicrosTo( + final DurationSentryMeasurementUnit unit, final int micros) { + switch (unit) { + case DurationSentryMeasurementUnit.nanoSecond: + return micros * 1000; + case DurationSentryMeasurementUnit.microSecond: + return micros.toDouble(); + case DurationSentryMeasurementUnit.milliSecond: + return micros / 1000.0; + case DurationSentryMeasurementUnit.second: + return micros / 1000000.0; + case DurationSentryMeasurementUnit.minute: + return micros / 60000000.0; + case DurationSentryMeasurementUnit.hour: + return micros / 3600000000.0; + case DurationSentryMeasurementUnit.day: + return micros / 86400000000.0; + case DurationSentryMeasurementUnit.week: + return micros / 86400000000.0 / 7.0; + } + } +} diff --git a/dart/lib/src/noop_hub.dart b/dart/lib/src/noop_hub.dart index 06d31e7da2..30f68ca895 100644 --- a/dart/lib/src/noop_hub.dart +++ b/dart/lib/src/noop_hub.dart @@ -4,6 +4,9 @@ import 'package:meta/meta.dart'; import 'hint.dart'; import 'hub.dart'; +import 'metrics/metric.dart'; +import 'metrics/metrics_aggregator.dart'; +import 'metrics/metrics_api.dart'; import 'profiling.dart'; import 'protocol.dart'; import 'scope.dart'; @@ -13,16 +16,24 @@ import 'sentry_user_feedback.dart'; import 'tracing.dart'; class NoOpHub implements Hub { - NoOpHub._(); + NoOpHub._() { + _metricsApi = MetricsApi(hub: this); + } static final NoOpHub _instance = NoOpHub._(); final _options = SentryOptions.empty(); + late final MetricsApi _metricsApi; + @override @internal SentryOptions get options => _options; + @override + @internal + MetricsApi get metricsApi => _metricsApi; + factory NoOpHub() { return _instance; } @@ -131,4 +142,14 @@ class NoOpHub implements Hub { @override Scope get scope => Scope(_options); + + @override + @internal + Future captureMetrics( + Map> metricsBuckets) async => + SentryId.empty(); + + @override + @internal + MetricsAggregator? get metricsAggregator => null; } diff --git a/dart/lib/src/noop_sentry_client.dart b/dart/lib/src/noop_sentry_client.dart index 593d63f74b..5a8c04bbae 100644 --- a/dart/lib/src/noop_sentry_client.dart +++ b/dart/lib/src/noop_sentry_client.dart @@ -1,6 +1,10 @@ import 'dart:async'; +import 'package:meta/meta.dart'; + import 'hint.dart'; +import 'metrics/metric.dart'; +import 'metrics/metrics_aggregator.dart'; import 'protocol.dart'; import 'scope.dart'; import 'sentry_client.dart'; @@ -63,4 +67,14 @@ class NoOpSentryClient implements SentryClient { SentryTraceContextHeader? traceContext, }) async => SentryId.empty(); + + @override + @internal + Future captureMetrics( + Map> metricsBuckets) async => + SentryId.empty(); + + @override + @internal + MetricsAggregator? get metricsAggregator => null; } diff --git a/dart/lib/src/noop_sentry_span.dart b/dart/lib/src/noop_sentry_span.dart index 2156aeb678..45d72b94c9 100644 --- a/dart/lib/src/noop_sentry_span.dart +++ b/dart/lib/src/noop_sentry_span.dart @@ -1,3 +1,4 @@ +import 'metrics/local_metrics_aggregator.dart'; import 'protocol.dart'; import 'tracing.dart'; import 'utils.dart'; @@ -95,4 +96,7 @@ class NoOpSentrySpan extends ISentrySpan { @override void scheduleFinish() {} + + @override + LocalMetricsAggregator? get localMetricsAggregator => null; } diff --git a/dart/lib/src/protocol.dart b/dart/lib/src/protocol.dart index 3dac1a6f3c..6d89823721 100644 --- a/dart/lib/src/protocol.dart +++ b/dart/lib/src/protocol.dart @@ -8,6 +8,7 @@ export 'protocol/sentry_device.dart'; export 'protocol/dsn.dart'; export 'protocol/sentry_gpu.dart'; export 'protocol/mechanism.dart'; +export 'protocol/metric_summary.dart'; export 'protocol/sentry_message.dart'; export 'protocol/sentry_operating_system.dart'; export 'protocol/sentry_request.dart'; diff --git a/dart/lib/src/protocol/metric_summary.dart b/dart/lib/src/protocol/metric_summary.dart new file mode 100644 index 0000000000..b0c617fb30 --- /dev/null +++ b/dart/lib/src/protocol/metric_summary.dart @@ -0,0 +1,43 @@ +import '../metrics/metric.dart'; + +class MetricSummary { + final num min; + final num max; + final num sum; + final int count; + final Map? tags; + + MetricSummary.fromGauge(GaugeMetric gauge) + : min = gauge.minimum, + max = gauge.maximum, + sum = gauge.sum, + count = gauge.count, + tags = gauge.tags; + + const MetricSummary( + {required this.min, + required this.max, + required this.sum, + required this.count, + required this.tags}); + + /// Deserializes a [MetricSummary] from JSON [Map]. + factory MetricSummary.fromJson(Map data) => MetricSummary( + min: data['min'], + max: data['max'], + count: data['count'], + sum: data['sum'], + tags: data['tags']?.cast(), + ); + + /// Produces a [Map] that can be serialized to JSON. + Map toJson() { + return { + 'min': min, + 'max': max, + 'count': count, + 'sum': sum, + if (tags?.isNotEmpty ?? false) 'tags': tags, + }; + } +} diff --git a/dart/lib/src/protocol/sentry_span.dart b/dart/lib/src/protocol/sentry_span.dart index e03410d715..780578d182 100644 --- a/dart/lib/src/protocol/sentry_span.dart +++ b/dart/lib/src/protocol/sentry_span.dart @@ -1,6 +1,7 @@ import 'dart:async'; import '../hub.dart'; +import '../metrics/local_metrics_aggregator.dart'; import '../protocol.dart'; import '../sentry_tracer.dart'; @@ -12,6 +13,7 @@ typedef OnFinishedCallback = Future Function({DateTime? endTimestamp}); class SentrySpan extends ISentrySpan { final SentrySpanContext _context; DateTime? _endTimestamp; + Map>? _metricSummaries; late final DateTime _startTimestamp; final Hub _hub; @@ -22,6 +24,7 @@ class SentrySpan extends ISentrySpan { SpanStatus? _status; final Map _tags = {}; OnFinishedCallback? _finishedCallback; + late final LocalMetricsAggregator? _localMetricsAggregator; @override final SentryTracesSamplingDecision? samplingDecision; @@ -37,6 +40,9 @@ class SentrySpan extends ISentrySpan { _startTimestamp = startTimestamp?.toUtc() ?? _hub.options.clock(); _finishedCallback = finishedCallback; _origin = _context.origin; + _localMetricsAggregator = _hub.options.enableSpanLocalMetricAggregation + ? LocalMetricsAggregator() + : null; } @override @@ -65,6 +71,7 @@ class SentrySpan extends ISentrySpan { if (_throwable != null) { _hub.setSpanContext(_throwable, this, _tracer.name); } + _metricSummaries = _localMetricsAggregator?.getSummaries(); await _finishedCallback?.call(endTimestamp: _endTimestamp); return super.finish(status: status, endTimestamp: _endTimestamp); } @@ -154,6 +161,9 @@ class SentrySpan extends ISentrySpan { @override set origin(String? origin) => _origin = origin; + @override + LocalMetricsAggregator? get localMetricsAggregator => _localMetricsAggregator; + Map toJson() { final json = _context.toJson(); json['start_timestamp'] = @@ -174,6 +184,16 @@ class SentrySpan extends ISentrySpan { if (_origin != null) { json['origin'] = _origin; } + + final metricSummariesMap = _metricSummaries?.entries ?? Iterable.empty(); + if (metricSummariesMap.isNotEmpty) { + final map = {}; + for (final entry in metricSummariesMap) { + final summary = entry.value.map((e) => e.toJson()); + map[entry.key] = summary.toList(growable: false); + } + json['_metrics_summary'] = map; + } return json; } diff --git a/dart/lib/src/protocol/sentry_transaction.dart b/dart/lib/src/protocol/sentry_transaction.dart index e00fa23355..eea319aa41 100644 --- a/dart/lib/src/protocol/sentry_transaction.dart +++ b/dart/lib/src/protocol/sentry_transaction.dart @@ -13,6 +13,7 @@ class SentryTransaction extends SentryEvent { @internal final SentryTracer tracer; late final Map measurements; + late final Map>? metricSummaries; late final SentryTransactionInfo? transactionInfo; SentryTransaction( @@ -37,6 +38,7 @@ class SentryTransaction extends SentryEvent { super.request, String? type, Map? measurements, + Map>? metricSummaries, SentryTransactionInfo? transactionInfo, }) : super( timestamp: timestamp ?? tracer.endTimestamp, @@ -52,6 +54,8 @@ class SentryTransaction extends SentryEvent { final spanContext = tracer.context; spans = tracer.children; this.measurements = measurements ?? {}; + this.metricSummaries = + metricSummaries ?? tracer.localMetricsAggregator?.getSummaries(); contexts.trace = spanContext.toTraceContext( sampled: tracer.samplingDecision?.sampled, @@ -85,6 +89,16 @@ class SentryTransaction extends SentryEvent { json['transaction_info'] = transactionInfo.toJson(); } + final metricSummariesMap = metricSummaries?.entries ?? Iterable.empty(); + if (metricSummariesMap.isNotEmpty) { + final map = {}; + for (final entry in metricSummariesMap) { + final summary = entry.value.map((e) => e.toJson()); + map[entry.key] = summary.toList(growable: false); + } + json['_metrics_summary'] = map; + } + return json; } @@ -123,6 +137,7 @@ class SentryTransaction extends SentryEvent { List? threads, String? type, Map? measurements, + Map>? metricSummaries, SentryTransactionInfo? transactionInfo, }) => SentryTransaction( @@ -148,6 +163,9 @@ class SentryTransaction extends SentryEvent { type: type ?? this.type, measurements: (measurements != null ? Map.from(measurements) : null) ?? this.measurements, + metricSummaries: + (metricSummaries != null ? Map.from(metricSummaries) : null) ?? + this.metricSummaries, transactionInfo: transactionInfo ?? this.transactionInfo, ); } diff --git a/dart/lib/src/sentry.dart b/dart/lib/src/sentry.dart index 88fdd42996..1873cd6308 100644 --- a/dart/lib/src/sentry.dart +++ b/dart/lib/src/sentry.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'package:meta/meta.dart'; +import 'metrics/metrics_api.dart'; import 'run_zoned_guarded_integration.dart'; import 'event_processor/enricher/enricher_event_processor.dart'; import 'environment/environment_variables.dart'; @@ -306,6 +307,9 @@ class Sentry { /// Gets the current active transaction or span bound to the scope. static ISentrySpan? getSpan() => _hub.getSpan(); + /// Gets access to the metrics API for the current hub. + static MetricsApi metrics() => _hub.metricsApi; + @internal static Hub get currentHub => _hub; } diff --git a/dart/lib/src/sentry_client.dart b/dart/lib/src/sentry_client.dart index 9761a4b349..47c6fc0d8b 100644 --- a/dart/lib/src/sentry_client.dart +++ b/dart/lib/src/sentry_client.dart @@ -1,6 +1,8 @@ import 'dart:async'; import 'dart:math'; import 'package:meta/meta.dart'; +import 'metrics/metric.dart'; +import 'metrics/metrics_aggregator.dart'; import 'sentry_baggage.dart'; import 'sentry_attachment/sentry_attachment.dart'; @@ -40,6 +42,8 @@ class SentryClient { final Random? _random; + late final MetricsAggregator? _metricsAggregator; + static final _sentryId = Future.value(SentryId.empty()); SentryExceptionFactory get _exceptionFactory => _options.exceptionFactory; @@ -63,7 +67,13 @@ class SentryClient { /// Instantiates a client using [SentryOptions] SentryClient._(this._options) - : _random = _options.sampleRate == null ? null : Random(); + : _random = _options.sampleRate == null ? null : Random(), + _metricsAggregator = _options.enableMetrics + ? MetricsAggregator(options: _options) + : null; + + @internal + MetricsAggregator? get metricsAggregator => _metricsAggregator; /// Reports an [event] to Sentry.io. Future captureEvent( @@ -379,7 +389,22 @@ class SentryClient { return _attachClientReportsAndSend(envelope); } - void close() => _options.httpClient.close(); + /// Reports the [metricsBuckets] to Sentry.io. + Future captureMetrics( + Map> metricsBuckets) async { + final envelope = SentryEnvelope.fromMetrics( + metricsBuckets, + _options.sdk, + dsn: _options.dsn, + ); + final id = await _attachClientReportsAndSend(envelope); + return id ?? SentryId.empty(); + } + + void close() { + _metricsAggregator?.close(); + _options.httpClient.close(); + } Future _runBeforeSend( SentryEvent event, { diff --git a/dart/lib/src/sentry_envelope.dart b/dart/lib/src/sentry_envelope.dart index eb62aeec47..7835b7859e 100644 --- a/dart/lib/src/sentry_envelope.dart +++ b/dart/lib/src/sentry_envelope.dart @@ -1,5 +1,6 @@ import 'dart:convert'; import 'client_reports/client_report.dart'; +import 'metrics/metric.dart'; import 'protocol.dart'; import 'sentry_item_type.dart'; import 'sentry_options.dart'; @@ -20,7 +21,7 @@ class SentryEnvelope { /// All items contained in the envelope. final List items; - /// Create an [SentryEnvelope] with containing one [SentryEnvelopeItem] which holds the [SentryEvent] data. + /// Create a [SentryEnvelope] containing one [SentryEnvelopeItem] which holds the [SentryEvent] data. factory SentryEnvelope.fromEvent( SentryEvent event, SdkVersion sdkVersion, { @@ -59,7 +60,7 @@ class SentryEnvelope { ); } - /// Create an [SentryEnvelope] with containing one [SentryEnvelopeItem] which holds the [SentryTransaction] data. + /// Create a [SentryEnvelope] containing one [SentryEnvelopeItem] which holds the [SentryTransaction] data. factory SentryEnvelope.fromTransaction( SentryTransaction transaction, SdkVersion sdkVersion, { @@ -82,6 +83,22 @@ class SentryEnvelope { ); } + /// Create a [SentryEnvelope] containing one [SentryEnvelopeItem] which holds the [Metric] data. + factory SentryEnvelope.fromMetrics( + Map> metricsBuckets, + SdkVersion sdkVersion, { + String? dsn, + }) { + return SentryEnvelope( + SentryEnvelopeHeader( + SentryId.newId(), + sdkVersion, + dsn: dsn, + ), + [SentryEnvelopeItem.fromMetrics(metricsBuckets)], + ); + } + /// Stream binary data representation of `Envelope` file encoded. Stream> envelopeStream(SentryOptions options) async* { yield utf8JsonEncoder.convert(header.toJson()); diff --git a/dart/lib/src/sentry_envelope_item.dart b/dart/lib/src/sentry_envelope_item.dart index 5e38a7123d..019e1e0a08 100644 --- a/dart/lib/src/sentry_envelope_item.dart +++ b/dart/lib/src/sentry_envelope_item.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'dart:convert'; import 'client_reports/client_report.dart'; +import 'metrics/metric.dart'; import 'protocol.dart'; import 'utils.dart'; import 'sentry_attachment/sentry_attachment.dart'; @@ -13,7 +14,7 @@ import 'sentry_user_feedback.dart'; class SentryEnvelopeItem { SentryEnvelopeItem(this.header, this.dataFactory); - /// Creates an [SentryEnvelopeItem] which sends [SentryTransaction]. + /// Creates a [SentryEnvelopeItem] which sends [SentryTransaction]. factory SentryEnvelopeItem.fromTransaction(SentryTransaction transaction) { final cachedItem = _CachedItem(() async => utf8JsonEncoder.convert(transaction.toJson())); @@ -27,7 +28,7 @@ class SentryEnvelopeItem { } factory SentryEnvelopeItem.fromAttachment(SentryAttachment attachment) { - final cachedItem = _CachedItem(() => attachment.bytes); + final cachedItem = _CachedItem(() async => attachment.bytes); final header = SentryEnvelopeItemHeader( SentryItemType.attachment, @@ -39,7 +40,7 @@ class SentryEnvelopeItem { return SentryEnvelopeItem(header, cachedItem.getData); } - /// Create an [SentryEnvelopeItem] which sends [SentryUserFeedback]. + /// Create a [SentryEnvelopeItem] which sends [SentryUserFeedback]. factory SentryEnvelopeItem.fromUserFeedback(SentryUserFeedback feedback) { final cachedItem = _CachedItem(() async => utf8JsonEncoder.convert(feedback.toJson())); @@ -52,7 +53,7 @@ class SentryEnvelopeItem { return SentryEnvelopeItem(header, cachedItem.getData); } - /// Create an [SentryEnvelopeItem] which holds the [SentryEvent] data. + /// Create a [SentryEnvelopeItem] which holds the [SentryEvent] data. factory SentryEnvelopeItem.fromEvent(SentryEvent event) { final cachedItem = _CachedItem(() async => utf8JsonEncoder.convert(event.toJson())); @@ -67,7 +68,7 @@ class SentryEnvelopeItem { ); } - /// Create an [SentryEnvelopeItem] which holds the [ClientReport] data. + /// Create a [SentryEnvelopeItem] which holds the [ClientReport] data. factory SentryEnvelopeItem.fromClientReport(ClientReport clientReport) { final cachedItem = _CachedItem(() async => utf8JsonEncoder.convert(clientReport.toJson())); @@ -82,6 +83,28 @@ class SentryEnvelopeItem { ); } + /// Creates a [SentryEnvelopeItem] which holds several [Metric] data. + factory SentryEnvelopeItem.fromMetrics(Map> buckets) { + final cachedItem = _CachedItem(() async { + final statsd = StringBuffer(); + // Encode all metrics of a bucket in statsd format, using the bucket key, + // which is the timestamp of the bucket. + for (final bucket in buckets.entries) { + final encodedMetrics = + bucket.value.map((metric) => metric.encodeToStatsd(bucket.key)); + statsd.write(encodedMetrics.join('\n')); + } + return utf8.encode(statsd.toString()); + }); + + final header = SentryEnvelopeItemHeader( + SentryItemType.statsd, + cachedItem.getDataLength, + contentType: 'application/octet-stream', + ); + return SentryEnvelopeItem(header, cachedItem.getData); + } + /// Header with info about type and length of data in bytes. final SentryEnvelopeItemHeader header; @@ -109,16 +132,11 @@ class SentryEnvelopeItem { class _CachedItem { _CachedItem(this._dataFactory); - final FutureOr> Function() _dataFactory; + final Future> Function() _dataFactory; List? _data; Future> getData() async { - final data = _dataFactory(); - if (data is Future>) { - _data ??= await data; - } else { - _data ??= data; - } + _data ??= await _dataFactory(); return _data!; } diff --git a/dart/lib/src/sentry_item_type.dart b/dart/lib/src/sentry_item_type.dart index 6215cbb78f..18dbc8f4ad 100644 --- a/dart/lib/src/sentry_item_type.dart +++ b/dart/lib/src/sentry_item_type.dart @@ -5,5 +5,6 @@ class SentryItemType { static const String transaction = 'transaction'; static const String clientReport = 'client_report'; static const String profile = 'profile'; + static const String statsd = 'statsd'; static const String unknown = '__unknown__'; } diff --git a/dart/lib/src/sentry_options.dart b/dart/lib/src/sentry_options.dart index 1de3a49d0f..eea642ae48 100644 --- a/dart/lib/src/sentry_options.dart +++ b/dart/lib/src/sentry_options.dart @@ -165,6 +165,10 @@ class SentryOptions { /// to the scope. When nothing is returned from the function, the breadcrumb is dropped BeforeBreadcrumbCallback? beforeBreadcrumb; + /// This function is called right before a metric is about to be emitted. + /// Can return true to emit the metric, or false to drop it. + BeforeMetricCallback? beforeMetricCallback; + /// Sets the release. SDK will try to automatically configure a release out of the box /// See [docs for further information](https://docs.sentry.io/platforms/flutter/configuration/releases/) String? release; @@ -380,6 +384,48 @@ class SentryOptions { /// are set. bool? enableTracing; + /// Enables sending developer metrics to Sentry. + /// More on https://develop.sentry.dev/delightful-developer-metrics/. + /// Example: + /// ```dart + /// Sentry.metrics.counter('myMetric'); + /// ``` + @experimental + bool enableMetrics = false; + + @experimental + bool _enableDefaultTagsForMetrics = true; + + /// Enables enriching metrics with default tags. Requires [enableMetrics]. + /// More on https://develop.sentry.dev/delightful-developer-metrics/sending-metrics-sdk/#automatic-tags-extraction + /// Currently adds release, environment and transaction name. + @experimental + bool get enableDefaultTagsForMetrics => + enableMetrics && _enableDefaultTagsForMetrics; + + /// Enables enriching metrics with default tags. Requires [enableMetrics]. + /// More on https://develop.sentry.dev/delightful-developer-metrics/sending-metrics-sdk/#automatic-tags-extraction + /// Currently adds release, environment and transaction name. + @experimental + set enableDefaultTagsForMetrics(final bool enableDefaultTagsForMetrics) => + _enableDefaultTagsForMetrics = enableDefaultTagsForMetrics; + + @experimental + bool _enableSpanLocalMetricAggregation = true; + + /// Enables span metrics aggregation. Requires [enableMetrics]. + /// More on https://develop.sentry.dev/sdk/metrics/#span-aggregation + @experimental + bool get enableSpanLocalMetricAggregation => + enableMetrics && _enableSpanLocalMetricAggregation; + + /// Enables span metrics aggregation. Requires [enableMetrics]. + /// More on https://develop.sentry.dev/sdk/metrics/#span-aggregation + @experimental + set enableSpanLocalMetricAggregation( + final bool enableSpanLocalMetricAggregation) => + _enableSpanLocalMetricAggregation = enableSpanLocalMetricAggregation; + /// Only for internal use. Changed SDK behaviour when set to true: /// - Rethrow exceptions that occur in user provided closures @internal @@ -500,6 +546,13 @@ typedef BeforeBreadcrumbCallback = Breadcrumb? Function( Hint? hint, }); +/// This function is called right before a metric is about to be emitted. +/// Can return true to emit the metric, or false to drop it. +typedef BeforeMetricCallback = bool Function( + String key, { + Map? tags, +}); + /// Used to provide timestamp for logging. typedef ClockProvider = DateTime Function(); diff --git a/dart/lib/src/sentry_span_interface.dart b/dart/lib/src/sentry_span_interface.dart index cdc121f849..1d142c45b9 100644 --- a/dart/lib/src/sentry_span_interface.dart +++ b/dart/lib/src/sentry_span_interface.dart @@ -1,5 +1,6 @@ import 'package:meta/meta.dart'; +import 'metrics/local_metrics_aggregator.dart'; import 'protocol.dart'; import 'tracing.dart'; @@ -46,6 +47,9 @@ abstract class ISentrySpan { /// See https://develop.sentry.dev/sdk/performance/trace-origin set origin(String? origin); + @internal + LocalMetricsAggregator? get localMetricsAggregator; + /// Returns the end timestamp if finished DateTime? get endTimestamp; diff --git a/dart/lib/src/sentry_tracer.dart b/dart/lib/src/sentry_tracer.dart index c7f6993ad3..d9ea75d256 100644 --- a/dart/lib/src/sentry_tracer.dart +++ b/dart/lib/src/sentry_tracer.dart @@ -3,6 +3,7 @@ import 'dart:async'; import 'package:meta/meta.dart'; import '../sentry.dart'; +import 'metrics/local_metrics_aggregator.dart'; import 'profiling.dart'; import 'sentry_tracer_finish_status.dart'; import 'utils/sample_rate_format.dart'; @@ -413,4 +414,8 @@ class SentryTracer extends ISentrySpan { }); } } + + @override + LocalMetricsAggregator? get localMetricsAggregator => + _rootSpan.localMetricsAggregator; } diff --git a/dart/lib/src/transport/data_category.dart b/dart/lib/src/transport/data_category.dart index 1843acfacb..f21da18ed7 100644 --- a/dart/lib/src/transport/data_category.dart +++ b/dart/lib/src/transport/data_category.dart @@ -7,6 +7,7 @@ enum DataCategory { transaction, attachment, security, + metricBucket, unknown } @@ -27,6 +28,8 @@ extension DataCategoryExtension on DataCategory { return DataCategory.attachment; case 'security': return DataCategory.security; + case 'metric_bucket': + return DataCategory.metricBucket; } return DataCategory.unknown; } @@ -47,6 +50,8 @@ extension DataCategoryExtension on DataCategory { return 'attachment'; case DataCategory.security: return 'security'; + case DataCategory.metricBucket: + return 'metric_bucket'; case DataCategory.unknown: return 'unknown'; } diff --git a/dart/lib/src/transport/rate_limit.dart b/dart/lib/src/transport/rate_limit.dart index 8f41b91d81..00284a3ba7 100644 --- a/dart/lib/src/transport/rate_limit.dart +++ b/dart/lib/src/transport/rate_limit.dart @@ -2,8 +2,10 @@ import 'data_category.dart'; /// `RateLimit` containing limited `DataCategory` and duration in milliseconds. class RateLimit { - RateLimit(this.category, this.duration); + RateLimit(this.category, this.duration, {List? namespaces}) + : namespaces = (namespaces?..removeWhere((e) => e.isEmpty)) ?? []; final DataCategory category; final Duration duration; + final List namespaces; } diff --git a/dart/lib/src/transport/rate_limit_parser.dart b/dart/lib/src/transport/rate_limit_parser.dart index 63f4f179d1..03391e0210 100644 --- a/dart/lib/src/transport/rate_limit_parser.dart +++ b/dart/lib/src/transport/rate_limit_parser.dart @@ -14,6 +14,7 @@ class RateLimitParser { if (rateLimitHeader == null) { return []; } + // example: 2700:metric_bucket:organization:quota_exceeded:custom,... final rateLimits = []; final rateLimitValues = rateLimitHeader.toLowerCase().split(','); for (final rateLimitValue in rateLimitValues) { @@ -30,7 +31,17 @@ class RateLimitParser { final categoryValues = allCategories.split(';'); for (final categoryValue in categoryValues) { final category = DataCategoryExtension.fromStringValue(categoryValue); - if (category != DataCategory.unknown) { + // Metric buckets rate limit can have namespaces + if (category == DataCategory.metricBucket) { + final namespaces = durationAndCategories.length > 4 + ? durationAndCategories[4] + : null; + rateLimits.add(RateLimit( + category, + duration, + namespaces: namespaces?.trim().split(','), + )); + } else if (category != DataCategory.unknown) { rateLimits.add(RateLimit(category, duration)); } } diff --git a/dart/lib/src/transport/rate_limiter.dart b/dart/lib/src/transport/rate_limiter.dart index 6d4d3c3e9a..ef9b168edd 100644 --- a/dart/lib/src/transport/rate_limiter.dart +++ b/dart/lib/src/transport/rate_limiter.dart @@ -64,6 +64,11 @@ class RateLimiter { } for (final rateLimit in rateLimits) { + if (rateLimit.category == DataCategory.metricBucket && + rateLimit.namespaces.isNotEmpty && + !rateLimit.namespaces.contains('custom')) { + continue; + } _applyRetryAfterOnlyIfLonger( rateLimit.category, DateTime.fromMillisecondsSinceEpoch( @@ -111,6 +116,10 @@ class RateLimiter { return DataCategory.attachment; case 'transaction': return DataCategory.transaction; + // The envelope item type used for metrics is statsd, + // whereas the client report category is metric_bucket + case 'statsd': + return DataCategory.metricBucket; default: return DataCategory.unknown; } diff --git a/dart/lib/src/utils/crc32_utils.dart b/dart/lib/src/utils/crc32_utils.dart new file mode 100644 index 0000000000..8e6f63fd53 --- /dev/null +++ b/dart/lib/src/utils/crc32_utils.dart @@ -0,0 +1,313 @@ +// Adapted from the archive library (https://pub.dev/packages/archive) +// https://github.com/brendan-duncan/archive/blob/21c864efe0df2b7fd962b59ff0a714c96732bf7d/lib/src/util/crc32.dart +// +// The MIT License +// +// Copyright (c) 2013-2021 Brendan Duncan. +// All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +/// Util class to compute the CRC-32 checksum of a given array. +class Crc32Utils { + /// Get the CRC-32 checksum of the given array. You can append bytes to an + /// already computed crc by specifying the previous [crc] value. + static int getCrc32(List array, [int crc = 0]) { + var len = array.length; + crc = crc ^ 0xffffffff; + var ip = 0; + while (len >= 8) { + crc = _crc32Table[(crc ^ array[ip++]) & 0xff] ^ (crc >> 8); + crc = _crc32Table[(crc ^ array[ip++]) & 0xff] ^ (crc >> 8); + crc = _crc32Table[(crc ^ array[ip++]) & 0xff] ^ (crc >> 8); + crc = _crc32Table[(crc ^ array[ip++]) & 0xff] ^ (crc >> 8); + crc = _crc32Table[(crc ^ array[ip++]) & 0xff] ^ (crc >> 8); + crc = _crc32Table[(crc ^ array[ip++]) & 0xff] ^ (crc >> 8); + crc = _crc32Table[(crc ^ array[ip++]) & 0xff] ^ (crc >> 8); + crc = _crc32Table[(crc ^ array[ip++]) & 0xff] ^ (crc >> 8); + len -= 8; + } + if (len > 0) { + do { + crc = _crc32Table[(crc ^ array[ip++]) & 0xff] ^ (crc >> 8); + } while (--len > 0); + } + return crc ^ 0xffffffff; + } +} + +// Precomputed CRC table for faster calculations. +const List _crc32Table = [ + 0, + 1996959894, + 3993919788, + 2567524794, + 124634137, + 1886057615, + 3915621685, + 2657392035, + 249268274, + 2044508324, + 3772115230, + 2547177864, + 162941995, + 2125561021, + 3887607047, + 2428444049, + 498536548, + 1789927666, + 4089016648, + 2227061214, + 450548861, + 1843258603, + 4107580753, + 2211677639, + 325883990, + 1684777152, + 4251122042, + 2321926636, + 335633487, + 1661365465, + 4195302755, + 2366115317, + 997073096, + 1281953886, + 3579855332, + 2724688242, + 1006888145, + 1258607687, + 3524101629, + 2768942443, + 901097722, + 1119000684, + 3686517206, + 2898065728, + 853044451, + 1172266101, + 3705015759, + 2882616665, + 651767980, + 1373503546, + 3369554304, + 3218104598, + 565507253, + 1454621731, + 3485111705, + 3099436303, + 671266974, + 1594198024, + 3322730930, + 2970347812, + 795835527, + 1483230225, + 3244367275, + 3060149565, + 1994146192, + 31158534, + 2563907772, + 4023717930, + 1907459465, + 112637215, + 2680153253, + 3904427059, + 2013776290, + 251722036, + 2517215374, + 3775830040, + 2137656763, + 141376813, + 2439277719, + 3865271297, + 1802195444, + 476864866, + 2238001368, + 4066508878, + 1812370925, + 453092731, + 2181625025, + 4111451223, + 1706088902, + 314042704, + 2344532202, + 4240017532, + 1658658271, + 366619977, + 2362670323, + 4224994405, + 1303535960, + 984961486, + 2747007092, + 3569037538, + 1256170817, + 1037604311, + 2765210733, + 3554079995, + 1131014506, + 879679996, + 2909243462, + 3663771856, + 1141124467, + 855842277, + 2852801631, + 3708648649, + 1342533948, + 654459306, + 3188396048, + 3373015174, + 1466479909, + 544179635, + 3110523913, + 3462522015, + 1591671054, + 702138776, + 2966460450, + 3352799412, + 1504918807, + 783551873, + 3082640443, + 3233442989, + 3988292384, + 2596254646, + 62317068, + 1957810842, + 3939845945, + 2647816111, + 81470997, + 1943803523, + 3814918930, + 2489596804, + 225274430, + 2053790376, + 3826175755, + 2466906013, + 167816743, + 2097651377, + 4027552580, + 2265490386, + 503444072, + 1762050814, + 4150417245, + 2154129355, + 426522225, + 1852507879, + 4275313526, + 2312317920, + 282753626, + 1742555852, + 4189708143, + 2394877945, + 397917763, + 1622183637, + 3604390888, + 2714866558, + 953729732, + 1340076626, + 3518719985, + 2797360999, + 1068828381, + 1219638859, + 3624741850, + 2936675148, + 906185462, + 1090812512, + 3747672003, + 2825379669, + 829329135, + 1181335161, + 3412177804, + 3160834842, + 628085408, + 1382605366, + 3423369109, + 3138078467, + 570562233, + 1426400815, + 3317316542, + 2998733608, + 733239954, + 1555261956, + 3268935591, + 3050360625, + 752459403, + 1541320221, + 2607071920, + 3965973030, + 1969922972, + 40735498, + 2617837225, + 3943577151, + 1913087877, + 83908371, + 2512341634, + 3803740692, + 2075208622, + 213261112, + 2463272603, + 3855990285, + 2094854071, + 198958881, + 2262029012, + 4057260610, + 1759359992, + 534414190, + 2176718541, + 4139329115, + 1873836001, + 414664567, + 2282248934, + 4279200368, + 1711684554, + 285281116, + 2405801727, + 4167216745, + 1634467795, + 376229701, + 2685067896, + 3608007406, + 1308918612, + 956543938, + 2808555105, + 3495958263, + 1231636301, + 1047427035, + 2932959818, + 3654703836, + 1088359270, + 936918000, + 2847714899, + 3736837829, + 1202900863, + 817233897, + 3183342108, + 3401237130, + 1404277552, + 615818150, + 3134207493, + 3453421203, + 1423857449, + 601450431, + 3009837614, + 3294710456, + 1567103746, + 711928724, + 3020668471, + 3272380065, + 1510334235, + 755167117 +]; diff --git a/dart/test/hub_test.dart b/dart/test/hub_test.dart index 31698329d6..8dcc622654 100644 --- a/dart/test/hub_test.dart +++ b/dart/test/hub_test.dart @@ -81,6 +81,21 @@ void main() { expect(fixture.client.captureMessageCalls.first.scope, isNotNull); }); + test('should capture metrics', () async { + final hub = fixture.getSut(); + await hub.captureMetrics(fakeMetrics); + + expect(fixture.client.captureMetricsCalls.length, 1); + expect( + fixture.client.captureMetricsCalls.first.values, + [ + [fakeMetric], + [fakeMetric, fakeMetric2], + [fakeMetric, fakeMetric3, fakeMetric4], + ], + ); + }); + test('should save the lastEventId', () async { final hub = fixture.getSut(); final event = SentryEvent(); @@ -155,7 +170,7 @@ void main() { }); }); - group('Hub captures', () { + group('Hub transactions', () { late Fixture fixture; setUp(() { @@ -376,6 +391,14 @@ void main() { expect( fixture.client.captureTransactionCalls.first.traceContext, context); }); + }); + + group('Hub profiles', () { + late Fixture fixture; + + setUp(() { + fixture = Fixture(); + }); test('profiler is not started by default', () async { final hub = fixture.getSut(); @@ -432,14 +455,6 @@ void main() { verify(profiler.dispose()).called(1); verifyNever(profiler.finishFor(any)); }); - - test('returns scope', () async { - final hub = fixture.getSut(); - - final scope = hub.scope; - - expect(scope, isNotNull); - }); }); group('Hub scope', () { @@ -452,6 +467,11 @@ void main() { hub.bindClient(client); }); + test('returns scope', () async { + final scope = hub.scope; + expect(scope, isNotNull); + }); + test('should configure its scope', () async { await hub.configureScope((Scope scope) { scope @@ -681,6 +701,44 @@ void main() { expect(fixture.recorder.category, DataCategory.transaction); }); }); + + group('Metrics', () { + late Fixture fixture; + + setUp(() { + fixture = Fixture(); + }); + + test('should not capture metrics if enableMetric is false', () async { + final hub = fixture.getSut(enableMetrics: false, debug: true); + await hub.captureMetrics(fakeMetrics); + + expect(fixture.client.captureMetricsCalls, isEmpty); + expect(fixture.loggedMessage, + 'Metrics are disabled and this \'captureMetrics\' call is a no-op.'); + }); + + test('should not capture metrics if hub is closed', () async { + final hub = fixture.getSut(debug: true); + await hub.close(); + + expect(hub.isEnabled, false); + await hub.captureMetrics(fakeMetrics); + expect(fixture.loggedMessage, + 'Instance is disabled and this \'captureMetrics\' call is a no-op.'); + + expect(fixture.client.captureMetricsCalls, isEmpty); + }); + + test('should not capture metrics if metrics are empty', () async { + final hub = fixture.getSut(debug: true); + await hub.captureMetrics({}); + expect(fixture.loggedMessage, + 'Metrics are empty and this \'captureMetrics\' call is a no-op.'); + + expect(fixture.client.captureMetricsCalls, isEmpty); + }); + }); } class Fixture { @@ -692,17 +750,20 @@ class Fixture { late SentryTracer tracer; SentryLevel? loggedLevel; + String? loggedMessage; Object? loggedException; Hub getSut({ double? tracesSampleRate = 1.0, TracesSamplerCallback? tracesSampler, bool? sampled = true, + bool enableMetrics = true, bool debug = false, }) { options.tracesSampleRate = tracesSampleRate; options.tracesSampler = tracesSampler; options.debug = debug; + options.enableMetrics = enableMetrics; options.logger = mockLogger; // Enable logging in DiagnosticsLogger final hub = Hub(options); @@ -731,6 +792,7 @@ class Fixture { StackTrace? stackTrace, }) { loggedLevel = level; + loggedMessage = message; loggedException = exception; } } diff --git a/dart/test/metrics/local_metrics_aggregator_test.dart b/dart/test/metrics/local_metrics_aggregator_test.dart new file mode 100644 index 0000000000..42648fdaf2 --- /dev/null +++ b/dart/test/metrics/local_metrics_aggregator_test.dart @@ -0,0 +1,40 @@ +import 'package:sentry/src/metrics/local_metrics_aggregator.dart'; +import 'package:test/expect.dart'; +import 'package:test/scaffolding.dart'; + +import '../mocks.dart'; + +void main() { + group('add', () { + late LocalMetricsAggregator aggregator; + + setUp(() { + aggregator = LocalMetricsAggregator(); + }); + + test('same metric multiple times aggregates them', () async { + aggregator.add(fakeMetric, 1); + aggregator.add(fakeMetric, 2); + final summaries = aggregator.getSummaries(); + expect(summaries.length, 1); + final summary = summaries.values.first; + expect(summary.length, 1); + }); + + test('same metric different tags aggregates summary bucket', () async { + aggregator.add(fakeMetric, 1); + aggregator.add(fakeMetric..tags.clear(), 2); + final summaries = aggregator.getSummaries(); + expect(summaries.length, 1); + final summary = summaries.values.first; + expect(summary.length, 2); + }); + + test('different metrics does not aggregate them', () async { + aggregator.add(fakeMetric, 1); + aggregator.add(fakeMetric2, 2); + final summaries = aggregator.getSummaries(); + expect(summaries.length, 2); + }); + }); +} diff --git a/dart/test/metrics/metric_test.dart b/dart/test/metrics/metric_test.dart new file mode 100644 index 0000000000..f3edc0486b --- /dev/null +++ b/dart/test/metrics/metric_test.dart @@ -0,0 +1,315 @@ +import 'package:sentry/sentry.dart'; +import 'package:sentry/src/metrics/metric.dart'; +import 'package:test/expect.dart'; +import 'package:test/scaffolding.dart'; + +import 'metrics_aggregator_test.dart'; + +void main() { + group('fromType', () { + test('counter creates a CounterMetric', () async { + final Metric metric = Metric.fromType( + type: MetricType.counter, + key: mockKey, + value: 1, + unit: mockUnit, + tags: mockTags); + expect(metric, isA()); + }); + + test('gauge creates a GaugeMetric', () async { + final Metric metric = Metric.fromType( + type: MetricType.gauge, + key: mockKey, + value: 1, + unit: mockUnit, + tags: mockTags); + expect(metric, isA()); + }); + + test('distribution creates a DistributionMetric', () async { + final Metric metric = Metric.fromType( + type: MetricType.distribution, + key: mockKey, + value: 1, + unit: mockUnit, + tags: mockTags); + expect(metric, isA()); + }); + + test('set creates a SetMetric', () async { + final Metric metric = Metric.fromType( + type: MetricType.set, + key: mockKey, + value: 1, + unit: mockUnit, + tags: mockTags); + expect(metric, isA()); + }); + }); + + group('Encode to statsd', () { + late Fixture fixture; + + setUp(() { + fixture = Fixture(); + }); + + test('encode CounterMetric', () async { + final int bucketKey = 10; + final expectedStatsd = + 'key_metric_@hour:2.1|c|#tag1:tag\\u{2c} value 1,key2:&@"13/-d_s|T10'; + final actualStatsd = fixture.counterMetric.encodeToStatsd(bucketKey); + expect(actualStatsd, expectedStatsd); + }); + + test('sanitize name', () async { + final metric = Metric.fromType( + type: MetricType.counter, + value: 2.1, + key: 'key£ - @# metric!', + unit: DurationSentryMeasurementUnit.day, + tags: {}, + ); + + final expectedStatsd = 'key_-_metric_@day:2.1|c|T10'; + expect(metric.encodeToStatsd(10), expectedStatsd); + }); + + test('sanitize unit', () async { + final metric = Metric.fromType( + type: MetricType.counter, + value: 2.1, + key: 'key', + unit: CustomSentryMeasurementUnit('weird-measurement name!'), + tags: {}, + ); + + final expectedStatsd = 'key@weirdmeasurementname:2.1|c|T10'; + expect(metric.encodeToStatsd(10), expectedStatsd); + }); + + test('sanitize tags', () async { + final metric = Metric.fromType( + type: MetricType.counter, + value: 2.1, + key: 'key', + unit: DurationSentryMeasurementUnit.day, + tags: {'tag1': 'tag, value 1', 'key 2': '&@"13/-d_s'}, + ); + + final expectedStatsd = + 'key@day:2.1|c|#tag1:tag\\u{2c} value 1,key2:&@"13/-d_s|T10'; + expect(metric.encodeToStatsd(10), expectedStatsd); + }); + }); + + group('getCompositeKey', () { + late Fixture fixture; + + setUp(() { + fixture = Fixture(); + }); + + test('escapes commas from tags', () async { + final Iterable tags = fixture.counterMetric.tags.values; + final joinedTags = tags.join(); + final Iterable expectedTags = + tags.map((e) => e.replaceAll(',', '\\,')); + final actualKey = fixture.counterMetric.getCompositeKey(); + + expect(joinedTags.contains(','), true); + expect(joinedTags.contains('\\,'), false); + expect(actualKey.contains('\\,'), true); + for (var tag in expectedTags) { + expect(actualKey.contains(tag), true); + } + }); + + test('CounterMetric', () async { + final expectedKey = + 'c_key metric!_hour_tag1=tag\\, value 1,key 2=&@"13/-d_s'; + final actualKey = fixture.counterMetric.getCompositeKey(); + expect(actualKey, expectedKey); + }); + + test('GaugeMetric', () async { + final expectedKey = + 'g_key metric!_hour_tag1=tag\\, value 1,key 2=&@"13/-d_s'; + final actualKey = fixture.gaugeMetric.getCompositeKey(); + expect(actualKey, expectedKey); + }); + + test('DistributionMetric', () async { + final expectedKey = + 'd_key metric!_hour_tag1=tag\\, value 1,key 2=&@"13/-d_s'; + final actualKey = fixture.distributionMetric.getCompositeKey(); + expect(actualKey, expectedKey); + }); + + test('SetMetric', () async { + final expectedKey = + 's_key metric!_hour_tag1=tag\\, value 1,key 2=&@"13/-d_s'; + final actualKey = fixture.setMetric.getCompositeKey(); + expect(actualKey, expectedKey); + }); + }); + + group('getSpanAggregationKey', () { + late Fixture fixture; + + setUp(() { + fixture = Fixture(); + }); + + test('CounterMetric', () async { + final expectedKey = 'c:key metric!@hour'; + final actualKey = fixture.counterMetric.getSpanAggregationKey(); + expect(actualKey, expectedKey); + }); + + test('GaugeMetric', () async { + final expectedKey = 'g:key metric!@hour'; + final actualKey = fixture.gaugeMetric.getSpanAggregationKey(); + expect(actualKey, expectedKey); + }); + + test('DistributionMetric', () async { + final expectedKey = 'd:key metric!@hour'; + final actualKey = fixture.distributionMetric.getSpanAggregationKey(); + expect(actualKey, expectedKey); + }); + + test('SetMetric', () async { + final expectedKey = 's:key metric!@hour'; + final actualKey = fixture.setMetric.getSpanAggregationKey(); + expect(actualKey, expectedKey); + }); + }); + + group('getWeight', () { + late Fixture fixture; + + setUp(() { + fixture = Fixture(); + }); + + test('counter always returns 1', () async { + final CounterMetric metric = fixture.counterMetric; + expect(metric.getWeight(), 1); + metric.add(5); + metric.add(2); + expect(metric.getWeight(), 1); + }); + + test('gauge always returns 5', () async { + final GaugeMetric metric = fixture.gaugeMetric; + expect(metric.getWeight(), 5); + metric.add(5); + metric.add(2); + expect(metric.getWeight(), 5); + }); + + test('distribution returns number of values', () async { + final DistributionMetric metric = fixture.distributionMetric; + expect(metric.getWeight(), 1); + metric.add(5); + // Repeated values are counted + metric.add(5); + expect(metric.getWeight(), 3); + }); + + test('set returns number of unique values', () async { + final SetMetric metric = fixture.setMetric; + expect(metric.getWeight(), 1); + metric.add(5); + // Repeated values are not counted + metric.add(5); + expect(metric.getWeight(), 2); + }); + }); + + group('add', () { + late Fixture fixture; + + setUp(() { + fixture = Fixture(); + }); + + test('counter increments', () async { + final CounterMetric metric = fixture.counterMetric; + expect(metric.value, 2.1); + metric.add(5); + metric.add(2); + expect(metric.value, 9.1); + }); + + test('gauge stores min, max, last, sum and count', () async { + final GaugeMetric metric = fixture.gaugeMetric; + expect(metric.minimum, 2.1); + expect(metric.maximum, 2.1); + expect(metric.last, 2.1); + expect(metric.sum, 2.1); + expect(metric.count, 1); + metric.add(1.4); + metric.add(5.4); + expect(metric.minimum, 1.4); + expect(metric.maximum, 5.4); + expect(metric.last, 5.4); + expect(metric.sum, 8.9); + expect(metric.count, 3); + }); + + test('distribution stores all values', () async { + final DistributionMetric metric = fixture.distributionMetric; + metric.add(2); + metric.add(4); + metric.add(4); + expect(metric.values, [2.1, 2, 4, 4]); + }); + + test('set stores unique int values', () async { + final SetMetric metric = fixture.setMetric; + metric.add(5); + // Repeated values are not counted + metric.add(5); + expect(metric.values, {2, 5}); + }); + }); +} + +class Fixture { + // We use a fractional number because on some platforms converting '2' to + // string return '2', while others '2.0', and we'd have issues testing. + final CounterMetric counterMetric = Metric.fromType( + type: MetricType.counter, + value: 2.1, + key: 'key metric!', + unit: DurationSentryMeasurementUnit.hour, + tags: {'tag1': 'tag, value 1', 'key 2': '&@"13/-d_s'}, + ) as CounterMetric; + + final GaugeMetric gaugeMetric = Metric.fromType( + type: MetricType.gauge, + value: 2.1, + key: 'key metric!', + unit: DurationSentryMeasurementUnit.hour, + tags: {'tag1': 'tag, value 1', 'key 2': '&@"13/-d_s'}, + ) as GaugeMetric; + + final DistributionMetric distributionMetric = Metric.fromType( + type: MetricType.distribution, + value: 2.1, + key: 'key metric!', + unit: DurationSentryMeasurementUnit.hour, + tags: {'tag1': 'tag, value 1', 'key 2': '&@"13/-d_s'}, + ) as DistributionMetric; + + final SetMetric setMetric = Metric.fromType( + type: MetricType.set, + value: 2.1, + key: 'key metric!', + unit: DurationSentryMeasurementUnit.hour, + tags: {'tag1': 'tag, value 1', 'key 2': '&@"13/-d_s'}, + ) as SetMetric; +} diff --git a/dart/test/metrics/metrics_aggregator_test.dart b/dart/test/metrics/metrics_aggregator_test.dart new file mode 100644 index 0000000000..5636e7ebf6 --- /dev/null +++ b/dart/test/metrics/metrics_aggregator_test.dart @@ -0,0 +1,493 @@ +import 'package:sentry/sentry.dart'; +import 'package:sentry/src/metrics/metric.dart'; +import 'package:sentry/src/metrics/metrics_aggregator.dart'; +import 'package:test/test.dart'; + +import '../mocks.dart'; +import '../mocks/mock_hub.dart'; + +void main() { + group('emit', () { + late Fixture fixture; + + setUp(() { + fixture = Fixture(); + }); + + test('counter', () async { + final MetricsAggregator sut = fixture.getSut(); + final String key = 'metric key'; + final double value = 5; + final SentryMeasurementUnit unit = DurationSentryMeasurementUnit.minute; + final Map tags = {'tag1': 'val1', 'tag2': 'val2'}; + sut.emit(MetricType.counter, key, value, unit, tags); + + final metricsCaptured = sut.buckets.values.first.values; + expect(metricsCaptured.length, 1); + expect(metricsCaptured.first, isA()); + expect(metricsCaptured.first.type, MetricType.counter); + expect(metricsCaptured.first.key, key); + expect((metricsCaptured.first as CounterMetric).value, value); + expect(metricsCaptured.first.unit, unit); + expect(metricsCaptured.first.tags, tags); + }); + + test('gauge', () async { + final MetricsAggregator sut = fixture.getSut(); + sut.testEmit(type: MetricType.gauge); + + final metricsCaptured = sut.buckets.values.first.values; + expect(metricsCaptured.first, isA()); + expect(metricsCaptured.first.type, MetricType.gauge); + }); + + test('distribution', () async { + final MetricsAggregator sut = fixture.getSut(); + sut.testEmit(type: MetricType.distribution); + + final metricsCaptured = sut.buckets.values.first.values; + expect(metricsCaptured.first, isA()); + expect(metricsCaptured.first.type, MetricType.distribution); + }); + + test('set', () async { + final MetricsAggregator sut = fixture.getSut(); + sut.testEmit(type: MetricType.set); + + final metricsCaptured = sut.buckets.values.first.values; + expect(metricsCaptured.first, isA()); + expect(metricsCaptured.first.type, MetricType.set); + }); + }); + + group('span local aggregation', () { + late Fixture fixture; + + setUp(() { + fixture = Fixture(); + }); + + test('emit calls add', () async { + final MetricsAggregator sut = fixture.getSut(hub: fixture.hub); + final t = fixture.hub.startTransaction('test', 'op', bindToScope: true); + + var spanSummary = t.localMetricsAggregator?.getSummaries().values; + expect(spanSummary, isEmpty); + + sut.testEmit(); + + spanSummary = t.localMetricsAggregator?.getSummaries().values; + expect(spanSummary, isNotEmpty); + }); + + test('emit counter', () async { + final MetricsAggregator sut = fixture.getSut(hub: fixture.hub); + final t = fixture.hub.startTransaction('test', 'op', bindToScope: true); + + sut.testEmit(type: MetricType.counter, value: 1); + sut.testEmit(type: MetricType.counter, value: 4); + + final spanSummary = t.localMetricsAggregator?.getSummaries().values.first; + expect(spanSummary!.length, 1); + expect(spanSummary.first.sum, 5); + expect(spanSummary.first.min, 1); + expect(spanSummary.first.max, 4); + expect(spanSummary.first.count, 2); + expect(spanSummary.first.tags, mockTags); + }); + + test('emit distribution', () async { + final MetricsAggregator sut = fixture.getSut(hub: fixture.hub); + final t = fixture.hub.startTransaction('test', 'op', bindToScope: true); + + sut.testEmit(type: MetricType.distribution, value: 1); + sut.testEmit(type: MetricType.distribution, value: 4); + + final spanSummary = t.localMetricsAggregator?.getSummaries().values.first; + expect(spanSummary!.length, 1); + expect(spanSummary.first.sum, 5); + expect(spanSummary.first.min, 1); + expect(spanSummary.first.max, 4); + expect(spanSummary.first.count, 2); + expect(spanSummary.first.tags, mockTags); + }); + + test('emit gauge', () async { + final MetricsAggregator sut = fixture.getSut(hub: fixture.hub); + final t = fixture.hub.startTransaction('test', 'op', bindToScope: true); + + sut.testEmit(type: MetricType.gauge, value: 1); + sut.testEmit(type: MetricType.gauge, value: 4); + + final spanSummary = t.localMetricsAggregator?.getSummaries().values.first; + expect(spanSummary!.length, 1); + expect(spanSummary.first.sum, 5); + expect(spanSummary.first.min, 1); + expect(spanSummary.first.max, 4); + expect(spanSummary.first.count, 2); + expect(spanSummary.first.tags, mockTags); + }); + + test('emit set', () async { + final MetricsAggregator sut = fixture.getSut(hub: fixture.hub); + final t = fixture.hub.startTransaction('test', 'op', bindToScope: true); + + sut.testEmit(type: MetricType.set, value: 1); + sut.testEmit(type: MetricType.set, value: 4); + + final spanSummary = t.localMetricsAggregator?.getSummaries().values.first; + expect(spanSummary!.length, 1); + expect(spanSummary.first.sum, 2); + expect(spanSummary.first.min, 1); + expect(spanSummary.first.max, 1); + expect(spanSummary.first.count, 2); + expect(spanSummary.first.tags, mockTags); + }); + }); + + group('emit in same time bucket', () { + late Fixture fixture; + + setUp(() { + fixture = Fixture(); + }); + + test('same metric with different keys emit different metrics', () async { + final MetricsAggregator sut = fixture.getSut(); + sut.testEmit(key: mockKey); + sut.testEmit(key: mockKey2); + + final timeBuckets = sut.buckets; + final bucket = timeBuckets.values.first; + + expect(bucket.length, 2); + expect(bucket.values.firstWhere((e) => e.key == mockKey), isNotNull); + expect(bucket.values.firstWhere((e) => e.key == mockKey2), isNotNull); + }); + + test('same metric with different units emit different metrics', () async { + final MetricsAggregator sut = fixture.getSut(); + sut.testEmit(unit: mockUnit); + sut.testEmit(unit: mockUnit2); + + final timeBuckets = sut.buckets; + final bucket = timeBuckets.values.first; + + expect(bucket.length, 2); + expect(bucket.values.firstWhere((e) => e.unit == mockUnit), isNotNull); + expect(bucket.values.firstWhere((e) => e.unit == mockUnit2), isNotNull); + }); + + test('same metric with different tags emit different metrics', () async { + final MetricsAggregator sut = fixture.getSut(); + sut.testEmit(tags: mockTags); + sut.testEmit(tags: mockTags2); + + final timeBuckets = sut.buckets; + final bucket = timeBuckets.values.first; + + expect(bucket.length, 2); + expect(bucket.values.firstWhere((e) => e.tags == mockTags), isNotNull); + expect(bucket.values.firstWhere((e) => e.tags == mockTags2), isNotNull); + }); + + test('increment same metric emit only one counter', () async { + final MetricsAggregator sut = fixture.getSut(); + sut.testEmit(type: MetricType.counter, value: 1); + sut.testEmit(type: MetricType.counter, value: 2); + + final timeBuckets = sut.buckets; + final bucket = timeBuckets.values.first; + + expect(bucket.length, 1); + expect((bucket.values.first as CounterMetric).value, 3); + }); + }); + + group('time buckets', () { + late Fixture fixture; + + setUp(() { + fixture = Fixture(); + }); + + test('same metric in < 10 seconds interval emit only one metric', () async { + final MetricsAggregator sut = fixture.getSut(); + fixture.options.clock = () => DateTime.fromMillisecondsSinceEpoch(0); + sut.testEmit(); + fixture.options.clock = () => DateTime.fromMillisecondsSinceEpoch(9999); + sut.testEmit(); + + final timeBuckets = sut.buckets; + expect(timeBuckets.length, 1); + }); + + test('same metric in >= 10 seconds interval emit two metrics', () async { + final MetricsAggregator sut = fixture.getSut(); + fixture.options.clock = () => DateTime.fromMillisecondsSinceEpoch(0); + sut.testEmit(); + fixture.options.clock = () => DateTime.fromMillisecondsSinceEpoch(10000); + sut.testEmit(); + fixture.options.clock = () => DateTime.fromMillisecondsSinceEpoch(20000); + sut.testEmit(); + + final timeBuckets = sut.buckets; + expect(timeBuckets.length, 3); + }); + }); + + group('flush metrics', () { + late Fixture fixture; + + setUp(() { + fixture = Fixture(); + }); + + test('emitting a metric schedules flushing', () async { + final MetricsAggregator sut = fixture.getSut(); + + expect(sut.flushCompleter, isNull); + sut.testEmit(); + expect(sut.flushCompleter, isNotNull); + }); + + test('flush calls hub captureMetrics', () async { + final MetricsAggregator sut = fixture.getSut(); + + // emit a metric + fixture.options.clock = () => DateTime.fromMillisecondsSinceEpoch(0); + sut.testEmit(); + expect(fixture.mockHub.captureMetricsCalls, isEmpty); + + // mock clock to allow metric time aggregation + fixture.options.clock = () => DateTime.fromMillisecondsSinceEpoch(10000); + // wait for flush + await sut.flushCompleter!.future; + expect(fixture.mockHub.captureMetricsCalls, isNotEmpty); + + Map> capturedMetrics = + fixture.mockHub.captureMetricsCalls.first.metricsBuckets; + Metric capturedMetric = capturedMetrics.values.first.first; + expect(capturedMetric.key, mockKey); + }); + + test('flush don\'t schedules flushing if no other metrics', () async { + final MetricsAggregator sut = fixture.getSut(); + + fixture.options.clock = () => DateTime.fromMillisecondsSinceEpoch(0); + sut.testEmit(); + fixture.options.clock = () => DateTime.fromMillisecondsSinceEpoch(10000); + expect(sut.flushCompleter, isNotNull); + await sut.flushCompleter!.future; + expect(sut.flushCompleter, isNull); + }); + + test('flush schedules flushing if there are other metrics', () async { + final MetricsAggregator sut = fixture.getSut(); + + fixture.options.clock = () => DateTime.fromMillisecondsSinceEpoch(0); + sut.testEmit(); + fixture.options.clock = () => DateTime.fromMillisecondsSinceEpoch(10000); + sut.testEmit(); + expect(sut.flushCompleter, isNotNull); + await sut.flushCompleter!.future; + // we expect the aggregator flushed metrics and schedules flushing again + expect(fixture.mockHub.captureMetricsCalls, isNotEmpty); + expect(sut.flushCompleter, isNotNull); + }); + + test('flush schedules flushing if no metric was captured', () async { + final MetricsAggregator sut = + fixture.getSut(flushInterval: Duration(milliseconds: 100)); + + fixture.options.clock = () => DateTime.fromMillisecondsSinceEpoch(10000); + sut.testEmit(); + fixture.options.clock = () => DateTime.fromMillisecondsSinceEpoch(10050); + + expect(sut.flushCompleter, isNotNull); + await sut.flushCompleter!.future; + // we expect the aggregator didn't flush anything and schedules flushing + expect(fixture.mockHub.captureMetricsCalls, isEmpty); + expect(sut.flushCompleter, isNotNull); + }); + + test('flush ignores last 10 seconds', () async { + final MetricsAggregator sut = fixture.getSut(); + + fixture.options.clock = () => DateTime.fromMillisecondsSinceEpoch(10000); + sut.testEmit(); + + // The 10 second bucket is not finished, so it shouldn't capture anything + fixture.options.clock = () => DateTime.fromMillisecondsSinceEpoch(19999); + await sut.flushCompleter!.future; + expect(fixture.mockHub.captureMetricsCalls, isEmpty); + + // The 10 second bucket finished, so it should capture metrics + fixture.options.clock = () => DateTime.fromMillisecondsSinceEpoch(20000); + await sut.flushCompleter!.future; + expect(fixture.mockHub.captureMetricsCalls, isNotEmpty); + }); + + test('flush ignores last flushShiftMs milliseconds', () async { + final MetricsAggregator sut = fixture.getSut(flushShiftMs: 4000); + + fixture.options.clock = () => DateTime.fromMillisecondsSinceEpoch(10000); + sut.testEmit(); + + // The 10 second bucket is not finished, so it shouldn't capture anything + fixture.options.clock = () => DateTime.fromMillisecondsSinceEpoch(19999); + await sut.flushCompleter!.future; + expect(fixture.mockHub.captureMetricsCalls, isEmpty); + + // The 10 second bucket finished, but flushShiftMs didn't pass, so it shouldn't capture anything + fixture.options.clock = () => DateTime.fromMillisecondsSinceEpoch(23999); + await sut.flushCompleter!.future; + expect(fixture.mockHub.captureMetricsCalls, isEmpty); + + // The 10 second bucket finished and flushShiftMs passed, so it should capture metrics + fixture.options.clock = () => DateTime.fromMillisecondsSinceEpoch(24000); + await sut.flushCompleter!.future; + expect(fixture.mockHub.captureMetricsCalls, isNotEmpty); + }); + + test('close flushes everything', () async { + final MetricsAggregator sut = fixture.getSut(); + sut.testEmit(); + sut.testEmit(type: MetricType.gauge); + // We have some metrics, but we don't flush them, yet + await sut.flushCompleter!.future; + expect(fixture.mockHub.captureMetricsCalls, isEmpty); + + // Closing the aggregator. Flush everything + sut.close(); + expect(fixture.mockHub.captureMetricsCalls, isNotEmpty); + expect(sut.buckets, isEmpty); + }); + }); + + group('beforeMetric', () { + late Fixture fixture; + + setUp(() { + fixture = Fixture(); + }); + + test('emits if not set', () async { + final MetricsAggregator sut = fixture.getSut(maxWeight: 4); + sut.testEmit(key: 'key1'); + final metricsCaptured = sut.buckets.values.first.values; + expect(metricsCaptured.length, 1); + expect(metricsCaptured.first.key, 'key1'); + }); + + test('drops if it return false', () async { + final MetricsAggregator sut = fixture.getSut(maxWeight: 4); + fixture.options.beforeMetricCallback = (key, {tags}) => key != 'key2'; + sut.testEmit(key: 'key1'); + sut.testEmit(key: 'key2'); + final metricsCaptured = sut.buckets.values.first.values; + expect(metricsCaptured.length, 1); + expect(metricsCaptured.first.key, 'key1'); + }); + + test('emits if it return true', () async { + final MetricsAggregator sut = fixture.getSut(maxWeight: 4); + fixture.options.beforeMetricCallback = (key, {tags}) => true; + sut.testEmit(key: 'key1'); + sut.testEmit(key: 'key2'); + final metricsCaptured = sut.buckets.values.first.values; + expect(metricsCaptured.length, 2); + expect(metricsCaptured.first.key, 'key1'); + expect(metricsCaptured.last.key, 'key2'); + }); + + test('emits if it throws', () async { + final MetricsAggregator sut = fixture.getSut(maxWeight: 4); + fixture.options.beforeMetricCallback = (key, {tags}) => throw Exception(); + sut.testEmit(key: 'key1'); + sut.testEmit(key: 'key2'); + final metricsCaptured = sut.buckets.values.first.values; + expect(metricsCaptured.length, 2); + expect(metricsCaptured.first.key, 'key1'); + expect(metricsCaptured.last.key, 'key2'); + }); + }); + + group('overweight', () { + late Fixture fixture; + + setUp(() { + fixture = Fixture(); + }); + + test('flush if exceeds maxWeight', () async { + final MetricsAggregator sut = fixture.getSut(maxWeight: 4); + sut.testEmit(type: MetricType.counter, key: 'key1'); + sut.testEmit(type: MetricType.counter, key: 'key2'); + sut.testEmit(type: MetricType.counter, key: 'key3'); + await sut.flushCompleter!.future; + expect(fixture.mockHub.captureMetricsCalls, isEmpty); + // After the 4th metric is emitted, the aggregator flushes immediately + sut.testEmit(type: MetricType.counter, key: 'key4'); + expect(fixture.mockHub.captureMetricsCalls, isNotEmpty); + }); + + test('does not flush if not exceeds maxWeight', () async { + final MetricsAggregator sut = fixture.getSut(maxWeight: 2); + // We are emitting the same metric, so no weight is added + sut.testEmit(type: MetricType.counter); + sut.testEmit(type: MetricType.counter); + sut.testEmit(type: MetricType.counter); + sut.testEmit(type: MetricType.counter); + await sut.flushCompleter!.future; + expect(fixture.mockHub.captureMetricsCalls, isEmpty); + }); + }); +} + +const String mockKey = 'metric key'; +const String mockKey2 = 'metric key 2'; +const double mockValue = 5; +const SentryMeasurementUnit mockUnit = DurationSentryMeasurementUnit.minute; +const SentryMeasurementUnit mockUnit2 = DurationSentryMeasurementUnit.second; +const Map mockTags = {'tag1': 'val1', 'tag2': 'val2'}; +const Map mockTags2 = {'tag1': 'val1'}; +final DateTime mockTimestamp = DateTime.fromMillisecondsSinceEpoch(1); + +class Fixture { + final options = SentryOptions(dsn: fakeDsn); + final mockHub = MockHub(); + late final hub = Hub(options); + + Fixture() { + options.tracesSampleRate = 1; + options.enableMetrics = true; + options.enableSpanLocalMetricAggregation = true; + } + + MetricsAggregator getSut({ + Hub? hub, + Duration flushInterval = const Duration(milliseconds: 1), + int flushShiftMs = 0, + int maxWeight = 100000, + }) { + return MetricsAggregator( + hub: hub ?? mockHub, + options: options, + flushInterval: flushInterval, + flushShiftMs: flushShiftMs, + maxWeight: maxWeight); + } +} + +extension _MetricsAggregatorUtils on MetricsAggregator { + testEmit({ + MetricType type = MetricType.counter, + String key = mockKey, + double value = mockValue, + SentryMeasurementUnit unit = mockUnit, + Map tags = mockTags, + }) { + emit(type, key, value, unit, tags); + } +} diff --git a/dart/test/metrics/metrics_api_test.dart b/dart/test/metrics/metrics_api_test.dart new file mode 100644 index 0000000000..9345720102 --- /dev/null +++ b/dart/test/metrics/metrics_api_test.dart @@ -0,0 +1,150 @@ +import 'dart:async'; + +import 'package:sentry/sentry.dart'; +import 'package:sentry/src/metrics/metric.dart'; +import 'package:sentry/src/metrics/metrics_api.dart'; +import 'package:sentry/src/sentry_tracer.dart'; +import 'package:test/test.dart'; + +import '../mocks.dart'; +import '../mocks/mock_hub.dart'; + +void main() { + group('api', () { + late Fixture fixture; + + setUp(() { + fixture = Fixture(); + }); + + test('counter', () async { + MetricsApi api = fixture.getSut(); + api.increment('key'); + api.increment('key', value: 2.4); + + Iterable sentMetrics = + fixture.mockHub.metricsAggregator!.buckets.values.first.values; + expect(sentMetrics.first.type, MetricType.counter); + expect((sentMetrics.first as CounterMetric).value, 3.4); + }); + + test('gauge', () async { + MetricsApi api = fixture.getSut(); + api.gauge('key', value: 1.5); + api.gauge('key', value: 2.4); + + Iterable sentMetrics = + fixture.mockHub.metricsAggregator!.buckets.values.first.values; + expect(sentMetrics.first.type, MetricType.gauge); + expect((sentMetrics.first as GaugeMetric).minimum, 1.5); + expect((sentMetrics.first as GaugeMetric).maximum, 2.4); + expect((sentMetrics.first as GaugeMetric).last, 2.4); + expect((sentMetrics.first as GaugeMetric).sum, 3.9); + expect((sentMetrics.first as GaugeMetric).count, 2); + }); + + test('distribution', () async { + MetricsApi api = fixture.getSut(); + api.distribution('key', value: 1.5); + api.distribution('key', value: 2.4); + + Iterable sentMetrics = + fixture.mockHub.metricsAggregator!.buckets.values.first.values; + expect(sentMetrics.first.type, MetricType.distribution); + expect((sentMetrics.first as DistributionMetric).values, [1.5, 2.4]); + }); + + test('set', () async { + MetricsApi api = fixture.getSut(); + api.set('key', value: 1); + api.set('key', value: 2); + // This is ignored as it's a repeated value + api.set('key', value: 2); + // This adds both an int and a crc32 of the string to the metric + api.set('key', value: 4, stringValue: 'value'); + // No value provided. This does nothing + api.set('key'); + // Empty String provided. This does nothing + api.set('key', stringValue: ''); + + Iterable sentMetrics = + fixture.mockHub.metricsAggregator!.buckets.values.first.values; + expect(sentMetrics.first.type, MetricType.set); + expect((sentMetrics.first as SetMetric).values, {1, 2, 4, 494360628}); + }); + + test('timing emits distribution', () async { + final delay = Duration(milliseconds: 100); + final completer = Completer(); + MetricsApi api = fixture.getSut(); + + // The timing API tries to start a child span + expect(fixture.mockHub.getSpanCalls, 0); + api.timing('key', + function: () => Future.delayed(delay, () => completer.complete())); + expect(fixture.mockHub.getSpanCalls, 1); + + await completer.future; + Iterable sentMetrics = + fixture.mockHub.metricsAggregator!.buckets.values.first.values; + + // The timing API emits a distribution metric + expect(sentMetrics.first.type, MetricType.distribution); + // The default unit is second + expect(sentMetrics.first.unit, DurationSentryMeasurementUnit.second); + // It awaits for the function completion, which means 100 milliseconds in + // this case. Since the unit is second, its value (duration) is >= 0.1 + expect( + (sentMetrics.first as DistributionMetric).values.first >= 0.1, true); + }); + + test('timing starts a span', () async { + final delay = Duration(milliseconds: 100); + final completer = Completer(); + fixture._options.tracesSampleRate = 1; + fixture._options.enableMetrics = true; + MetricsApi api = fixture.getSut(hub: fixture.hub); + + // Start a transaction so that timing api can start a child span + final transaction = fixture.hub.startTransaction( + 'name', + 'operation', + bindToScope: true, + ) as SentryTracer; + expect(transaction.children, isEmpty); + + // Timing starts a span + api.timing('my key', + unit: DurationSentryMeasurementUnit.milliSecond, + function: () => Future.delayed(delay, () => completer.complete())); + final span = transaction.children.first; + expect(span.finished, false); + expect(span.context.operation, 'metric.timing'); + expect(span.context.description, 'my key'); + + // Timing finishes the span when the function is finished, which takes 100 milliseconds + await completer.future; + expect(span.finished, true); + final spanDuration = span.endTimestamp!.difference(span.startTimestamp); + expect(spanDuration.inMilliseconds >= 100, true); + await Future.delayed(Duration()); + + Iterable sentMetrics = + fixture.hub.metricsAggregator!.buckets.values.first.values; + + // The emitted metric value should match the span duration + expect(sentMetrics.first.unit, DurationSentryMeasurementUnit.milliSecond); + // Duration.inMilliseconds returns an int, so we have to assert it + expect((sentMetrics.first as DistributionMetric).values.first.toInt(), + spanDuration.inMilliseconds); + }); + }); +} + +class Fixture { + final _options = SentryOptions(dsn: fakeDsn); + final mockHub = MockHub(); + late final hub = Hub(_options); + + MetricsApi getSut({Hub? hub}) => MetricsApi(hub: hub ?? mockHub); +} diff --git a/dart/test/mocks.dart b/dart/test/mocks.dart index b5fdd59aa9..1c79599a6b 100644 --- a/dart/test/mocks.dart +++ b/dart/test/mocks.dart @@ -1,5 +1,6 @@ import 'package:mockito/annotations.dart'; import 'package:sentry/sentry.dart'; +import 'package:sentry/src/metrics/metric.dart'; import 'package:sentry/src/profiling.dart'; import 'package:sentry/src/transport/rate_limiter.dart'; @@ -97,6 +98,37 @@ final fakeEvent = SentryEvent( ), ); +final fakeMetric = Metric.fromType( + type: MetricType.counter, + value: 4, + key: 'key', + unit: DurationSentryMeasurementUnit.hour, + tags: {'tag1': 'value1', 'tag2': 'value2'}); +final fakeMetric2 = Metric.fromType( + type: MetricType.counter, + value: 2, + key: 'key', + unit: SentryMeasurementUnit.none, + tags: {'tag1': 'value1', 'tag2': 'value2'}); +final fakeMetric3 = Metric.fromType( + type: MetricType.counter, + value: 2, + key: 'key', + unit: SentryMeasurementUnit.none, + tags: {'tag1': 'value1'}); +final fakeMetric4 = Metric.fromType( + type: MetricType.counter, + value: 2, + key: 'key2', + unit: SentryMeasurementUnit.none, + tags: {'tag1': 'value1'}); + +final Map> fakeMetrics = { + 10: [fakeMetric], + 20: [fakeMetric, fakeMetric2], + 30: [fakeMetric, fakeMetric3, fakeMetric4], +}; + /// Always returns null and thus drops all events class DropAllEventProcessor implements EventProcessor { @override diff --git a/dart/test/mocks/mock_hub.dart b/dart/test/mocks/mock_hub.dart index 351ad70672..c076251736 100644 --- a/dart/test/mocks/mock_hub.dart +++ b/dart/test/mocks/mock_hub.dart @@ -1,5 +1,7 @@ import 'package:meta/meta.dart'; import 'package:sentry/sentry.dart'; +import 'package:sentry/src/metrics/metric.dart'; +import 'package:sentry/src/metrics/metrics_aggregator.dart'; import '../mocks.dart'; import 'mock_sentry_client.dart'; @@ -13,17 +15,23 @@ class MockHub with NoSuchMethodProvider implements Hub { List bindClientCalls = []; List userFeedbackCalls = []; List captureTransactionCalls = []; + List captureMetricsCalls = []; int closeCalls = 0; bool _isEnabled = true; int spanContextCals = 0; int getSpanCalls = 0; final _options = SentryOptions(dsn: fakeDsn); + late final MetricsAggregator _metricsAggregator = + MetricsAggregator(options: _options, hub: this); @override @internal SentryOptions get options => _options; + @override + MetricsAggregator? get metricsAggregator => _metricsAggregator; + /// Useful for tests. void reset() { captureEventCalls = []; @@ -35,6 +43,7 @@ class MockHub with NoSuchMethodProvider implements Hub { _isEnabled = true; spanContextCals = 0; captureTransactionCalls = []; + captureMetricsCalls = []; getSpanCalls = 0; } @@ -116,6 +125,13 @@ class MockHub with NoSuchMethodProvider implements Hub { return transaction.eventId; } + @override + Future captureMetrics( + Map> metricsBuckets) async { + captureMetricsCalls.add(CaptureMetricsCall(metricsBuckets)); + return SentryId.newId(); + } + @override Future captureUserFeedback(SentryUserFeedback userFeedback) async { userFeedbackCalls.add(userFeedback); diff --git a/dart/test/mocks/mock_sentry_client.dart b/dart/test/mocks/mock_sentry_client.dart index 7b08250193..248ea19032 100644 --- a/dart/test/mocks/mock_sentry_client.dart +++ b/dart/test/mocks/mock_sentry_client.dart @@ -1,4 +1,5 @@ import 'package:sentry/sentry.dart'; +import 'package:sentry/src/metrics/metric.dart'; import 'no_such_method_provider.dart'; @@ -9,6 +10,7 @@ class MockSentryClient with NoSuchMethodProvider implements SentryClient { List captureEnvelopeCalls = []; List captureTransactionCalls = []; List userFeedbackCalls = []; + List>> captureMetricsCalls = []; int closeCalls = 0; @override @@ -74,6 +76,12 @@ class MockSentryClient with NoSuchMethodProvider implements SentryClient { userFeedbackCalls.add(userFeedback); } + @override + Future captureMetrics(Map> metrics) async { + captureMetricsCalls.add(metrics); + return SentryId.newId(); + } + @override void close() { closeCalls = closeCalls + 1; @@ -149,3 +157,9 @@ class CaptureTransactionCall { CaptureTransactionCall(this.transaction, this.traceContext); } + +class CaptureMetricsCall { + final Map> metricsBuckets; + + CaptureMetricsCall(this.metricsBuckets); +} diff --git a/dart/test/mocks/mock_transport.dart b/dart/test/mocks/mock_transport.dart index 0ce6c9d896..fad9f43696 100644 --- a/dart/test/mocks/mock_transport.dart +++ b/dart/test/mocks/mock_transport.dart @@ -6,6 +6,7 @@ import 'package:test/expect.dart'; class MockTransport implements Transport { List envelopes = []; List events = []; + List statsdItems = []; int _calls = 0; String _exceptions = ''; @@ -27,8 +28,7 @@ class MockTransport implements Transport { // failure causes. Instead, we log them and check on access to [calls]. try { envelopes.add(envelope); - final event = await _eventFromEnvelope(envelope); - events.add(event); + await _eventFromEnvelope(envelope); } catch (e, stack) { _exceptions += '$e\n$stack\n\n'; rethrow; @@ -37,13 +37,18 @@ class MockTransport implements Transport { return envelope.header.eventId ?? SentryId.empty(); } - Future _eventFromEnvelope(SentryEnvelope envelope) async { + Future _eventFromEnvelope(SentryEnvelope envelope) async { final envelopeItemData = []; + final RegExp statSdRegex = RegExp('^(?!{).+@.+:.+\\|.+', multiLine: true); envelopeItemData.addAll(await envelope.items.first.envelopeItemStream()); final envelopeItem = utf8.decode(envelopeItemData).split('\n').last; - final envelopeItemJson = jsonDecode(envelopeItem) as Map; - return SentryEvent.fromJson(envelopeItemJson); + if (statSdRegex.hasMatch(envelopeItem)) { + statsdItems.add(envelopeItem); + } else { + final envelopeItemJson = jsonDecode(envelopeItem) as Map; + events.add(SentryEvent.fromJson(envelopeItemJson)); + } } void reset() { diff --git a/dart/test/protocol/rate_limit_parser_test.dart b/dart/test/protocol/rate_limit_parser_test.dart index c898915e04..567dec34f0 100644 --- a/dart/test/protocol/rate_limit_parser_test.dart +++ b/dart/test/protocol/rate_limit_parser_test.dart @@ -75,6 +75,45 @@ void main() { expect(sut[0].duration.inMilliseconds, RateLimitParser.httpRetryAfterDefaultDelay.inMilliseconds); }); + + test('do not parse namespaces if not metric_bucket', () { + final sut = + RateLimitParser('1:transaction:organization:quota_exceeded:custom') + .parseRateLimitHeader(); + + expect(sut.length, 1); + expect(sut[0].category, DataCategory.transaction); + expect(sut[0].namespaces, isEmpty); + }); + + test('parse namespaces on metric_bucket', () { + final sut = + RateLimitParser('1:metric_bucket:organization:quota_exceeded:custom') + .parseRateLimitHeader(); + + expect(sut.length, 1); + expect(sut[0].category, DataCategory.metricBucket); + expect(sut[0].namespaces, isNotEmpty); + expect(sut[0].namespaces.first, 'custom'); + }); + + test('parse empty namespaces on metric_bucket', () { + final sut = + RateLimitParser('1:metric_bucket:organization:quota_exceeded:') + .parseRateLimitHeader(); + + expect(sut.length, 1); + expect(sut[0].category, DataCategory.metricBucket); + expect(sut[0].namespaces, isEmpty); + }); + + test('parse missing namespaces on metric_bucket', () { + final sut = RateLimitParser('1:metric_bucket').parseRateLimitHeader(); + + expect(sut.length, 1); + expect(sut[0].category, DataCategory.metricBucket); + expect(sut[0].namespaces, isEmpty); + }); }); group('parseRetryAfterHeader', () { diff --git a/dart/test/protocol/rate_limiter_test.dart b/dart/test/protocol/rate_limiter_test.dart index cc931d5b66..1f52a60003 100644 --- a/dart/test/protocol/rate_limiter_test.dart +++ b/dart/test/protocol/rate_limiter_test.dart @@ -228,6 +228,118 @@ void main() { expect(fixture.mockRecorder.category, DataCategory.transaction); expect(fixture.mockRecorder.reason, DiscardReason.rateLimitBackoff); }); + + test('dropping of metrics recorded', () { + final rateLimiter = fixture.getSut(); + + final metricsItem = SentryEnvelopeItem.fromMetrics({}); + final eventEnvelope = SentryEnvelope( + SentryEnvelopeHeader.newEventId(), + [metricsItem], + ); + + rateLimiter.updateRetryAfterLimits( + '1:metric_bucket:key, 5:metric_bucket:organization', null, 1); + + final result = rateLimiter.filter(eventEnvelope); + expect(result, isNull); + + expect(fixture.mockRecorder.category, DataCategory.metricBucket); + expect(fixture.mockRecorder.reason, DiscardReason.rateLimitBackoff); + }); + + group('apply rateLimit', () { + test('error', () { + final rateLimiter = fixture.getSut(); + fixture.dateTimeToReturn = 0; + + final eventItem = SentryEnvelopeItem.fromEvent(SentryEvent()); + final envelope = SentryEnvelope( + SentryEnvelopeHeader.newEventId(), + [eventItem], + ); + + rateLimiter.updateRetryAfterLimits( + '1:error:key, 5:error:organization', null, 1); + + expect(rateLimiter.filter(envelope), isNull); + }); + + test('transaction', () { + final rateLimiter = fixture.getSut(); + fixture.dateTimeToReturn = 0; + + final transaction = fixture.getTransaction(); + final eventItem = SentryEnvelopeItem.fromTransaction(transaction); + final envelope = SentryEnvelope( + SentryEnvelopeHeader.newEventId(), + [eventItem], + ); + + rateLimiter.updateRetryAfterLimits( + '1:transaction:key, 5:transaction:organization', null, 1); + + final result = rateLimiter.filter(envelope); + expect(result, isNull); + }); + + test('metrics', () { + final rateLimiter = fixture.getSut(); + fixture.dateTimeToReturn = 0; + + final metricsItem = SentryEnvelopeItem.fromMetrics({}); + final envelope = SentryEnvelope( + SentryEnvelopeHeader.newEventId(), + [metricsItem], + ); + + rateLimiter.updateRetryAfterLimits( + '1:metric_bucket:key, 5:metric_bucket:organization', null, 1); + + final result = rateLimiter.filter(envelope); + expect(result, isNull); + }); + + test('metrics with empty namespaces', () { + final rateLimiter = fixture.getSut(); + fixture.dateTimeToReturn = 0; + + final eventItem = SentryEnvelopeItem.fromEvent(SentryEvent()); + final metricsItem = SentryEnvelopeItem.fromMetrics({}); + final envelope = SentryEnvelope( + SentryEnvelopeHeader.newEventId(), + [eventItem, metricsItem], + ); + + rateLimiter.updateRetryAfterLimits( + '10:metric_bucket:key:quota_exceeded:', null, 1); + + final result = rateLimiter.filter(envelope); + expect(result, isNotNull); + expect(result!.items.length, 1); + expect(result.items.first.header.type, 'event'); + }); + + test('metrics with custom namespace', () { + final rateLimiter = fixture.getSut(); + fixture.dateTimeToReturn = 0; + + final eventItem = SentryEnvelopeItem.fromEvent(SentryEvent()); + final metricsItem = SentryEnvelopeItem.fromMetrics({}); + final envelope = SentryEnvelope( + SentryEnvelopeHeader.newEventId(), + [eventItem, metricsItem], + ); + + rateLimiter.updateRetryAfterLimits( + '10:metric_bucket:key:quota_exceeded:custom', null, 1); + + final result = rateLimiter.filter(envelope); + expect(result, isNotNull); + expect(result!.items.length, 1); + expect(result.items.first.header.type, 'event'); + }); + }); } class Fixture { diff --git a/dart/test/sentry_client_test.dart b/dart/test/sentry_client_test.dart index 63c83a321f..ca7718ba32 100644 --- a/dart/test/sentry_client_test.dart +++ b/dart/test/sentry_client_test.dart @@ -8,6 +8,7 @@ import 'package:sentry/src/client_reports/client_report.dart'; import 'package:sentry/src/client_reports/discard_reason.dart'; import 'package:sentry/src/client_reports/discarded_event.dart'; import 'package:sentry/src/client_reports/noop_client_report_recorder.dart'; +import 'package:sentry/src/metrics/metric.dart'; import 'package:sentry/src/sentry_item_type.dart'; import 'package:sentry/src/sentry_stack_trace_factory.dart'; import 'package:sentry/src/sentry_tracer.dart'; @@ -405,6 +406,8 @@ void main() { Error error; + dynamic exception; + final stacktrace = ''' #0 baz (file:///pathto/test.dart:50:3) @@ -436,16 +439,6 @@ void main() { capturedEvent.exceptions?.first.stackTrace!.frames.first.lineNo, 46); expect(capturedEvent.exceptions?.first.stackTrace!.frames.first.colNo, 9); }); - }); - - group('SentryClient captures exception and stacktrace', () { - late Fixture fixture; - - dynamic exception; - - setUp(() { - fixture = Fixture(); - }); test('should capture exception', () async { try { @@ -454,12 +447,6 @@ void main() { exception = err; } - final stacktrace = ''' -#0 baz (file:///pathto/test.dart:50:3) - -#1 bar (file:///pathto/test.dart:46:9) - '''; - final client = fixture.getSut(); await client.captureException(exception, stackTrace: stacktrace); @@ -513,13 +500,6 @@ void main() { exception = err; } - final stacktrace = ''' -#0 init (package:sentry/sentry.dart:46:9) -#1 bar (file:///pathto/test.dart:46:9) - -#2 capture (package:sentry/sentry.dart:46:9) - '''; - final client = fixture.getSut(); await client.captureException(exception, stackTrace: stacktrace); @@ -1716,6 +1696,42 @@ void main() { expect(fixture.options.transport is SpotlightHttpTransport, true); }); }); + + group('Capture metrics', () { + late Fixture fixture; + + setUp(() { + fixture = Fixture(); + }); + + test('metricsAggregator is set if metrics are enabled', () async { + final client = fixture.getSut(enableMetrics: true); + expect(client.metricsAggregator, isNotNull); + }); + + test('metricsAggregator is null if metrics are disabled', () async { + final client = fixture.getSut(enableMetrics: false); + expect(client.metricsAggregator, isNull); + }); + + test('captureMetrics send statsd envelope', () async { + final client = fixture.getSut(); + await client.captureMetrics(fakeMetrics); + + final capturedStatsd = (fixture.transport).statsdItems.first; + expect(capturedStatsd, isNotNull); + }); + + test('close closes metricsAggregator', () async { + final client = fixture.getSut(); + client.close(); + expect(client.metricsAggregator, isNotNull); + client.metricsAggregator! + .emit(MetricType.counter, 'key', 1, SentryMeasurementUnit.none, {}); + // metricsAggregator is closed, so no metrics should be recorded + expect(client.metricsAggregator!.buckets, isEmpty); + }); + }); } Future eventFromEnvelope(SentryEnvelope envelope) async { @@ -1802,6 +1818,7 @@ class Fixture { bool sendDefaultPii = false, bool attachStacktrace = true, bool attachThreads = false, + bool enableMetrics = true, double? sampleRate, BeforeSendCallback? beforeSend, BeforeSendTransactionCallback? beforeSendTransaction, @@ -1818,6 +1835,7 @@ class Fixture { options.tracesSampleRate = 1.0; options.sendDefaultPii = sendDefaultPii; + options.enableMetrics = enableMetrics; options.attachStacktrace = attachStacktrace; options.attachThreads = attachThreads; options.sampleRate = sampleRate; diff --git a/dart/test/sentry_envelope_item_test.dart b/dart/test/sentry_envelope_item_test.dart index 673f679740..c5a205c945 100644 --- a/dart/test/sentry_envelope_item_test.dart +++ b/dart/test/sentry_envelope_item_test.dart @@ -4,12 +4,14 @@ import 'package:sentry/sentry.dart'; import 'package:sentry/src/client_reports/client_report.dart'; import 'package:sentry/src/client_reports/discard_reason.dart'; import 'package:sentry/src/client_reports/discarded_event.dart'; +import 'package:sentry/src/metrics/metric.dart'; import 'package:sentry/src/sentry_envelope_item_header.dart'; import 'package:sentry/src/sentry_item_type.dart'; import 'package:sentry/src/sentry_tracer.dart'; import 'package:sentry/src/transport/data_category.dart'; import 'package:test/test.dart'; +import 'mocks.dart'; import 'mocks/mock_hub.dart'; void main() { @@ -109,5 +111,49 @@ void main() { expect(actualLength, expectedLength); expect(actualData, expectedData); }); + + test('fromUserFeedback', () async { + final userFeedback = SentryUserFeedback( + eventId: SentryId.newId(), + name: 'name', + comments: 'comments', + email: 'email'); + final sut = SentryEnvelopeItem.fromUserFeedback(userFeedback); + + final expectedData = utf8.encode(jsonEncode( + userFeedback.toJson(), + toEncodable: jsonSerializationFallback, + )); + final actualData = await sut.dataFactory(); + + final expectedLength = expectedData.length; + final actualLength = await sut.header.length(); + + expect(sut.header.contentType, 'application/json'); + expect(sut.header.type, SentryItemType.userFeedback); + expect(actualLength, expectedLength); + expect(actualData, expectedData); + }); + + test('fromMetrics', () async { + final sut = SentryEnvelopeItem.fromMetrics(fakeMetrics); + + final StringBuffer statsd = StringBuffer(); + for (MapEntry> bucket in fakeMetrics.entries) { + final Iterable encodedMetrics = + bucket.value.map((metric) => metric.encodeToStatsd(bucket.key)); + statsd.write(encodedMetrics.join('\n')); + } + final expectedData = utf8.encode(statsd.toString()); + final actualData = await sut.dataFactory(); + + final expectedLength = expectedData.length; + final actualLength = await sut.header.length(); + + expect(sut.header.contentType, 'application/octet-stream'); + expect(sut.header.type, SentryItemType.statsd); + expect(actualLength, expectedLength); + expect(actualData, expectedData); + }); }); } diff --git a/dart/test/sentry_envelope_test.dart b/dart/test/sentry_envelope_test.dart index 375f62846e..a24cab20c7 100644 --- a/dart/test/sentry_envelope_test.dart +++ b/dart/test/sentry_envelope_test.dart @@ -130,6 +130,63 @@ void main() { expect(actualItem, expectedItem); }); + test('fromUserFeedback', () async { + final eventId = SentryId.newId(); + final userFeedback = SentryUserFeedback( + eventId: eventId, name: 'name', email: 'email', comments: 'comments'); + final sdkVersion = + SdkVersion(name: 'fixture-name', version: 'fixture-version'); + final sut = SentryEnvelope.fromUserFeedback( + userFeedback, + sdkVersion, + dsn: fakeDsn, + ); + + final expectedEnvelopeItem = + SentryEnvelopeItem.fromUserFeedback(userFeedback); + + expect(sut.header.eventId, eventId); + expect(sut.header.sdkVersion, sdkVersion); + expect(sut.header.dsn, fakeDsn); + expect(sut.items[0].header.contentType, + expectedEnvelopeItem.header.contentType); + expect(sut.items[0].header.type, expectedEnvelopeItem.header.type); + expect(await sut.items[0].header.length(), + await expectedEnvelopeItem.header.length()); + + final actualItem = await sut.items[0].envelopeItemStream(); + + final expectedItem = await expectedEnvelopeItem.envelopeItemStream(); + + expect(actualItem, expectedItem); + }); + + test('fromMetrics', () async { + final sdkVersion = + SdkVersion(name: 'fixture-name', version: 'fixture-version'); + final sut = SentryEnvelope.fromMetrics( + fakeMetrics, + sdkVersion, + dsn: fakeDsn, + ); + + final expectedEnvelopeItem = SentryEnvelopeItem.fromMetrics(fakeMetrics); + + expect(sut.header.sdkVersion, sdkVersion); + expect(sut.header.dsn, fakeDsn); + expect(sut.items[0].header.contentType, + expectedEnvelopeItem.header.contentType); + expect(sut.items[0].header.type, expectedEnvelopeItem.header.type); + expect(await sut.items[0].header.length(), + await expectedEnvelopeItem.header.length()); + + final actualItem = await sut.items[0].envelopeItemStream(); + + final expectedItem = await expectedEnvelopeItem.envelopeItemStream(); + + expect(actualItem, expectedItem); + }); + test('max attachment size', () async { final attachment = SentryAttachment.fromLoader( loader: () => Uint8List.fromList([1, 2, 3, 4]), diff --git a/dart/test/sentry_options_test.dart b/dart/test/sentry_options_test.dart index e921c87b32..273366e442 100644 --- a/dart/test/sentry_options_test.dart +++ b/dart/test/sentry_options_test.dart @@ -133,4 +133,55 @@ void main() { expect(options.spotlight.enabled, false); }); + + test('metrics are disabled by default', () { + final options = SentryOptions(dsn: fakeDsn); + + expect(options.enableMetrics, false); + }); + + test('default tags for metrics are enabled by default', () { + final options = SentryOptions(dsn: fakeDsn); + options.enableMetrics = true; + + expect(options.enableDefaultTagsForMetrics, true); + }); + + test('default tags for metrics are disabled if metrics are disabled', () { + final options = SentryOptions(dsn: fakeDsn); + options.enableMetrics = false; + + expect(options.enableDefaultTagsForMetrics, false); + }); + + test('default tags for metrics are enabled if metrics are enabled, too', () { + final options = SentryOptions(dsn: fakeDsn); + options.enableMetrics = true; + options.enableDefaultTagsForMetrics = true; + + expect(options.enableDefaultTagsForMetrics, true); + }); + + test('span local metric aggregation is enabled by default', () { + final options = SentryOptions(dsn: fakeDsn); + options.enableMetrics = true; + + expect(options.enableSpanLocalMetricAggregation, true); + }); + + test('span local metric aggregation is disabled if metrics are disabled', () { + final options = SentryOptions(dsn: fakeDsn); + options.enableMetrics = false; + + expect(options.enableSpanLocalMetricAggregation, false); + }); + + test('span local metric aggregation is enabled if metrics are enabled, too', + () { + final options = SentryOptions(dsn: fakeDsn); + options.enableMetrics = true; + options.enableSpanLocalMetricAggregation = true; + + expect(options.enableSpanLocalMetricAggregation, true); + }); } diff --git a/dart/test/sentry_span_test.dart b/dart/test/sentry_span_test.dart index e878be5cf2..e161ceee2f 100644 --- a/dart/test/sentry_span_test.dart +++ b/dart/test/sentry_span_test.dart @@ -2,6 +2,7 @@ import 'package:sentry/sentry.dart'; import 'package:sentry/src/sentry_tracer.dart'; import 'package:test/test.dart'; +import 'mocks.dart'; import 'mocks/mock_hub.dart'; void main() { @@ -125,11 +126,14 @@ void main() { }); test('span serializes', () async { + fixture.hub.options.enableMetrics = true; + fixture.hub.options.enableSpanLocalMetricAggregation = true; final sut = fixture.getSut(); sut.setTag('test', 'test'); sut.setData('test', 'test'); sut.origin = 'manual'; + sut.localMetricsAggregator?.add(fakeMetric, 0); await sut.finish(status: SpanStatus.aborted()); @@ -141,6 +145,26 @@ void main() { expect(map['tags']['test'], 'test'); expect(map['status'], 'aborted'); expect(map['origin'], 'manual'); + expect(map['_metrics_summary'], isNotNull); + }); + + test('adding a metric after span finish does not serialize', () async { + fixture.hub.options.enableMetrics = true; + fixture.hub.options.enableSpanLocalMetricAggregation = true; + final sut = fixture.getSut(); + await sut.finish(status: SpanStatus.aborted()); + sut.localMetricsAggregator?.add(fakeMetric, 0); + + expect(sut.toJson()['_metrics_summary'], isNull); + }); + + test('adding a metric when option is disabled does not serialize', () async { + fixture.hub.options.enableMetrics = false; + final sut = fixture.getSut(); + sut.localMetricsAggregator?.add(fakeMetric, 0); + await sut.finish(status: SpanStatus.aborted()); + + expect(sut.toJson()['_metrics_summary'], isNull); }); test('finished returns false if not yet', () { @@ -271,6 +295,21 @@ void main() { final sut = fixture.getSut(); expect(sut.origin, 'manual'); }); + + test('localMetricsAggregator is set when option is enabled', () async { + fixture.hub.options.enableMetrics = true; + fixture.hub.options.enableSpanLocalMetricAggregation = true; + final sut = fixture.getSut(); + expect(fixture.hub.options.enableSpanLocalMetricAggregation, true); + expect(sut.localMetricsAggregator, isNotNull); + }); + + test('localMetricsAggregator is null when option is disabled', () async { + fixture.hub.options.enableSpanLocalMetricAggregation = false; + final sut = fixture.getSut(); + expect(fixture.hub.options.enableSpanLocalMetricAggregation, false); + expect(sut.localMetricsAggregator, null); + }); } class Fixture { diff --git a/dart/test/sentry_test.dart b/dart/test/sentry_test.dart index a361c0bc4f..0a8dd5db27 100644 --- a/dart/test/sentry_test.dart +++ b/dart/test/sentry_test.dart @@ -129,6 +129,10 @@ void main() { expect(Sentry.getSpan(), isNull); }); + + test('should provide metrics API', () async { + expect(Sentry.metrics(), Sentry.currentHub.metricsApi); + }); }); group('Sentry is enabled or disabled', () { @@ -412,29 +416,7 @@ void main() { expect(sentryOptions.logger, isNot(dartLogger)); }); - group("Sentry init optionsConfiguration", () { - final fixture = Fixture(); - - test('throw is handled and logged', () async { - final sentryOptions = SentryOptions(dsn: fakeDsn) - ..automatedTestMode = false - ..debug = true - ..logger = fixture.mockLogger; - - final exception = Exception("Exception in options callback"); - await Sentry.init( - (options) async { - throw exception; - }, - options: sentryOptions, - ); - - expect(fixture.loggedException, exception); - expect(fixture.loggedLevel, SentryLevel.error); - }); - }); - - group("Sentry init optionsConfiguration", () { + group('Sentry init optionsConfiguration', () { final fixture = Fixture(); test('throw is handled and logged', () async { diff --git a/dart/test/sentry_tracer_test.dart b/dart/test/sentry_tracer_test.dart index e57cb415ea..77914e66d3 100644 --- a/dart/test/sentry_tracer_test.dart +++ b/dart/test/sentry_tracer_test.dart @@ -468,6 +468,21 @@ void main() { expect(sut.measurements.isEmpty, true); }); + + test('localMetricsAggregator is set when option is enabled', () async { + fixture.hub.options.enableMetrics = true; + fixture.hub.options.enableSpanLocalMetricAggregation = true; + final sut = fixture.getSut(); + expect(fixture.hub.options.enableSpanLocalMetricAggregation, true); + expect(sut.localMetricsAggregator, isNotNull); + }); + + test('localMetricsAggregator is null when option is disabled', () async { + fixture.hub.options.enableMetrics = false; + final sut = fixture.getSut(); + expect(fixture.hub.options.enableSpanLocalMetricAggregation, false); + expect(sut.localMetricsAggregator, null); + }); }); group('$SentryBaggageHeader', () { diff --git a/dart/test/sentry_transaction_test.dart b/dart/test/sentry_transaction_test.dart index fb784abd6d..7de0549a13 100644 --- a/dart/test/sentry_transaction_test.dart +++ b/dart/test/sentry_transaction_test.dart @@ -2,6 +2,7 @@ import 'package:sentry/sentry.dart'; import 'package:sentry/src/sentry_tracer.dart'; import 'package:test/test.dart'; +import 'mocks.dart'; import 'mocks/mock_hub.dart'; void main() { @@ -9,6 +10,7 @@ void main() { SentryTracer _createTracer({ bool? sampled = true, + Hub? hub, }) { final context = SentryTransactionContext( 'name', @@ -16,11 +18,16 @@ void main() { samplingDecision: SentryTracesSamplingDecision(sampled!), transactionNameSource: SentryTransactionNameSource.component, ); - return SentryTracer(context, MockHub()); + return SentryTracer(context, hub ?? MockHub()); } test('toJson serializes', () async { - final tracer = _createTracer(); + fixture.options.enableSpanLocalMetricAggregation = true; + fixture.options.enableMetrics = true; + + final tracer = _createTracer(hub: fixture.hub); + tracer.localMetricsAggregator?.add(fakeMetric, 0); + final child = tracer.startChild('child'); await child.finish(); await tracer.finish(); @@ -32,6 +39,7 @@ void main() { expect(map['start_timestamp'], isNotNull); expect(map['spans'], isNotNull); expect(map['transaction_info']['source'], 'component'); + expect(map['_metrics_summary'], isNotNull); }); test('returns finished if it is', () async { @@ -66,9 +74,43 @@ void main() { expect(sut.sampled, false); }); + + test('add a metric to localAggregator adds it to metricSummary', () async { + fixture.options.enableSpanLocalMetricAggregation = true; + fixture.options.enableMetrics = true; + + final tracer = _createTracer(hub: fixture.hub) + ..localMetricsAggregator?.add(fakeMetric, 0); + await tracer.finish(); + + final sut = fixture.getSut(tracer); + expect(sut.metricSummaries, isNotEmpty); + }); + + test('add metric after creation does not add it to metricSummary', () async { + fixture.options.enableSpanLocalMetricAggregation = true; + fixture.options.enableMetrics = true; + + final tracer = _createTracer(hub: fixture.hub); + await tracer.finish(); + final sut = fixture.getSut(tracer); + tracer.localMetricsAggregator?.add(fakeMetric, 0); + + expect(sut.metricSummaries, isEmpty); + }); + + test('metricSummary is null by default', () async { + final tracer = _createTracer(); + await tracer.finish(); + final sut = fixture.getSut(tracer); + expect(sut.metricSummaries, null); + }); } class Fixture { + final SentryOptions options = SentryOptions(dsn: fakeDsn); + late final Hub hub = Hub(options); + SentryTransaction getSut(SentryTracer tracer) { return SentryTransaction(tracer); } diff --git a/flutter/example/lib/main.dart b/flutter/example/lib/main.dart index 2a68648ee0..5d52ab6080 100644 --- a/flutter/example/lib/main.dart +++ b/flutter/example/lib/main.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'dart:convert'; +import 'dart:math'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -83,6 +84,7 @@ Future setupSentry( options.debug = true; options.spotlight = Spotlight(enabled: true); options.enableTimeToFullDisplayTracing = true; + options.enableMetrics = true; options.maxRequestBodySize = MaxRequestBodySize.always; options.maxResponseBodySize = MaxResponseBodySize.always; @@ -527,6 +529,35 @@ class MainScaffold extends StatelessWidget { 'Demonstrates the logging integration. log.info() will create an info event send it to Sentry.', buttonTitle: 'Logging', ), + TooltipButton( + onPressed: () async { + final span = Sentry.getSpan() ?? + Sentry.startTransaction( + 'testMetrics', 'span summary example', + bindToScope: true); + Sentry.metrics().increment('increment key', + unit: DurationSentryMeasurementUnit.day); + Sentry.metrics().distribution('distribution key', + value: Random().nextDouble() * 10); + Sentry.metrics().set('set int key', + value: Random().nextInt(100), + tags: {'myTag': 'myValue', 'myTag2': 'myValue2'}); + Sentry.metrics().set('set string key', + stringValue: 'Random n ${Random().nextInt(100)}'); + Sentry.metrics() + .gauge('gauge key', value: Random().nextDouble() * 10); + Sentry.metrics().timing( + 'timing key', + function: () async => await Future.delayed( + Duration(milliseconds: Random().nextInt(100)), + () => span.finish()), + unit: DurationSentryMeasurementUnit.milliSecond, + ); + }, + text: + 'Demonstrates the metrics. It creates several metrics and send them to Sentry.', + buttonTitle: 'Metrics', + ), if (UniversalPlatform.isIOS || UniversalPlatform.isMacOS) const CocoaExample(), if (UniversalPlatform.isAndroid) const AndroidExample(), diff --git a/flutter/test/mocks.mocks.dart b/flutter/test/mocks.mocks.dart index d747a3889f..ee81d44430 100644 --- a/flutter/test/mocks.mocks.dart +++ b/flutter/test/mocks.mocks.dart @@ -640,6 +640,7 @@ class MockSentryTransaction extends _i1.Mock implements _i3.SentryTransaction { List<_i3.SentryThread>? threads, String? type, Map? measurements, + Map>? metricSummaries, _i3.SentryTransactionInfo? transactionInfo, }) => (super.noSuchMethod( @@ -674,6 +675,7 @@ class MockSentryTransaction extends _i1.Mock implements _i3.SentryTransaction { #threads: threads, #type: type, #measurements: measurements, + #metricSummaries: metricSummaries, #transactionInfo: transactionInfo, }, ), From 1584864a854b3f29bdcf0b55ba5f9496317dea68 Mon Sep 17 00:00:00 2001 From: getsentry-bot Date: Tue, 9 Apr 2024 15:17:45 +0000 Subject: [PATCH 130/237] release: 7.19.0 --- CHANGELOG.md | 2 +- dart/lib/src/version.dart | 2 +- dart/pubspec.yaml | 2 +- dio/lib/src/version.dart | 2 +- dio/pubspec.yaml | 4 ++-- drift/lib/src/version.dart | 2 +- drift/pubspec.yaml | 4 ++-- file/lib/src/version.dart | 2 +- file/pubspec.yaml | 4 ++-- flutter/example/pubspec.yaml | 2 +- flutter/lib/src/version.dart | 2 +- flutter/pubspec.yaml | 4 ++-- hive/lib/src/version.dart | 2 +- hive/pubspec.yaml | 4 ++-- isar/lib/src/version.dart | 2 +- isar/pubspec.yaml | 4 ++-- logging/lib/src/version.dart | 2 +- logging/pubspec.yaml | 4 ++-- sqflite/lib/src/version.dart | 2 +- sqflite/pubspec.yaml | 4 ++-- 20 files changed, 28 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 57c0ba848b..7b44a18ded 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## Unreleased +## 7.19.0 ### Features diff --git a/dart/lib/src/version.dart b/dart/lib/src/version.dart index 4f568f22fe..8f035ff451 100644 --- a/dart/lib/src/version.dart +++ b/dart/lib/src/version.dart @@ -9,7 +9,7 @@ library version; /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.18.0'; +const String sdkVersion = '7.19.0'; String sdkName(bool isWeb) => isWeb ? _browserSdkName : _ioSdkName; diff --git a/dart/pubspec.yaml b/dart/pubspec.yaml index 077d25aefa..d14d8bacc3 100644 --- a/dart/pubspec.yaml +++ b/dart/pubspec.yaml @@ -1,5 +1,5 @@ name: sentry -version: 7.18.0 +version: 7.19.0 description: > A crash reporting library for Dart that sends crash reports to Sentry.io. This library supports Dart VM and Web. For Flutter consider sentry_flutter instead. diff --git a/dio/lib/src/version.dart b/dio/lib/src/version.dart index cea3633864..0a1978233f 100644 --- a/dio/lib/src/version.dart +++ b/dio/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.18.0'; +const String sdkVersion = '7.19.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_dio'; diff --git a/dio/pubspec.yaml b/dio/pubspec.yaml index 4ef132dbb7..aade33f1f0 100644 --- a/dio/pubspec.yaml +++ b/dio/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_dio description: An integration which adds support for performance tracing for the Dio package. -version: 7.18.0 +version: 7.19.0 homepage: https://docs.sentry.io/platforms/dart/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -11,7 +11,7 @@ environment: dependencies: dio: ^5.0.0 - sentry: 7.18.0 + sentry: 7.19.0 dev_dependencies: meta: ^1.3.0 diff --git a/drift/lib/src/version.dart b/drift/lib/src/version.dart index 3cd30a54ba..53bd1f6467 100644 --- a/drift/lib/src/version.dart +++ b/drift/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.18.0'; +const String sdkVersion = '7.19.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_drift'; diff --git a/drift/pubspec.yaml b/drift/pubspec.yaml index 5fe411b5f1..c52e2937f1 100644 --- a/drift/pubspec.yaml +++ b/drift/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_drift description: An integration which adds support for performance tracing for the drift package. -version: 7.18.0 +version: 7.19.0 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -9,7 +9,7 @@ environment: sdk: '>=2.17.0 <4.0.0' dependencies: - sentry: 7.18.0 + sentry: 7.19.0 meta: ^1.3.0 drift: ^2.13.0 diff --git a/file/lib/src/version.dart b/file/lib/src/version.dart index c2a34fa8c9..e24a6de0bc 100644 --- a/file/lib/src/version.dart +++ b/file/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.18.0'; +const String sdkVersion = '7.19.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_file'; diff --git a/file/pubspec.yaml b/file/pubspec.yaml index cc7adacc4e..ba1a2fc4e2 100644 --- a/file/pubspec.yaml +++ b/file/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_file description: An integration which adds support for performance tracing for dart.io.File. -version: 7.18.0 +version: 7.19.0 homepage: https://docs.sentry.io/platforms/dart/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -10,7 +10,7 @@ environment: sdk: '>=2.19.0 <4.0.0' dependencies: - sentry: 7.18.0 + sentry: 7.19.0 meta: ^1.3.0 dev_dependencies: diff --git a/flutter/example/pubspec.yaml b/flutter/example/pubspec.yaml index 3d09b42741..dd565be890 100644 --- a/flutter/example/pubspec.yaml +++ b/flutter/example/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_flutter_example description: Demonstrates how to use the sentry_flutter plugin. -version: 7.18.0 +version: 7.19.0 publish_to: 'none' # Remove this line if you wish to publish to pub.dev diff --git a/flutter/lib/src/version.dart b/flutter/lib/src/version.dart index d44390a826..89821cce76 100644 --- a/flutter/lib/src/version.dart +++ b/flutter/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.18.0'; +const String sdkVersion = '7.19.0'; /// The default SDK name reported to Sentry.io in the submitted events. const String sdkName = 'sentry.dart.flutter'; diff --git a/flutter/pubspec.yaml b/flutter/pubspec.yaml index 1627f1260c..30ccca3dcc 100644 --- a/flutter/pubspec.yaml +++ b/flutter/pubspec.yaml @@ -1,5 +1,5 @@ name: sentry_flutter -version: 7.18.0 +version: 7.19.0 description: Sentry SDK for Flutter. This package aims to support different Flutter targets by relying on the many platforms supported by Sentry with native SDKs. homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart @@ -15,7 +15,7 @@ dependencies: sdk: flutter flutter_web_plugins: sdk: flutter - sentry: 7.18.0 + sentry: 7.19.0 package_info_plus: '>=1.0.0 <7.0.0' meta: ^1.3.0 ffi: ^2.0.0 diff --git a/hive/lib/src/version.dart b/hive/lib/src/version.dart index 89edc4dc0b..9ae5c45c00 100644 --- a/hive/lib/src/version.dart +++ b/hive/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.18.0'; +const String sdkVersion = '7.19.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_hive'; diff --git a/hive/pubspec.yaml b/hive/pubspec.yaml index 4d65143ac2..86d39fcf91 100644 --- a/hive/pubspec.yaml +++ b/hive/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_hive description: An integration which adds support for performance tracing for the hive package. -version: 7.18.0 +version: 7.19.0 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -9,7 +9,7 @@ environment: sdk: '>=2.17.0 <4.0.0' dependencies: - sentry: 7.18.0 + sentry: 7.19.0 hive: ^2.2.3 meta: ^1.3.0 diff --git a/isar/lib/src/version.dart b/isar/lib/src/version.dart index bd4ec9f9f2..e6cd47c793 100644 --- a/isar/lib/src/version.dart +++ b/isar/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.18.0'; +const String sdkVersion = '7.19.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_isar'; diff --git a/isar/pubspec.yaml b/isar/pubspec.yaml index 3cfdb66795..f87180882f 100644 --- a/isar/pubspec.yaml +++ b/isar/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_isar description: An integration which adds support for performance tracing for the isar package. -version: 7.18.0 +version: 7.19.0 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -12,7 +12,7 @@ environment: dependencies: isar: ^3.1.0 isar_flutter_libs: ^3.1.0 # contains Isar Core - sentry: 7.18.0 + sentry: 7.19.0 meta: ^1.3.0 path: ^1.8.3 diff --git a/logging/lib/src/version.dart b/logging/lib/src/version.dart index 6e8151ee32..023c1a52ff 100644 --- a/logging/lib/src/version.dart +++ b/logging/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.18.0'; +const String sdkVersion = '7.19.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_logging'; diff --git a/logging/pubspec.yaml b/logging/pubspec.yaml index f9f6d86e50..f7a0384d2e 100644 --- a/logging/pubspec.yaml +++ b/logging/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_logging description: An integration which adds support for recording log from the logging package. -version: 7.18.0 +version: 7.19.0 homepage: https://docs.sentry.io/platforms/dart/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -11,7 +11,7 @@ environment: dependencies: logging: ^1.0.0 - sentry: 7.18.0 + sentry: 7.19.0 dev_dependencies: lints: ^3.0.0 diff --git a/sqflite/lib/src/version.dart b/sqflite/lib/src/version.dart index 6b0a9b5b24..cc20b6cd9b 100644 --- a/sqflite/lib/src/version.dart +++ b/sqflite/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.18.0'; +const String sdkVersion = '7.19.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_sqflite'; diff --git a/sqflite/pubspec.yaml b/sqflite/pubspec.yaml index bdf8a4441a..154cfa3d10 100644 --- a/sqflite/pubspec.yaml +++ b/sqflite/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_sqflite description: An integration which adds support for performance tracing for the sqflite package. -version: 7.18.0 +version: 7.19.0 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -10,7 +10,7 @@ environment: flutter: '>=3.3.0' # matching sqflite dependencies: - sentry: 7.18.0 + sentry: 7.19.0 sqflite: ^2.0.0 sqflite_common: ^2.0.0 meta: ^1.3.0 From ca9b8e5cf1e88e2dc05b0d6cf3003401f45c1b8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20Andra=C5=A1ec?= Date: Wed, 10 Apr 2024 07:53:44 +0000 Subject: [PATCH 131/237] Enable canvaskit renderer tests (#1979) Co-authored-by: Giancarlo Buenaflor --- .github/workflows/flutter.yml | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/.github/workflows/flutter.yml b/.github/workflows/flutter.yml index 8572cd1394..a40f21ca12 100644 --- a/.github/workflows/flutter.yml +++ b/.github/workflows/flutter.yml @@ -93,18 +93,12 @@ jobs: cd flutter flutter pub get - - name: Test chrome (exclude canvasKit) + - name: Test chrome if: runner.os == 'Linux' run: | cd flutter flutter test --platform chrome --test-randomize-ordering-seed=random --exclude-tags canvasKit - - # TODO: Revert when canvasKit is available again in `beta` channel - - name: Test chrome (canvasKit) - if: runner.os == 'Linux' && matrix.sdk != 'beta' - run: | - cd flutter - flutter test --platform chrome --test-randomize-ordering-seed=random --tags canvasKit --web-renderer canvaskit + flutter test --platform chrome --test-randomize-ordering-seed=random --tags canvasKit --web-renderer canvaskit - name: Test VM with coverage run: | From be8cafe7319da28a1853bf73e5c3a1ade50320f3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 10 Apr 2024 09:54:05 +0200 Subject: [PATCH 132/237] chore: update flutter/scripts/update-android.sh to 7.8.0 (#1977) Co-authored-by: GitHub --- CHANGELOG.md | 8 ++++++++ flutter/android/build.gradle | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b44a18ded..ca09425f34 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## Unreleased + +### Dependencies + +- Bump Android SDK from v7.6.0 to v7.8.0 ([#1977](https://github.com/getsentry/sentry-dart/pull/1977)) + - [changelog](https://github.com/getsentry/sentry-java/blob/main/CHANGELOG.md#780) + - [diff](https://github.com/getsentry/sentry-java/compare/7.6.0...7.8.0) + ## 7.19.0 ### Features diff --git a/flutter/android/build.gradle b/flutter/android/build.gradle index a2c0f7316e..6014fa1117 100644 --- a/flutter/android/build.gradle +++ b/flutter/android/build.gradle @@ -60,7 +60,7 @@ android { } dependencies { - api 'io.sentry:sentry-android:7.6.0' + api 'io.sentry:sentry-android:7.8.0' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" // Required -- JUnit 4 framework From 6034b0a5af03e6891b1153ba6a88f095cbd7a948 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20Andra=C5=A1ec?= Date: Wed, 10 Apr 2024 10:23:48 +0000 Subject: [PATCH 133/237] Add textScale(r) value to Flutter context (#1886) * entrich event contexts app with text scale * read textScale from sentry widget event processor * revert change * revert change * update changelog * update changelog * Use scale method instead of deprecated `textScaleFactor` * fix changelog * fix changelog * use maybeTextScaleFactorOf method * fix changelog * fix changelog * use textScaleFactorOf * fix tests * update doc * Update CHANGELOG.md --------- Co-authored-by: Giancarlo Buenaflor --- CHANGELOG.md | 4 ++ dart/lib/src/protocol/sentry_app.dart | 9 ++++ dart/test/protocol/sentry_app_test.dart | 6 +++ flutter/example/lib/main.dart | 1 + .../widget_event_processor.dart | 31 +++++++++++++ flutter/lib/src/sentry_flutter.dart | 10 +++-- flutter/lib/src/sentry_widget.dart | 10 ++++- .../widget_event_processor_test.dart | 44 +++++++++++++++++++ 8 files changed, 110 insertions(+), 5 deletions(-) create mode 100644 flutter/lib/src/event_processor/widget_event_processor.dart create mode 100644 flutter/test/event_processor/widget_event_processor_test.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index ca09425f34..2123e2bde1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Features + +- Add textScale(r) value to Flutter context ([#1886](https://github.com/getsentry/sentry-dart/pull/1886)) + ### Dependencies - Bump Android SDK from v7.6.0 to v7.8.0 ([#1977](https://github.com/getsentry/sentry-dart/pull/1977)) diff --git a/dart/lib/src/protocol/sentry_app.dart b/dart/lib/src/protocol/sentry_app.dart index b5163e5856..24501ce540 100644 --- a/dart/lib/src/protocol/sentry_app.dart +++ b/dart/lib/src/protocol/sentry_app.dart @@ -19,6 +19,7 @@ class SentryApp { this.appMemory, this.inForeground, this.viewNames, + this.textScale, }); /// Human readable application name, as it appears on the platform. @@ -52,6 +53,9 @@ class SentryApp { /// The names of the currently visible views. final List? viewNames; + /// The current text scale. Only available on Flutter. + final double? textScale; + /// Deserializes a [SentryApp] from JSON [Map]. factory SentryApp.fromJson(Map data) { final viewNamesJson = data['view_names'] as List?; @@ -68,6 +72,7 @@ class SentryApp { appMemory: data['app_memory'], inForeground: data['in_foreground'], viewNames: viewNamesJson?.map((e) => e as String).toList(), + textScale: data['text_scale'], ); } @@ -84,6 +89,7 @@ class SentryApp { if (appMemory != null) 'app_memory': appMemory!, if (inForeground != null) 'in_foreground': inForeground!, if (viewNames != null && viewNames!.isNotEmpty) 'view_names': viewNames!, + if (textScale != null) 'text_scale': textScale!, }; } @@ -98,6 +104,7 @@ class SentryApp { appMemory: appMemory, inForeground: inForeground, viewNames: viewNames, + textScale: textScale, ); SentryApp copyWith({ @@ -111,6 +118,7 @@ class SentryApp { int? appMemory, bool? inForeground, List? viewNames, + double? textScale, }) => SentryApp( name: name ?? this.name, @@ -123,5 +131,6 @@ class SentryApp { appMemory: appMemory ?? this.appMemory, inForeground: inForeground ?? this.inForeground, viewNames: viewNames ?? this.viewNames, + textScale: textScale ?? this.textScale, ); } diff --git a/dart/test/protocol/sentry_app_test.dart b/dart/test/protocol/sentry_app_test.dart index 6fd4236efc..0fdef8a780 100644 --- a/dart/test/protocol/sentry_app_test.dart +++ b/dart/test/protocol/sentry_app_test.dart @@ -15,6 +15,7 @@ void main() { deviceAppHash: 'fixture-deviceAppHash', inForeground: true, viewNames: ['fixture-viewName', 'fixture-viewName2'], + textScale: 2.0, ); final sentryAppJson = { @@ -27,6 +28,7 @@ void main() { 'device_app_hash': 'fixture-deviceAppHash', 'in_foreground': true, 'view_names': ['fixture-viewName', 'fixture-viewName2'], + 'text_scale': 2.0, }; group('json', () { @@ -42,6 +44,7 @@ void main() { expect(json['device_app_hash'], 'fixture-deviceAppHash'); expect(json['in_foreground'], true); expect(json['view_names'], ['fixture-viewName', 'fixture-viewName2']); + expect(json['text_scale'], 2.0); }); test('fromJson', () { final sentryApp = SentryApp.fromJson(sentryAppJson); @@ -56,6 +59,7 @@ void main() { expect(json['device_app_hash'], 'fixture-deviceAppHash'); expect(json['in_foreground'], true); expect(json['view_names'], ['fixture-viewName', 'fixture-viewName2']); + expect(json['text_scale'], 2.0); }); }); @@ -86,6 +90,7 @@ void main() { deviceAppHash: 'hash1', inForeground: true, viewNames: ['screen1'], + textScale: 3.0, ); expect('name1', copy.name); @@ -97,6 +102,7 @@ void main() { expect('hash1', copy.deviceAppHash); expect(true, copy.inForeground); expect(['screen1'], copy.viewNames); + expect(3.0, copy.textScale); }); }); } diff --git a/flutter/example/lib/main.dart b/flutter/example/lib/main.dart index 5d52ab6080..c7f202f4f9 100644 --- a/flutter/example/lib/main.dart +++ b/flutter/example/lib/main.dart @@ -88,6 +88,7 @@ Future setupSentry( options.maxRequestBodySize = MaxRequestBodySize.always; options.maxResponseBodySize = MaxResponseBodySize.always; + options.navigatorKey = navigatorKey; _isIntegrationTest = isIntegrationTest; if (_isIntegrationTest) { diff --git a/flutter/lib/src/event_processor/widget_event_processor.dart b/flutter/lib/src/event_processor/widget_event_processor.dart new file mode 100644 index 0000000000..88e9159d4d --- /dev/null +++ b/flutter/lib/src/event_processor/widget_event_processor.dart @@ -0,0 +1,31 @@ +import 'dart:async'; + +import 'package:flutter/widgets.dart'; + +import '../../sentry_flutter.dart'; + +class WidgetEventProcessor implements EventProcessor { + @override + FutureOr apply(SentryEvent event, {Hint? hint}) { + if (event is SentryTransaction) { + return event; + } + if (event.exceptions == null && event.throwable == null) { + return event; + } + final context = sentryWidgetGlobalKey.currentContext; + if (context == null) { + return event; + } + + // ignore: deprecated_member_use + final textScale = MediaQuery.textScaleFactorOf(context); + return event.copyWith( + contexts: event.contexts.copyWith( + app: event.contexts.app?.copyWith( + textScale: textScale, + ), + ), + ); + } +} diff --git a/flutter/lib/src/sentry_flutter.dart b/flutter/lib/src/sentry_flutter.dart index b90bd47ad7..6c4e2c243b 100644 --- a/flutter/lib/src/sentry_flutter.dart +++ b/flutter/lib/src/sentry_flutter.dart @@ -8,6 +8,7 @@ import '../sentry_flutter.dart'; import 'event_processor/android_platform_exception_event_processor.dart'; import 'event_processor/flutter_exception_event_processor.dart'; import 'event_processor/platform_exception_event_processor.dart'; +import 'event_processor/widget_event_processor.dart'; import 'frame_callback_handler.dart'; import 'integrations/connectivity/connectivity_integration.dart'; import 'integrations/screenshot_integration.dart'; @@ -110,12 +111,13 @@ mixin SentryFlutter { options.addScopeObserver(NativeScopeObserver(_native!)); } - var flutterEventProcessor = FlutterEnricherEventProcessor(options); - options.addEventProcessor(flutterEventProcessor); + options.addEventProcessor(FlutterEnricherEventProcessor(options)); + options.addEventProcessor(WidgetEventProcessor()); if (options.platformChecker.platform.isAndroid) { - options - .addEventProcessor(AndroidPlatformExceptionEventProcessor(options)); + options.addEventProcessor( + AndroidPlatformExceptionEventProcessor(options), + ); } options.addEventProcessor(PlatformExceptionEventProcessor()); diff --git a/flutter/lib/src/sentry_widget.dart b/flutter/lib/src/sentry_widget.dart index ed390d1ab4..40709a5465 100644 --- a/flutter/lib/src/sentry_widget.dart +++ b/flutter/lib/src/sentry_widget.dart @@ -1,6 +1,11 @@ import 'package:flutter/cupertino.dart'; +import 'package:meta/meta.dart'; import '../sentry_flutter.dart'; +/// Key which is used to identify the [SentryWidget] +@internal +final sentryWidgetGlobalKey = GlobalKey(debugLabel: 'sentry_widget'); + /// This widget serves as a wrapper to include Sentry widgets such /// as [SentryScreenshotWidget] and [SentryUserInteractionWidget]. class SentryWidget extends StatefulWidget { @@ -18,6 +23,9 @@ class _SentryWidgetState extends State { Widget content = widget.child; content = SentryScreenshotWidget(child: content); content = SentryUserInteractionWidget(child: content); - return content; + return Container( + key: sentryWidgetGlobalKey, + child: content, + ); } } diff --git a/flutter/test/event_processor/widget_event_processor_test.dart b/flutter/test/event_processor/widget_event_processor_test.dart new file mode 100644 index 0000000000..5e93e288ff --- /dev/null +++ b/flutter/test/event_processor/widget_event_processor_test.dart @@ -0,0 +1,44 @@ +import 'package:flutter/widgets.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:sentry_flutter/sentry_flutter.dart'; +import 'package:sentry_flutter/src/event_processor/widget_event_processor.dart'; + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + late Fixture fixture; + + setUp(() { + fixture = Fixture(); + }); + + testWidgets('adds screenshot attachment dart:io', (tester) async { + await tester.runAsync(() async { + final sut = fixture.getSut(); + await tester.pumpWidget( + SentryWidget( + child: Text( + 'Catching Pokémon is a snap!', + textDirection: TextDirection.ltr, + ), + ), + ); + + final throwable = Exception(); + SentryEvent? event = SentryEvent(throwable: throwable); + event = event.copyWith( + contexts: event.contexts.copyWith( + app: SentryApp(), + ), + ); + event = await sut.apply(event); + + expect(event?.contexts.app?.textScale, 1.0); + }); + }); +} + +class Fixture { + WidgetEventProcessor getSut() { + return WidgetEventProcessor(); + } +} From 727330345f1e1f7def2842b27d8a94d75a1fea52 Mon Sep 17 00:00:00 2001 From: Bartek Pacia Date: Wed, 10 Apr 2024 11:56:35 +0100 Subject: [PATCH 134/237] Bump compileSdkVersion to 34 in Gradle buildscripts (#1980) * bump compileSdkVersion to 34 * update changelog --------- Co-authored-by: Giancarlo Buenaflor --- CHANGELOG.md | 675 ++++++++++++----------- flutter/android/build.gradle | 2 +- flutter/example/android/app/build.gradle | 4 +- 3 files changed, 343 insertions(+), 338 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2123e2bde1..c81d5170e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Build + +- Bump compileSdkVersion to 34 in Gradle buildscripts ([#1980](https://github.com/getsentry/sentry-dart/pull/1980)) + ### Features - Add textScale(r) value to Flutter context ([#1886](https://github.com/getsentry/sentry-dart/pull/1886)) @@ -77,7 +81,7 @@ - Fix transaction end timestamp trimming ([#1916](https://github.com/getsentry/sentry-dart/pull/1916)) - Transaction end timestamps are now correctly trimmed to the latest child span end timestamp -- remove transitive dart:io reference for web ([#1898](https://github.com/getsentry/sentry-dart/pull/1898)) +- remove transitive dart:io reference for web ([#1898](https://github.com/getsentry/sentry-dart/pull/1898)) ### Features @@ -126,7 +130,7 @@ - Method `hint.addAll(Map keysAndValues)` now takes `Map` instead of `Map` - Method `set(String key, dynamic value)` now takes value of `dynamic` instead of `Object` - Method `hint.get(String key)` now returns `dynamic` instead of `Object?` - + ### Dependencies - Bump Cocoa SDK from v8.18.0 to v8.19.0 ([#1803](https://github.com/getsentry/sentry-dart/pull/1844)) @@ -148,7 +152,7 @@ - Starting with Flutter 3.16, Sentry adds the [`appFlavor`](https://api.flutter.dev/flutter/services/appFlavor-constant.html) to the `flutter_context` ([#1799](https://github.com/getsentry/sentry-dart/pull/1799)) - Add beforeScreenshotCallback to SentryFlutterOptions ([#1805](https://github.com/getsentry/sentry-dart/pull/1805)) - Add support for `readTransaction` in `sqflite` ([#1819](https://github.com/getsentry/sentry-dart/pull/1819)) - + ### Dependencies - Bump Android SDK from v7.0.0 to v7.2.0 ([#1788](https://github.com/getsentry/sentry-dart/pull/1788), [#1815](https://github.com/getsentry/sentry-dart/pull/1815)) @@ -165,7 +169,7 @@ ### Fixes - Add debug_meta to all events ([#1756](https://github.com/getsentry/sentry-dart/pull/1756)) - - Fixes obfuscated stacktraces when `captureMessage` or `captureEvent` is called with `attachStacktrace` option + - Fixes obfuscated stacktraces when `captureMessage` or `captureEvent` is called with `attachStacktrace` option ### Features @@ -185,7 +189,7 @@ ### Fixes -- Fix SIGSEV, SIGABRT and SIGBUS crashes happening after/around the August Google Play System update, see [#2955](https://github-redirect.dependabot.com/getsentry/sentry-java/issues/2955) for more details (fix provided by Native SDK bump) +- Fix SIGSEV, SIGABRT and SIGBUS crashes happening after/around the August Google Play System update, see [#2955](https://github-redirect.dependabot.com/getsentry/sentry-java/issues/2955) for more details (fix provided by Native SDK bump) ### Dependencies @@ -202,7 +206,7 @@ ## 7.13.0 -### Fixes +### Fixes - Fixes setting the correct locale to contexts with navigatorKey ([#1724](https://github.com/getsentry/sentry-dart/pull/1724)) - If you have a selected locale in e.g MaterialApp, this fix will retrieve the correct locale for the event context. @@ -428,7 +432,7 @@ ### Features -- Add `SentryIOOverridesIntegration` that automatically wraps `File` into `SentryFile` ([#1362](https://github.com/getsentry/sentry-dart/pull/1362)) +- Add `SentryIOOverridesIntegration` that automatically wraps `File` into `SentryFile` ([#1362](https://github.com/getsentry/sentry-dart/pull/1362)) ```dart import 'package:sentry_file/sentry_file.dart'; @@ -1117,8 +1121,8 @@ options.beforeSend = (event, {hint}) { ### Fixes -* Scope.clone incorrectly accesses tags ([#978](https://github.com/getsentry/sentry-dart/pull/978)) -* beforeBreadcrumb was not adding the mutated breadcrumb ([#982](https://github.com/getsentry/sentry-dart/pull/982)) +- Scope.clone incorrectly accesses tags ([#978](https://github.com/getsentry/sentry-dart/pull/978)) +- beforeBreadcrumb was not adding the mutated breadcrumb ([#982](https://github.com/getsentry/sentry-dart/pull/982)) ### Features @@ -1133,25 +1137,26 @@ options.beforeSend = (event, {hint}) { ### Features -* Bump Flutter's min. supported version from 1.17.0 to 2.0.0 ([#966](https://github.com/getsentry/sentry-dart/pull/966)) +- Bump Flutter's min. supported version from 1.17.0 to 2.0.0 ([#966](https://github.com/getsentry/sentry-dart/pull/966)) This should not break anything since the Dart's min. version is already 2.12.0 and Flutter 2.0.0 uses Dart 2.12.0 ### Fixes -* Back compatibility of Object.hash for Dart 2.12.0 ([#966](https://github.com/getsentry/sentry-dart/pull/966)) -* Fix back compatibility for OnErrorIntegration integration ([#965](https://github.com/getsentry/sentry-dart/pull/965)) +- Back compatibility of Object.hash for Dart 2.12.0 ([#966](https://github.com/getsentry/sentry-dart/pull/966)) +- Fix back compatibility for OnErrorIntegration integration ([#965](https://github.com/getsentry/sentry-dart/pull/965)) ## 6.8.1 ### Fixes -* `Scope#setContexts` pasing a List value would't not work ([#932](https://github.com/getsentry/sentry-dart/pull/932)) +- `Scope#setContexts` pasing a List value would't not work ([#932](https://github.com/getsentry/sentry-dart/pull/932)) ### Features -* Add integration for `PlatformDispatcher.onError` ([#915](https://github.com/getsentry/sentry-dart/pull/915)) -- Bump Cocoa SDK to v7.22.0 ([#960](https://github.com/getsentry/sentry-dart/pull/960)) +- Add integration for `PlatformDispatcher.onError` ([#915](https://github.com/getsentry/sentry-dart/pull/915)) + +* Bump Cocoa SDK to v7.22.0 ([#960](https://github.com/getsentry/sentry-dart/pull/960)) - [changelog](https://github.com/getsentry/sentry-cocoa/blob/master/CHANGELOG.md#7220) - [diff](https://github.com/getsentry/sentry-cocoa/compare/7.21.0...7.22.0) @@ -1159,23 +1164,23 @@ This should not break anything since the Dart's min. version is already 2.12.0 a ### Fixes -* Missing OS context for iOS events ([#958](https://github.com/getsentry/sentry-dart/pull/958)) -* Fix: `Scope#clone` calls the Native bridges again via the `scopeObserver` ([#959](https://github.com/getsentry/sentry-dart/pull/959)) +- Missing OS context for iOS events ([#958](https://github.com/getsentry/sentry-dart/pull/958)) +- Fix: `Scope#clone` calls the Native bridges again via the `scopeObserver` ([#959](https://github.com/getsentry/sentry-dart/pull/959)) ### Features -* Dio Integration adds response data ([#934](https://github.com/getsentry/sentry-dart/pull/934)) +- Dio Integration adds response data ([#934](https://github.com/getsentry/sentry-dart/pull/934)) ## 6.7.0 ### Fixes -* Maps with Key Object, Object would fail during serialization if not String, Object ([#935](https://github.com/getsentry/sentry-dart/pull/935)) -* Breadcrumbs "Concurrent Modification" ([#948](https://github.com/getsentry/sentry-dart/pull/948)) -* Duplicative Screen size changed breadcrumbs ([#888](https://github.com/getsentry/sentry-dart/pull/888)) -* Duplicated Android Breadcrumbs with no Mechanism ([#954](https://github.com/getsentry/sentry-dart/pull/954)) -* Fix windows native method need default result ([#943](https://github.com/getsentry/sentry-dart/pull/943)) -* Add request instead of response data to `SentryRequest` in `DioEventProcessor` [#933](https://github.com/getsentry/sentry-dart/pull/933) +- Maps with Key Object, Object would fail during serialization if not String, Object ([#935](https://github.com/getsentry/sentry-dart/pull/935)) +- Breadcrumbs "Concurrent Modification" ([#948](https://github.com/getsentry/sentry-dart/pull/948)) +- Duplicative Screen size changed breadcrumbs ([#888](https://github.com/getsentry/sentry-dart/pull/888)) +- Duplicated Android Breadcrumbs with no Mechanism ([#954](https://github.com/getsentry/sentry-dart/pull/954)) +- Fix windows native method need default result ([#943](https://github.com/getsentry/sentry-dart/pull/943)) +- Add request instead of response data to `SentryRequest` in `DioEventProcessor` [#933](https://github.com/getsentry/sentry-dart/pull/933) ### Features @@ -1190,7 +1195,7 @@ This should not break anything since the Dart's min. version is already 2.12.0 a ### Fixes -* Context Escape with ScopeCallback ([#925](https://github.com/getsentry/sentry-dart/pull/925)) +- Context Escape with ScopeCallback ([#925](https://github.com/getsentry/sentry-dart/pull/925)) ## 6.6.2 @@ -1205,419 +1210,419 @@ This should not break anything since the Dart's min. version is already 2.12.0 a ### Fixes -* Send DidBecomeActiveNotification when OOM enabled (#905) -* `dio.addSentry` hangs if `dsn` is empty and SDK NoOp ([#920](https://github.com/getsentry/sentry-dart/pull/920)) -* addBreadcrumb throws on Android API < 24 because of NewApi usage ([#923](https://github.com/getsentry/sentry-dart/pull/923)) -* [`sentry_dio`](https://pub.dev/packages/sentry_dio) is promoted to GA and not experimental anymore ([#914](https://github.com/getsentry/sentry-dart/pull/914)) +- Send DidBecomeActiveNotification when OOM enabled (#905) +- `dio.addSentry` hangs if `dsn` is empty and SDK NoOp ([#920](https://github.com/getsentry/sentry-dart/pull/920)) +- addBreadcrumb throws on Android API < 24 because of NewApi usage ([#923](https://github.com/getsentry/sentry-dart/pull/923)) +- [`sentry_dio`](https://pub.dev/packages/sentry_dio) is promoted to GA and not experimental anymore ([#914](https://github.com/getsentry/sentry-dart/pull/914)) ## 6.6.1 ### Fixes -* Filter out app starts with more than 60s (#895) +- Filter out app starts with more than 60s (#895) ## 6.6.0 ### Fixes -* Bump: Sentry-Cocoa to 7.18.0 and Sentry-Android to 6.1.2 (#892) -* Fix: Add missing iOS contexts (#761) -* Fix serialization of threads (#844) -* Fix: `SentryAssetBundle` on Flutter >= 3.1 (#877) +- Bump: Sentry-Cocoa to 7.18.0 and Sentry-Android to 6.1.2 (#892) +- Fix: Add missing iOS contexts (#761) +- Fix serialization of threads (#844) +- Fix: `SentryAssetBundle` on Flutter >= 3.1 (#877) ### Features -* Feat: Client Reports (#829) -* Feat: Allow manual init of the Native SDK (#765) -* Feat: Attach Isolate name to thread context (#847) -* Feat: Add Android thread to platform stacktraces (#853) -* Feat: Sync Scope to Native (#858) +- Feat: Client Reports (#829) +- Feat: Allow manual init of the Native SDK (#765) +- Feat: Attach Isolate name to thread context (#847) +- Feat: Add Android thread to platform stacktraces (#853) +- Feat: Sync Scope to Native (#858) ### Sentry Self-hosted Compatibility -* Starting with version `6.6.0` of `sentry`, [Sentry's version >= v21.9.0](https://github.com/getsentry/self-hosted/releases) is required or you have to manually disable sending client reports via the `sendClientReports` option. This only applies to self-hosted Sentry. If you are using [sentry.io](https://sentry.io), no action is needed. +- Starting with version `6.6.0` of `sentry`, [Sentry's version >= v21.9.0](https://github.com/getsentry/self-hosted/releases) is required or you have to manually disable sending client reports via the `sendClientReports` option. This only applies to self-hosted Sentry. If you are using [sentry.io](https://sentry.io), no action is needed. ## 6.6.0-beta.4 -* Bump: Sentry-Cocoa to 7.17.0 and Sentry-Android to 6.1.1 (#891) +- Bump: Sentry-Cocoa to 7.17.0 and Sentry-Android to 6.1.1 (#891) ## 6.6.0-beta.3 -* Bump: Sentry-Cocoa to 7.16.1 (#886) +- Bump: Sentry-Cocoa to 7.16.1 (#886) ## 6.6.0-beta.2 -* Fix: Add user setter back in the scope (#883) -* Fix: clear method sets all properties synchronously (#882) +- Fix: Add user setter back in the scope (#883) +- Fix: clear method sets all properties synchronously (#882) ## 6.6.0-beta.1 -* Feat: Sync Scope to Native (#858) +- Feat: Sync Scope to Native (#858) ## 6.6.0-alpha.3 -* Feat: Attach Isolate name to thread context (#847) -* Fix: `SentryAssetBundle` on Flutter >= 3.1 (#877) -* Feat: Add Android thread to platform stacktraces (#853) -* Fix: Rename auto initialize property (#857) -* Bump: Sentry-Android to 6.0.0 (#879) +- Feat: Attach Isolate name to thread context (#847) +- Fix: `SentryAssetBundle` on Flutter >= 3.1 (#877) +- Feat: Add Android thread to platform stacktraces (#853) +- Fix: Rename auto initialize property (#857) +- Bump: Sentry-Android to 6.0.0 (#879) ## 6.6.0-alpha.2 -* Fix serialization of threads (#844) -* Feat: Allow manual init of the Native SDK (#765) +- Fix serialization of threads (#844) +- Feat: Allow manual init of the Native SDK (#765) ## 6.6.0-alpha.1 -* Feat: Client Reports (#829) -* Fix: Add missing iOS contexts (#761) +- Feat: Client Reports (#829) +- Fix: Add missing iOS contexts (#761) ### Sentry Self-hosted Compatibility -* Starting with version `6.6.0` of `sentry`, [Sentry's version >= v21.9.0](https://github.com/getsentry/self-hosted/releases) is required or you have to manually disable sending client reports via the `sendClientReports` option. This only applies to self-hosted Sentry. If you are using [sentry.io](https://sentry.io), no action is needed. +- Starting with version `6.6.0` of `sentry`, [Sentry's version >= v21.9.0](https://github.com/getsentry/self-hosted/releases) is required or you have to manually disable sending client reports via the `sendClientReports` option. This only applies to self-hosted Sentry. If you are using [sentry.io](https://sentry.io), no action is needed. ## 6.5.1 -* Update event contexts (#838) +- Update event contexts (#838) ## 6.5.0 -* No documented changes. +- No documented changes. ## 6.5.0-beta.2 -* Fix: Do not set the transaction to scope if no op (#828) +- Fix: Do not set the transaction to scope if no op (#828) ## 6.5.0-beta.1 -* No documented changes. +- No documented changes. ## 6.5.0-alpha.3 -* Feat: Support for platform stacktraces on Android (#788) +- Feat: Support for platform stacktraces on Android (#788) ## 6.5.0-alpha.2 -* Bump: Sentry-Android to 5.7.0 and Sentry-Cocoa to 7.11.0 (#796) -* Fix: Dio event processor safelly bails if no DioError in the exception list (#795) +- Bump: Sentry-Android to 5.7.0 and Sentry-Cocoa to 7.11.0 (#796) +- Fix: Dio event processor safelly bails if no DioError in the exception list (#795) ## 6.5.0-alpha.1 -* Feat: Mobile Vitals - Native App Start (#749) -* Feat: Mobile Vitals - Native Frames (#772) +- Feat: Mobile Vitals - Native App Start (#749) +- Feat: Mobile Vitals - Native Frames (#772) ## 6.4.0 ### Various fixes & improvements -* Fix: Missing userId on iOS when userId is not set (#782) by @marandaneto -* Allow to set startTimestamp & endTimestamp manually to SentrySpan (#676) by @fatihergin +- Fix: Missing userId on iOS when userId is not set (#782) by @marandaneto +- Allow to set startTimestamp & endTimestamp manually to SentrySpan (#676) by @fatihergin ## 6.4.0-beta.3 -* Feat: Allow to set startTimestamp & endTimestamp manually to SentrySpan (#676) -* Bump: Sentry-Cocoa to 7.10.0 (#777) -* Feat: Additional Dart/Flutter context information (#778) -* Bump: Kotlin plugin to 1.5.31 (#763) -* Fix: Missing userId on iOS when userId is not set (#782) +- Feat: Allow to set startTimestamp & endTimestamp manually to SentrySpan (#676) +- Bump: Sentry-Cocoa to 7.10.0 (#777) +- Feat: Additional Dart/Flutter context information (#778) +- Bump: Kotlin plugin to 1.5.31 (#763) +- Fix: Missing userId on iOS when userId is not set (#782) ## 6.4.0-beta.2 -* No documented changes. +- No documented changes. ## 6.4.0-beta.1 -* Fix: Disable log by default in debug mode (#753) -* [Dio] Ref: Replace FailedRequestAdapter with FailedRequestInterceptor (#728) -* Fix: Add missing return values - dart analyzer (#742) -* Feat: Add `DioEventProcessor` which improves DioError crash reports (#718) -* Fix: Do not report duplicated packages and integrations (#760) -* Feat: Allow manual init of the Native SDK or no Native SDK at all (#765) +- Fix: Disable log by default in debug mode (#753) +- [Dio] Ref: Replace FailedRequestAdapter with FailedRequestInterceptor (#728) +- Fix: Add missing return values - dart analyzer (#742) +- Feat: Add `DioEventProcessor` which improves DioError crash reports (#718) +- Fix: Do not report duplicated packages and integrations (#760) +- Feat: Allow manual init of the Native SDK or no Native SDK at all (#765) ## 6.3.0 -* Feat: Support maxSpan for performance API and expose SentryOptions through Hub (#716) -* Fix: await ZonedGuard integration to run (#732) -* Fix: `sentry_logging` incorrectly setting SDK name (#725) -* Bump: Sentry-Android to 5.6.1 and Sentry-Cocoa to 7.9.0 (#736) -* Feat: Support Attachment.addToTransactions (#709) -* Fix: captureTransaction should return emptyId when transaction is discarded (#713) -* Add `SentryAssetBundle` for automatic spans for asset loading (#685) -* Fix: `maxRequestBodySize` should be `never` by default when using the FailedRequestClientAdapter directly (#701) -* Feat: Add support for [Dio](https://pub.dev/packages/dio) (#688) -* Fix: Use correct data/extras type in tracer (#693) -* Fix: Do not throw when Throwable type is not supported for associating errors to a transaction (#692) -* Feat: Automatically create transactions when navigating between screens (#643) +- Feat: Support maxSpan for performance API and expose SentryOptions through Hub (#716) +- Fix: await ZonedGuard integration to run (#732) +- Fix: `sentry_logging` incorrectly setting SDK name (#725) +- Bump: Sentry-Android to 5.6.1 and Sentry-Cocoa to 7.9.0 (#736) +- Feat: Support Attachment.addToTransactions (#709) +- Fix: captureTransaction should return emptyId when transaction is discarded (#713) +- Add `SentryAssetBundle` for automatic spans for asset loading (#685) +- Fix: `maxRequestBodySize` should be `never` by default when using the FailedRequestClientAdapter directly (#701) +- Feat: Add support for [Dio](https://pub.dev/packages/dio) (#688) +- Fix: Use correct data/extras type in tracer (#693) +- Fix: Do not throw when Throwable type is not supported for associating errors to a transaction (#692) +- Feat: Automatically create transactions when navigating between screens (#643) ## 6.3.0-beta.4 -* Feat: Support Attachment.addToTransactions (#709) -* Fix: captureTransaction should return emptyId when transaction is discarded (#713) +- Feat: Support Attachment.addToTransactions (#709) +- Fix: captureTransaction should return emptyId when transaction is discarded (#713) ## 6.3.0-beta.3 -* Feat: Auto transactions duration trimming (#702) -* Add `SentryAssetBundle` for automatic spans for asset loading (#685) -* Feat: Configure idle transaction duration (#705) -* Fix: `maxRequestBodySize` should be `never` by default when using the FailedRequestClientAdapter directly (#701) +- Feat: Auto transactions duration trimming (#702) +- Add `SentryAssetBundle` for automatic spans for asset loading (#685) +- Feat: Configure idle transaction duration (#705) +- Fix: `maxRequestBodySize` should be `never` by default when using the FailedRequestClientAdapter directly (#701) ## 6.3.0-beta.2 -* Feat: Improve configuration options of `SentryNavigatorObserver` (#684) -* Feat: Add support for [Dio](https://pub.dev/packages/dio) (#688) -* Bump: Sentry-Android to 5.5.2 and Sentry-Cocoa to 7.8.0 (#696) +- Feat: Improve configuration options of `SentryNavigatorObserver` (#684) +- Feat: Add support for [Dio](https://pub.dev/packages/dio) (#688) +- Bump: Sentry-Android to 5.5.2 and Sentry-Cocoa to 7.8.0 (#696) ## 6.3.0-beta.1 -* Enha: Replace flutter default root name '/' with 'root' (#678) -* Fix: Use 'navigation' instead of 'ui.load' for auto transaction operation (#675) -* Fix: Use correct data/extras type in tracer (#693) -* Fix: Do not throw when Throwable type is not supported for associating errors to a transaction (#692) +- Enha: Replace flutter default root name '/' with 'root' (#678) +- Fix: Use 'navigation' instead of 'ui.load' for auto transaction operation (#675) +- Fix: Use correct data/extras type in tracer (#693) +- Fix: Do not throw when Throwable type is not supported for associating errors to a transaction (#692) ## 6.3.0-alpha.1 -* Feat: Automatically create transactions when navigating between screens (#643) +- Feat: Automatically create transactions when navigating between screens (#643) ## 6.2.2 -* Fix: ConcurrentModificationError in when finishing span (#664) -* Feat: Add enableNdkScopeSync Android support (#665) +- Fix: ConcurrentModificationError in when finishing span (#664) +- Feat: Add enableNdkScopeSync Android support (#665) ## 6.2.1 -* Fix: `sentry_logging` works now on web (#660) -* Fix: `sentry_logging` timestamps are in UTC (#660) -* Fix: `sentry_logging` Level.Off is never recorded (#660) -* Fix: Rate limiting fallback to retryAfterHeader (#658) +- Fix: `sentry_logging` works now on web (#660) +- Fix: `sentry_logging` timestamps are in UTC (#660) +- Fix: `sentry_logging` Level.Off is never recorded (#660) +- Fix: Rate limiting fallback to retryAfterHeader (#658) ## 6.2.0 -* Feat: Integration for `logging` (#631) -* Feat: Add logger name to `SentryLogger` and send errors in integrations to the registered logger (#641) +- Feat: Integration for `logging` (#631) +- Feat: Add logger name to `SentryLogger` and send errors in integrations to the registered logger (#641) ## 6.1.2 -* Fix: Remove is Enum check to support older Dart versions (#635) +- Fix: Remove is Enum check to support older Dart versions (#635) ## 6.1.1 -* Fix: Transaction serialization if not encodable (#633) +- Fix: Transaction serialization if not encodable (#633) ## 6.1.0 -* Bump: Sentry-Android to 5.3.0 and Sentry-Cocoa to 7.5.1 (#629) -* Fix: event.origin tag for macOS and other Apple platforms (#622) -* Feat: Add current route as transaction (#615) -* Feat: Add Breadcrumbs for Flutters `debugPrint` (#618) -* Feat: Enrich Dart context with isolate name (#600) -* Feat: Sentry Performance for HTTP client (#603) -* Performance API for Dart/Flutter (#530) +- Bump: Sentry-Android to 5.3.0 and Sentry-Cocoa to 7.5.1 (#629) +- Fix: event.origin tag for macOS and other Apple platforms (#622) +- Feat: Add current route as transaction (#615) +- Feat: Add Breadcrumbs for Flutters `debugPrint` (#618) +- Feat: Enrich Dart context with isolate name (#600) +- Feat: Sentry Performance for HTTP client (#603) +- Performance API for Dart/Flutter (#530) ### Breaking Changes: -* `SentryEvent` inherits from the `SentryEventLike` mixin -* `Scope#transaction` sets and reads from the `Scope#span` object if bound to the Scope +- `SentryEvent` inherits from the `SentryEventLike` mixin +- `Scope#transaction` sets and reads from the `Scope#span` object if bound to the Scope ## 6.1.0-beta.1 -* Feat: Add current route as transaction (#615) -* Feat: Add Breadcrumbs for Flutters `debugPrint` (#618) +- Feat: Add current route as transaction (#615) +- Feat: Add Breadcrumbs for Flutters `debugPrint` (#618) ## 6.1.0-alpha.2 -* Bump Sentry Android SDK to [5.2.0](https://github.com/getsentry/sentry-dart/pull/594) (#594) +- Bump Sentry Android SDK to [5.2.0](https://github.com/getsentry/sentry-dart/pull/594) (#594) - [changelog](https://github.com/getsentry/sentry-java/blob/5.2.0/CHANGELOG.md) - [diff](https://github.com/getsentry/sentry-java/compare/5.1.2...5.2.0) -* Feat: Enrich Dart context with isolate name (#600) -* Feat: Sentry Performance for HTTP client (#603) +- Feat: Enrich Dart context with isolate name (#600) +- Feat: Sentry Performance for HTTP client (#603) ## 6.1.0-alpha.1 -* Performance API for Dart/Flutter (#530) +- Performance API for Dart/Flutter (#530) ### Breaking Changes: -* `SentryEvent` inherits from the `SentryEventLike` mixin -* `Scope#transaction` sets and reads from the `Scope#span` object if bound to the Scope +- `SentryEvent` inherits from the `SentryEventLike` mixin +- `Scope#transaction` sets and reads from the `Scope#span` object if bound to the Scope ## 6.0.1 -* Fix: Set custom SentryHttpClientError when HTTP error is captured without an exception (#580) -* Bump: Android AGP 4.1 (#586) -* Bump: Sentry Cocoa to 7.3.0 (#589) +- Fix: Set custom SentryHttpClientError when HTTP error is captured without an exception (#580) +- Bump: Android AGP 4.1 (#586) +- Bump: Sentry Cocoa to 7.3.0 (#589) ## 6.0.0 -* Fix: Update `SentryUser` according to docs (#561) -* Feat: Enable or disable reporting of packages (#563) -* Bump: Sentry-Cocoa to 7.2.7 (#578) -* Bump: Sentry-Android to 5.1.2 (#578) -* Fix: Read Sentry config from environment variables as fallback (#567) +- Fix: Update `SentryUser` according to docs (#561) +- Feat: Enable or disable reporting of packages (#563) +- Bump: Sentry-Cocoa to 7.2.7 (#578) +- Bump: Sentry-Android to 5.1.2 (#578) +- Fix: Read Sentry config from environment variables as fallback (#567) ## 6.0.0-beta.4 ### Breaking Changes: -* Feat: Lists of exceptions and threads (#524) -* Feat: Collect more information for exceptions collected via `FlutterError.onError` (#538) -* Feat: Add maxAttachmentSize option (#553) -* Feat: HTTP breadcrumbs have the request & response size if available (#552) +- Feat: Lists of exceptions and threads (#524) +- Feat: Collect more information for exceptions collected via `FlutterError.onError` (#538) +- Feat: Add maxAttachmentSize option (#553) +- Feat: HTTP breadcrumbs have the request & response size if available (#552) ## 6.0.0-beta.3 -* Fix: Re-initialization of Flutter SDK (#526) -* Enhancement: Call `toString()` on all non-serializable fields (#528) -* Fix: Always call `Flutter.onError` in order to not swallow messages (#533) -* Bump: Android SDK to 5.1.0-beta.6 (#535) +- Fix: Re-initialization of Flutter SDK (#526) +- Enhancement: Call `toString()` on all non-serializable fields (#528) +- Fix: Always call `Flutter.onError` in order to not swallow messages (#533) +- Bump: Android SDK to 5.1.0-beta.6 (#535) ## 6.0.0-beta.2 -* Fix: Serialization of Flutter Context (#520) -* Feat: Add support for attachments (#505) -* Feat: Add support for User Feedback (#506) +- Fix: Serialization of Flutter Context (#520) +- Feat: Add support for attachments (#505) +- Feat: Add support for User Feedback (#506) ## 6.0.0-beta.1 -* Feat: Browser detection (#502) -* Feat: Enrich events with more context (#452) -* Feat: Add Culture Context (#491) -* Feat: Add DeduplicationEventProcessor (#498) -* Feat: Capture failed requests as event (#473) -* Feat: `beforeSend` callback accepts async code (#494) +- Feat: Browser detection (#502) +- Feat: Enrich events with more context (#452) +- Feat: Add Culture Context (#491) +- Feat: Add DeduplicationEventProcessor (#498) +- Feat: Capture failed requests as event (#473) +- Feat: `beforeSend` callback accepts async code (#494) ### Breaking Changes: -* Ref: EventProcessor changed to an interface (#489) -* Feat: Support envelope based transport for events (#391) - * The method signature of `Transport` changed from `Future send(SentryEvent event)` to `Future send(SentryEnvelope envelope)` -* Remove `Sentry.currentHub` (#490) -* Ref: Rename `cacheDirSize` to `maxCacheItems` and add `maxCacheItems` for iOS (#495) -* Ref: Add error and stacktrace parameter to logger (#503) -* Feat: Change timespans to Durations in SentryOptions (#504) -* Feat: `beforeSend` callback accepts async code (#494) +- Ref: EventProcessor changed to an interface (#489) +- Feat: Support envelope based transport for events (#391) + - The method signature of `Transport` changed from `Future send(SentryEvent event)` to `Future send(SentryEnvelope envelope)` +- Remove `Sentry.currentHub` (#490) +- Ref: Rename `cacheDirSize` to `maxCacheItems` and add `maxCacheItems` for iOS (#495) +- Ref: Add error and stacktrace parameter to logger (#503) +- Feat: Change timespans to Durations in SentryOptions (#504) +- Feat: `beforeSend` callback accepts async code (#494) ### Sentry Self Hosted Compatibility -* Since version `6.0.0` of the `sentry`, [Sentry's version >= v20.6.0](https://github.com/getsentry/self-hosted/releases) is required. This only applies to on-premise Sentry, if you are using sentry.io no action is needed. +- Since version `6.0.0` of the `sentry`, [Sentry's version >= v20.6.0](https://github.com/getsentry/self-hosted/releases) is required. This only applies to on-premise Sentry, if you are using sentry.io no action is needed. ## 5.1.0 -* Fix: Merge user from event and scope (#467) -* Feature: Allow setting of default values for in-app-frames via `SentryOptions.considerInAppFramesByDefault` (#482) -* Bump: sentry-android to v5.0.1 (#486) -* Bump: Sentry-Cocoa to 7.1.3 for iOS and macOS (#488) +- Fix: Merge user from event and scope (#467) +- Feature: Allow setting of default values for in-app-frames via `SentryOptions.considerInAppFramesByDefault` (#482) +- Bump: sentry-android to v5.0.1 (#486) +- Bump: Sentry-Cocoa to 7.1.3 for iOS and macOS (#488) ## 5.1.0-beta.1 -* Fix: `Sentry.close()` closes native SDK integrations (#388) -* Feat: Support for macOS (#389) -* Feat: Support for Linux (#402) -* Feat: Support for Windows (#407) -* Fix: Mark `Sentry.currentHub` as deprecated (#406) -* Fix: Set console logger as default logger in debug mode (#413) -* Fix: Use name from pubspec.yaml for release if package id is not available (#411) -* Feat: `SentryHttpClient` tracks the duration which a request takes and logs failed requests (#414) -* Bump: sentry-cocoa to v7.0.0 (#424) -* Feat: Support for Out-of-Memory-Tracking on macOS/iOS (#424) -* Fix: Trim `\u0000` from Windows package info (#420) -* Feature: Log calls to `print()` as Breadcrumbs (#439) -* Fix: `dist` was read from `SENTRY_DSN`, now it's read from `SENTRY_DIST` (#442) -* Bump: sentry-cocoa to v7.0.3 (#445) -* Fix: Fix adding integrations on web (#450) -* Fix: Use `log()` instead of `print()` for SDK logging (#453) -* Bump: sentry-android to v5.0.0-beta.2 (#457) -* Feature: Add `withScope` callback to capture methods (#463) -* Fix: Add missing properties `language`, `screenHeightPixels` and `screenWidthPixels` to `SentryDevice` (#465) +- Fix: `Sentry.close()` closes native SDK integrations (#388) +- Feat: Support for macOS (#389) +- Feat: Support for Linux (#402) +- Feat: Support for Windows (#407) +- Fix: Mark `Sentry.currentHub` as deprecated (#406) +- Fix: Set console logger as default logger in debug mode (#413) +- Fix: Use name from pubspec.yaml for release if package id is not available (#411) +- Feat: `SentryHttpClient` tracks the duration which a request takes and logs failed requests (#414) +- Bump: sentry-cocoa to v7.0.0 (#424) +- Feat: Support for Out-of-Memory-Tracking on macOS/iOS (#424) +- Fix: Trim `\u0000` from Windows package info (#420) +- Feature: Log calls to `print()` as Breadcrumbs (#439) +- Fix: `dist` was read from `SENTRY_DSN`, now it's read from `SENTRY_DIST` (#442) +- Bump: sentry-cocoa to v7.0.3 (#445) +- Fix: Fix adding integrations on web (#450) +- Fix: Use `log()` instead of `print()` for SDK logging (#453) +- Bump: sentry-android to v5.0.0-beta.2 (#457) +- Feature: Add `withScope` callback to capture methods (#463) +- Fix: Add missing properties `language`, `screenHeightPixels` and `screenWidthPixels` to `SentryDevice` (#465) ### Sentry Self Hosted Compatibility -* This version of the `sentry` Dart package requires [Sentry server >= v20.6.0](https://github.com/getsentry/self-hosted/releases). This only applies to on-premise Sentry, if you are using sentry.io no action is needed. +- This version of the `sentry` Dart package requires [Sentry server >= v20.6.0](https://github.com/getsentry/self-hosted/releases). This only applies to on-premise Sentry, if you are using sentry.io no action is needed. ## 5.0.0 -* Sound null safety -* Fix: event.origin and event.environment tags have wrong value for iOS (#365) and (#369) -* Fix: Fix deprecated `registrar.messenger` call in `SentryFlutterWeb` (#364) -* Fix: Enable breadcrumb recording mechanism based on platform (#366) -* Feat: Send default PII options (#360) -* Bump: sentry-cocoa to v6.2.1 (#360) -* Feat: Migration from `package_info` to `package_info_plus` plugin (#370) -* Fix: Set `SentryOptions.debug` in `sentry` (#376) -* Fix: Read all environment variables in `sentry` (#375) +- Sound null safety +- Fix: event.origin and event.environment tags have wrong value for iOS (#365) and (#369) +- Fix: Fix deprecated `registrar.messenger` call in `SentryFlutterWeb` (#364) +- Fix: Enable breadcrumb recording mechanism based on platform (#366) +- Feat: Send default PII options (#360) +- Bump: sentry-cocoa to v6.2.1 (#360) +- Feat: Migration from `package_info` to `package_info_plus` plugin (#370) +- Fix: Set `SentryOptions.debug` in `sentry` (#376) +- Fix: Read all environment variables in `sentry` (#375) ### Breaking Changes: -* Return type of `Sentry.close()` changed from `void` to `Future` and `Integration.close()` changed from `void` to `FutureOr` (#395) -* Remove deprecated member `enableLifecycleBreadcrumbs`. Use `enableAppLifecycleBreadcrumbs` instead. (#366) +- Return type of `Sentry.close()` changed from `void` to `Future` and `Integration.close()` changed from `void` to `FutureOr` (#395) +- Remove deprecated member `enableLifecycleBreadcrumbs`. Use `enableAppLifecycleBreadcrumbs` instead. (#366) ## 4.1.0-nullsafety.1 -* Bump: sentry-android to v4.3.0 (#343) -* Fix: Multiple FlutterError.onError calls in FlutterErrorIntegration (#345) -* Fix: Pass hint to EventProcessors (#356) -* Fix: EventProcessors were not dropping events when returning null (#353) +- Bump: sentry-android to v4.3.0 (#343) +- Fix: Multiple FlutterError.onError calls in FlutterErrorIntegration (#345) +- Fix: Pass hint to EventProcessors (#356) +- Fix: EventProcessors were not dropping events when returning null (#353) ### Breaking Changes: -* Fix: Plugin Registrant class moved to barrel file (#358) - * This changed the import from `import 'package:sentry_flutter/src/sentry_flutter_web.dart';` +- Fix: Plugin Registrant class moved to barrel file (#358) + - This changed the import from `import 'package:sentry_flutter/src/sentry_flutter_web.dart';` to `import 'package:sentry_flutter/sentry_flutter_web.dart';` - * This could lead to breaking changes. Typically it shouldn't because the referencing file is auto-generated. -* Fix: Prefix classes with Sentry (#357) - * A couple of classes were often conflicting with user's code. + - This could lead to breaking changes. Typically it shouldn't because the referencing file is auto-generated. +- Fix: Prefix classes with Sentry (#357) + - A couple of classes were often conflicting with user's code. Thus this change renames the following classes: - * `App` -> `SentryApp` - * `Browser` -> `SentryBrowser` - * `Device` -> `SentryDevice` - * `Gpu` -> `SentryGpu` - * `Integration` -> `SentryIntegration` - * `Message` -> `SentryMessage` - * `OperatingSystem` -> `SentryOperatingSystem` - * `Request` -> `SentryRequest` - * `User` -> `SentryUser` - * `Orientation` -> `SentryOrientation` + - `App` -> `SentryApp` + - `Browser` -> `SentryBrowser` + - `Device` -> `SentryDevice` + - `Gpu` -> `SentryGpu` + - `Integration` -> `SentryIntegration` + - `Message` -> `SentryMessage` + - `OperatingSystem` -> `SentryOperatingSystem` + - `Request` -> `SentryRequest` + - `User` -> `SentryUser` + - `Orientation` -> `SentryOrientation` ## 4.1.0-nullsafety.0 -* Fix: Do not append stack trace to the exception if there are no frames -* Fix: Empty DSN disables the SDK and runs the App -* Feat: sentry and sentry_flutter null-safety thanks to @ueman and @fzyzcjy +- Fix: Do not append stack trace to the exception if there are no frames +- Fix: Empty DSN disables the SDK and runs the App +- Feat: sentry and sentry_flutter null-safety thanks to @ueman and @fzyzcjy ## 4.0.6 -* Fix: captureMessage defaults SentryLevel to info -* Fix: SentryEvent.throwable returns the unwrapped throwable instead of the throwableMechanism -* Feat: Support enableNativeCrashHandling on iOS +- Fix: captureMessage defaults SentryLevel to info +- Fix: SentryEvent.throwable returns the unwrapped throwable instead of the throwableMechanism +- Feat: Support enableNativeCrashHandling on iOS ## 4.0.5 -* Bump: sentry-android to v4.0.0 -* Fix: Pana Flutter upper bound deprecation -* Fix: sentry_flutter static analysis (pana) using stable version +- Bump: sentry-android to v4.0.0 +- Fix: Pana Flutter upper bound deprecation +- Fix: sentry_flutter static analysis (pana) using stable version ## 4.0.4 -* Fix: Call WidgetsFlutterBinding.ensureInitialized() within runZoneGuarded +- Fix: Call WidgetsFlutterBinding.ensureInitialized() within runZoneGuarded ## 4.0.3 -* Fix: Auto session tracking start on iOS #274 -* Bump: Sentry-cocoa to 6.1.4 +- Fix: Auto session tracking start on iOS #274 +- Bump: Sentry-cocoa to 6.1.4 ## 4.0.2 -* Fix: Mark session as `errored` in iOS #270 -* Fix: Pass auto session tracking interval to iOS -* Fix: Deprecated binaryMessenger (MethodChannel member) for Flutter Web -* Ref: Make `WidgetsFlutterBinding.ensureInitialized();` the first thing the Sentry SDK calls. -* Bump: Sentry-cocoa to 6.0.12 -* Feat: Respect FlutterError silent flag #248 -* Bump: Android SDK to v3.2.1 #273 +- Fix: Mark session as `errored` in iOS #270 +- Fix: Pass auto session tracking interval to iOS +- Fix: Deprecated binaryMessenger (MethodChannel member) for Flutter Web +- Ref: Make `WidgetsFlutterBinding.ensureInitialized();` the first thing the Sentry SDK calls. +- Bump: Sentry-cocoa to 6.0.12 +- Feat: Respect FlutterError silent flag #248 +- Bump: Android SDK to v3.2.1 #273 ## 4.0.1 -* Ref: Changed category of Flutter lifecycle tracking [#240](https://github.com/getsentry/sentry-dart/issues/240) -* Fix: Envelope length should be based on the UTF8 array instead of String length +- Ref: Changed category of Flutter lifecycle tracking [#240](https://github.com/getsentry/sentry-dart/issues/240) +- Fix: Envelope length should be based on the UTF8 array instead of String length ## 4.0.0 @@ -1627,100 +1632,100 @@ New features not offered by <= v4.0.0: ### Dart SDK -* Sentry's [Unified API](https://develop.sentry.dev/sdk/unified-api/). -* Complete Sentry's [Protocol](https://develop.sentry.dev/sdk/event-payloads/) available. -* [Dart SDK](https://docs.sentry.io/platforms/dart/) docs. -* Automatic [HTTP Breadcrumbs](https://docs.sentry.io/platforms/dart/usage/advanced-usage/#automatic-breadcrumbs) for [http.Client](https://pub.dev/documentation/http/latest/http/Client-class.html) -* No boilerplate for `runZonedGuarded` and `Isolate.current.addErrorListener` -* All events are enriched with [Scope's Contexts](https://develop.sentry.dev/sdk/event-payloads/#scope-interfaces), this includes Breadcrumbs, tags, User, etc... +- Sentry's [Unified API](https://develop.sentry.dev/sdk/unified-api/). +- Complete Sentry's [Protocol](https://develop.sentry.dev/sdk/event-payloads/) available. +- [Dart SDK](https://docs.sentry.io/platforms/dart/) docs. +- Automatic [HTTP Breadcrumbs](https://docs.sentry.io/platforms/dart/usage/advanced-usage/#automatic-breadcrumbs) for [http.Client](https://pub.dev/documentation/http/latest/http/Client-class.html) +- No boilerplate for `runZonedGuarded` and `Isolate.current.addErrorListener` +- All events are enriched with [Scope's Contexts](https://develop.sentry.dev/sdk/event-payloads/#scope-interfaces), this includes Breadcrumbs, tags, User, etc... ### Flutter SDK -* The Flutter SDK is built on top of the Dart SDK, so it includes all the available features, plus -* [Flutter SDK](https://docs.sentry.io/platforms/flutter/) docs. -* Automatic [NavigatorObserver Breadcrumbs](https://docs.sentry.io/platforms/flutter/usage/advanced-usage/#automatic-breadcrumbs) -* Automatic [Device's Breadcrumbs](https://docs.sentry.io/platforms/flutter/usage/advanced-usage/#automatic-breadcrumbs) through the Android and iOS SDKs or via Sentry's `WidgetsBindingObserver` wrapper -* No boilerplate for `FlutterError.onError` -* All events are enriched with [Contexts's data](https://develop.sentry.dev/sdk/event-payloads/contexts/), this includes Device's, OS, App info, etc... -* Offline caching -* [Release health](https://docs.sentry.io/product/releases/health/) -* Captures not only Dart and Flutter errors, but also errors caused on the native platforms, Like Kotlin, Java, C and C++ for Android and Swift, ObjC, C, C++ for iOS -* Supports Fatal crashes, Event is going to be sent on App's restart -* Supports `split-debug-info` for Android only -* Flutter Android, iOS and limited support for Flutter Web +- The Flutter SDK is built on top of the Dart SDK, so it includes all the available features, plus +- [Flutter SDK](https://docs.sentry.io/platforms/flutter/) docs. +- Automatic [NavigatorObserver Breadcrumbs](https://docs.sentry.io/platforms/flutter/usage/advanced-usage/#automatic-breadcrumbs) +- Automatic [Device's Breadcrumbs](https://docs.sentry.io/platforms/flutter/usage/advanced-usage/#automatic-breadcrumbs) through the Android and iOS SDKs or via Sentry's `WidgetsBindingObserver` wrapper +- No boilerplate for `FlutterError.onError` +- All events are enriched with [Contexts's data](https://develop.sentry.dev/sdk/event-payloads/contexts/), this includes Device's, OS, App info, etc... +- Offline caching +- [Release health](https://docs.sentry.io/product/releases/health/) +- Captures not only Dart and Flutter errors, but also errors caused on the native platforms, Like Kotlin, Java, C and C++ for Android and Swift, ObjC, C, C++ for iOS +- Supports Fatal crashes, Event is going to be sent on App's restart +- Supports `split-debug-info` for Android only +- Flutter Android, iOS and limited support for Flutter Web Improvements: -* Feat: Added a copyWith method to all the protocol classes +- Feat: Added a copyWith method to all the protocol classes Packages were released on [sentry pubdev](https://pub.dev/packages/sentry) and [sentry_flutter pubdev](https://pub.dev/packages/sentry_flutter) ### Sentry Self Hosted Compatibility -* Since version `4.0.0` of the `sentry_flutter`, [Sentry's version >= v20.6.0](https://github.com/getsentry/self-hosted/releases) is required. This only applies to on-premise Sentry, if you are using sentry.io no action is needed. +- Since version `4.0.0` of the `sentry_flutter`, [Sentry's version >= v20.6.0](https://github.com/getsentry/self-hosted/releases) is required. This only applies to on-premise Sentry, if you are using sentry.io no action is needed. ## 4.0.0-beta.2 -* Ref: Remove duplicated attachStackTrace field -* Fix: Flutter Configurations should be able to mutate the SentryFlutterOptions -* Enhancement: Add SentryWidgetsBindingObserver, an Integration that captures certain window and device events. -* Enhancement: Set `options.environment` on SDK init based on the flags (kReleaseMode, kDebugMode, kProfileMode or SENTRY_ENVIRONMENT). -* Feature: SentryHttpClient to capture HTTP requests as breadcrumbs -* Ref: Only assign non-null option values in Android native integration in order preserve default values -* Enhancement: Add 'attachThreads' in options. When enabled, threads are attached to all logged events for Android -* Ref: Rename typedef `Logger` to `SentryLogger` to prevent name clashes with logging packages -* Fix: Scope Event processors should be awaited -* Fix: Package usage as git dependency +- Ref: Remove duplicated attachStackTrace field +- Fix: Flutter Configurations should be able to mutate the SentryFlutterOptions +- Enhancement: Add SentryWidgetsBindingObserver, an Integration that captures certain window and device events. +- Enhancement: Set `options.environment` on SDK init based on the flags (kReleaseMode, kDebugMode, kProfileMode or SENTRY_ENVIRONMENT). +- Feature: SentryHttpClient to capture HTTP requests as breadcrumbs +- Ref: Only assign non-null option values in Android native integration in order preserve default values +- Enhancement: Add 'attachThreads' in options. When enabled, threads are attached to all logged events for Android +- Ref: Rename typedef `Logger` to `SentryLogger` to prevent name clashes with logging packages +- Fix: Scope Event processors should be awaited +- Fix: Package usage as git dependency ### Breaking changes -* `Logger` typedef is renamed to `SentryLogger` -* `attachStackTrace` is renamed to `attachStacktrace` +- `Logger` typedef is renamed to `SentryLogger` +- `attachStackTrace` is renamed to `attachStacktrace` ## 4.0.0-beta.1 -* Fix: StackTrace frames with 'package' uri.scheme are inApp by default #185 -* Fix: Missing App's StackTrace frames for Flutter errors -* Enhancement: Add isolateErrorIntegration and runZonedGuardedIntegration to default integrations in sentry-dart -* Fix: Breadcrumb list is a plain list instead of a values list #201 -* Ref: Remove deprecated classes (Flutter Plugin for Android) and cleaning up #186 -* Fix: Handle immutable event lists and maps -* Fix: NDK integration was being disabled by a typo -* Fix: Missing toList for debug meta #192 -* Enhancement: NavigationObserver to record Breadcrumbs for navigation events #197 -* Fix: Integrations should be closeable -* Feat: Support split-debug-info for Android #191 -* Fix: the event payload must never serialize null or empty fields -* Ref: Make hints optional +- Fix: StackTrace frames with 'package' uri.scheme are inApp by default #185 +- Fix: Missing App's StackTrace frames for Flutter errors +- Enhancement: Add isolateErrorIntegration and runZonedGuardedIntegration to default integrations in sentry-dart +- Fix: Breadcrumb list is a plain list instead of a values list #201 +- Ref: Remove deprecated classes (Flutter Plugin for Android) and cleaning up #186 +- Fix: Handle immutable event lists and maps +- Fix: NDK integration was being disabled by a typo +- Fix: Missing toList for debug meta #192 +- Enhancement: NavigationObserver to record Breadcrumbs for navigation events #197 +- Fix: Integrations should be closeable +- Feat: Support split-debug-info for Android #191 +- Fix: the event payload must never serialize null or empty fields +- Ref: Make hints optional ### Breaking changes -* `Sentry.init` and `SentryFlutter.init` have an optional callback argument which runs the host App after Sentry initialization. -* `Integration` is an `Interface` instead of a pure Function -* `Hints` are optional arguments -* Sentry Dart SDK adds an `IsolateError` handler by default +- `Sentry.init` and `SentryFlutter.init` have an optional callback argument which runs the host App after Sentry initialization. +- `Integration` is an `Interface` instead of a pure Function +- `Hints` are optional arguments +- Sentry Dart SDK adds an `IsolateError` handler by default ## 4.0.0-alpha.2 -* Enhancement: `Contexts` were added to the `Scope` #154 -* Fix: App. would hang if `debug` mode was enabled and refactoring ##157 -* Enhancement: Sentry Protocol v7 -* Enhancement: Added missing Protocol fields, `Request`, `SentryStackTrace`...) #155 -* Feat: Added `attachStackTrace` options to attach stack traces on `captureMessage` calls -* Feat: Flutter SDK has the Native SDKs embedded (Android and Apple) #158 +- Enhancement: `Contexts` were added to the `Scope` #154 +- Fix: App. would hang if `debug` mode was enabled and refactoring ##157 +- Enhancement: Sentry Protocol v7 +- Enhancement: Added missing Protocol fields, `Request`, `SentryStackTrace`...) #155 +- Feat: Added `attachStackTrace` options to attach stack traces on `captureMessage` calls +- Feat: Flutter SDK has the Native SDKs embedded (Android and Apple) #158 ### Breaking changes -* `Sentry.init` returns a `Future`. -* Dart min. SDK is `2.8.0` -* Flutter min. SDK is `1.17.0` -* Timestamp has millis precision. -* For better groupping, add your own package to the `addInAppInclude` list, e.g. `options.addInAppInclude('sentry_flutter_example');` -* A few classes of the `Protocol` were renamed. +- `Sentry.init` returns a `Future`. +- Dart min. SDK is `2.8.0` +- Flutter min. SDK is `1.17.0` +- Timestamp has millis precision. +- For better groupping, add your own package to the `addInAppInclude` list, e.g. `options.addInAppInclude('sentry_flutter_example');` +- A few classes of the `Protocol` were renamed. ### Sentry Self Hosted Compatibility -* Since version `4.0.0` of the `sentry_flutter`, `Sentry` version >= `v20.6.0` is required. This only applies to on-premise Sentry, if you are using sentry.io no action is needed. +- Since version `4.0.0` of the `sentry_flutter`, `Sentry` version >= `v20.6.0` is required. This only applies to on-premise Sentry, if you are using sentry.io no action is needed. ## 4.0.0-alpha.1 @@ -1728,10 +1733,10 @@ First Release of Sentry's new SDK for Dart/Flutter. New features not offered by <= v4.0.0: -* Sentry's [Unified API](https://develop.sentry.dev/sdk/unified-api/). -* Complete Sentry [Protocol](https://develop.sentry.dev/sdk/event-payloads/) available. -* Docs and Migration is under review on this [PR](https://github.com/getsentry/sentry-docs/pull/2599) -* For all the breaking changes follow this [PR](https://github.com/getsentry/sentry-dart/pull/117), they'll be soon available on the Migration page. +- Sentry's [Unified API](https://develop.sentry.dev/sdk/unified-api/). +- Complete Sentry [Protocol](https://develop.sentry.dev/sdk/event-payloads/) available. +- Docs and Migration is under review on this [PR](https://github.com/getsentry/sentry-docs/pull/2599) +- For all the breaking changes follow this [PR](https://github.com/getsentry/sentry-dart/pull/117), they'll be soon available on the Migration page. Packages were released on [pubdev](https://pub.dev/packages/sentry) @@ -1740,85 +1745,85 @@ Until then, the stable SDK offered by Sentry is at version [3.0.1](https://githu ## 3.0.1 -* Add support for Contexts in Sentry events +- Add support for Contexts in Sentry events ## 3.0.0+1 -* `pubspec.yaml` and example code clean-up. +- `pubspec.yaml` and example code clean-up. ## 3.0.0 -* Support Web - * `SentryClient` from `package:sentry/sentry.dart` with conditional import - * `SentryBrowserClient` for web from `package:sentry/browser_client.dart` - * `SentryIOClient` for VM and Flutter from `package:sentry/io_client.dart` +- Support Web + - `SentryClient` from `package:sentry/sentry.dart` with conditional import + - `SentryBrowserClient` for web from `package:sentry/browser_client.dart` + - `SentryIOClient` for VM and Flutter from `package:sentry/io_client.dart` ## 2.3.1 -* Support non-standard port numbers and paths in DSN URL. +- Support non-standard port numbers and paths in DSN URL. ## 2.3.0 -* Add [breadcrumb](https://docs.sentry.io/development/sdk-dev/event-payloads/breadcrumbs/) support. +- Add [breadcrumb](https://docs.sentry.io/development/sdk-dev/event-payloads/breadcrumbs/) support. ## 2.2.0 -* Add a `stackFrameFilter` argument to `SentryClient`'s `capture` method (96be842). -* Clean-up code using pre-Dart 2 API (91c7706, b01ebf8). +- Add a `stackFrameFilter` argument to `SentryClient`'s `capture` method (96be842). +- Clean-up code using pre-Dart 2 API (91c7706, b01ebf8). ## 2.1.1 -* Defensively copy internal maps event attributes to +- Defensively copy internal maps event attributes to avoid shared mutable state (https://github.com/flutter/sentry/commit/044e4c1f43c2d199ed206e5529e2a630c90e4434) ## 2.1.0 -* Support DNS format without secret key. -* Remove dependency on `package:quiver`. -* The `clock` argument to `SentryClient` constructor _should_ now be +- Support DNS format without secret key. +- Remove dependency on `package:quiver`. +- The `clock` argument to `SentryClient` constructor _should_ now be `ClockProvider` (but still accepts `Clock` for backwards compatibility). ## 2.0.2 -* Add support for user context in Sentry events. +- Add support for user context in Sentry events. ## 2.0.1 -* Invert stack frames to be compatible with Sentry's default culprit detection. +- Invert stack frames to be compatible with Sentry's default culprit detection. ## 2.0.0 -* Fixed deprecation warnings for Dart 2 -* Refactored tests to work with Dart 2 +- Fixed deprecation warnings for Dart 2 +- Refactored tests to work with Dart 2 ## 1.0.0 -* first and last Dart 1-compatible release (we may fix bugs on a separate branch if there's demand) -* fix code for Dart 2 +- first and last Dart 1-compatible release (we may fix bugs on a separate branch if there's demand) +- fix code for Dart 2 ## 0.0.6 -* use UTC in the `timestamp` field +- use UTC in the `timestamp` field ## 0.0.5 -* remove sub-seconds from the timestamp +- remove sub-seconds from the timestamp ## 0.0.4 -* parse and report async gaps in stack traces +- parse and report async gaps in stack traces ## 0.0.3 -* environment attributes -* auto-generate event_id and timestamp for events +- environment attributes +- auto-generate event_id and timestamp for events ## 0.0.2 -* parse and report stack traces -* use x-sentry-error HTTP response header -* gzip outgoing payloads by default +- parse and report stack traces +- use x-sentry-error HTTP response header +- gzip outgoing payloads by default ## 0.0.1 -* basic ability to send exception reports to Sentry.io +- basic ability to send exception reports to Sentry.io diff --git a/flutter/android/build.gradle b/flutter/android/build.gradle index 6014fa1117..1fa9b4f6c9 100644 --- a/flutter/android/build.gradle +++ b/flutter/android/build.gradle @@ -22,7 +22,7 @@ apply plugin: 'com.android.library' apply plugin: 'kotlin-android' android { - compileSdkVersion 33 + compileSdkVersion 34 // Conditional for compatibility with AGP <4.2. if (project.android.hasProperty("namespace")) { diff --git a/flutter/example/android/app/build.gradle b/flutter/example/android/app/build.gradle index ac4557e2cd..e9ac4161a5 100644 --- a/flutter/example/android/app/build.gradle +++ b/flutter/example/android/app/build.gradle @@ -40,7 +40,7 @@ android { languageVersion = "1.4" } - compileSdkVersion 33 + compileSdkVersion 34 sourceSets { main.java.srcDirs += 'src/main/kotlin' @@ -49,7 +49,7 @@ android { defaultConfig { applicationId "io.sentry.samples.flutter" minSdkVersion flutter.minSdkVersion - targetSdkVersion 33 + targetSdkVersion 34 versionCode flutterVersionCode.toInteger() versionName flutterVersionName From 6daa837b45789cb21c8bb0075c58ad6f5e5e83b6 Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Wed, 10 Apr 2024 14:02:54 +0200 Subject: [PATCH 135/237] fix: ci deps updater (#1968) * Change subdir * Debug this in PR * Revert push --- flutter/scripts/generate-cocoa-bindings.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flutter/scripts/generate-cocoa-bindings.sh b/flutter/scripts/generate-cocoa-bindings.sh index 3381089df5..0b653d0df1 100755 --- a/flutter/scripts/generate-cocoa-bindings.sh +++ b/flutter/scripts/generate-cocoa-bindings.sh @@ -29,7 +29,7 @@ temp="cocoa_bindings_temp" rm -rf $temp mkdir -p $temp curl -Lv https://github.com/getsentry/sentry-cocoa/releases/download/$cocoa_version/Sentry.xcframework.zip -o $temp/Sentry.xcframework.zip -subdir="Carthage/Build/Sentry.xcframework/macos-arm64_x86_64/Sentry.framework" +subdir="Sentry.xcframework/macos-arm64_x86_64/Sentry.framework" unzip -q $temp/Sentry.xcframework.zip "$subdir/*" -d $temp mv "$temp/$subdir" $temp/Sentry.framework From e82709a24504959ed7fe9b79ba3f038a31b6c5db Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Fri, 12 Apr 2024 10:30:48 +0200 Subject: [PATCH 136/237] deps: update package_info_plus range to include 7 (#1984) * Update range to include 7 * Update CHANGELOG --- CHANGELOG.md | 1 + flutter/pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c81d5170e7..0a3f6fba96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ ### Dependencies +- Expand dependency range of `package_info_plus` to include major version 7 ([#1984](https://github.com/getsentry/sentry-dart/pull/1984)) - Bump Android SDK from v7.6.0 to v7.8.0 ([#1977](https://github.com/getsentry/sentry-dart/pull/1977)) - [changelog](https://github.com/getsentry/sentry-java/blob/main/CHANGELOG.md#780) - [diff](https://github.com/getsentry/sentry-java/compare/7.6.0...7.8.0) diff --git a/flutter/pubspec.yaml b/flutter/pubspec.yaml index 30ccca3dcc..55a23a6fa4 100644 --- a/flutter/pubspec.yaml +++ b/flutter/pubspec.yaml @@ -16,7 +16,7 @@ dependencies: flutter_web_plugins: sdk: flutter sentry: 7.19.0 - package_info_plus: '>=1.0.0 <7.0.0' + package_info_plus: '>=1.0.0 <8.0.0' meta: ^1.3.0 ffi: ^2.0.0 From d8f5abb1c680cf28aa56bc1fcb7fd38b1d711449 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20Andra=C5=A1ec?= Date: Mon, 15 Apr 2024 10:03:18 +0000 Subject: [PATCH 137/237] Add platforms in `pubspec.yaml` for `pub.dev` (#1975) --- dart/pubspec.yaml | 8 ++++++++ dio/pubspec.yaml | 8 ++++++++ drift/pubspec.yaml | 8 ++++++++ file/pubspec.yaml | 7 +++++++ flutter/pubspec.yaml | 8 ++++++++ hive/pubspec.yaml | 8 ++++++++ isar/pubspec.yaml | 8 ++++++++ logging/pubspec.yaml | 8 ++++++++ sqflite/pubspec.yaml | 5 +++++ 9 files changed, 68 insertions(+) diff --git a/dart/pubspec.yaml b/dart/pubspec.yaml index d14d8bacc3..87dd6ef93c 100644 --- a/dart/pubspec.yaml +++ b/dart/pubspec.yaml @@ -11,6 +11,14 @@ documentation: https://docs.sentry.io/platforms/dart/ environment: sdk: '>=2.17.0 <4.0.0' +platforms: + android: + ios: + macos: + linux: + windows: + web: + dependencies: http: '>=0.13.0 <2.0.0' meta: ^1.3.0 diff --git a/dio/pubspec.yaml b/dio/pubspec.yaml index aade33f1f0..86fde090e9 100644 --- a/dio/pubspec.yaml +++ b/dio/pubspec.yaml @@ -9,6 +9,14 @@ documentation: https://docs.sentry.io/platforms/dart/integrations/dio/ environment: sdk: '>=2.17.0 <4.0.0' +platforms: + android: + ios: + macos: + linux: + windows: + web: + dependencies: dio: ^5.0.0 sentry: 7.19.0 diff --git a/drift/pubspec.yaml b/drift/pubspec.yaml index c52e2937f1..d1c44549e9 100644 --- a/drift/pubspec.yaml +++ b/drift/pubspec.yaml @@ -8,6 +8,14 @@ issue_tracker: https://github.com/getsentry/sentry-dart/issues environment: sdk: '>=2.17.0 <4.0.0' +platforms: + android: + ios: + macos: + linux: + windows: + web: + dependencies: sentry: 7.19.0 meta: ^1.3.0 diff --git a/file/pubspec.yaml b/file/pubspec.yaml index ba1a2fc4e2..4c06119cd7 100644 --- a/file/pubspec.yaml +++ b/file/pubspec.yaml @@ -9,6 +9,13 @@ documentation: https://docs.sentry.io/platforms/dart/configuration/integrations/ environment: sdk: '>=2.19.0 <4.0.0' +platforms: + android: + ios: + macos: + linux: + windows: + dependencies: sentry: 7.19.0 meta: ^1.3.0 diff --git a/flutter/pubspec.yaml b/flutter/pubspec.yaml index 55a23a6fa4..acf38d8f06 100644 --- a/flutter/pubspec.yaml +++ b/flutter/pubspec.yaml @@ -10,6 +10,14 @@ environment: sdk: '>=2.17.0 <4.0.0' flutter: '>=3.0.0' +platforms: + android: + ios: + macos: + linux: + windows: + web: + dependencies: flutter: sdk: flutter diff --git a/hive/pubspec.yaml b/hive/pubspec.yaml index 86d39fcf91..d2bd685a39 100644 --- a/hive/pubspec.yaml +++ b/hive/pubspec.yaml @@ -8,6 +8,14 @@ issue_tracker: https://github.com/getsentry/sentry-dart/issues environment: sdk: '>=2.17.0 <4.0.0' +platforms: + android: + ios: + macos: + linux: + windows: + web: + dependencies: sentry: 7.19.0 hive: ^2.2.3 diff --git a/isar/pubspec.yaml b/isar/pubspec.yaml index f87180882f..66bde801bd 100644 --- a/isar/pubspec.yaml +++ b/isar/pubspec.yaml @@ -9,6 +9,14 @@ environment: sdk: '>=2.17.0 <4.0.0' flutter: '>=3.3.0' +platforms: + android: + ios: + macos: + linux: + windows: + web: + dependencies: isar: ^3.1.0 isar_flutter_libs: ^3.1.0 # contains Isar Core diff --git a/logging/pubspec.yaml b/logging/pubspec.yaml index f7a0384d2e..4bbe3b14c6 100644 --- a/logging/pubspec.yaml +++ b/logging/pubspec.yaml @@ -9,6 +9,14 @@ documentation: https://docs.sentry.io/platforms/dart/integrations/logging/ environment: sdk: '>=2.17.0 <4.0.0' +platforms: + android: + ios: + macos: + linux: + windows: + web: + dependencies: logging: ^1.0.0 sentry: 7.19.0 diff --git a/sqflite/pubspec.yaml b/sqflite/pubspec.yaml index 154cfa3d10..0104813e5e 100644 --- a/sqflite/pubspec.yaml +++ b/sqflite/pubspec.yaml @@ -9,6 +9,11 @@ environment: sdk: '>=2.17.0 <4.0.0' flutter: '>=3.3.0' # matching sqflite +platforms: + android: + ios: + macos: + dependencies: sentry: 7.19.0 sqflite: ^2.0.0 From 2189f9bc2dab6d6d448db23544da8906d72cd2b3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 16 Apr 2024 13:29:12 +0200 Subject: [PATCH 138/237] build(deps): bump gradle/gradle-build-action from 3.2.0 to 3.3.0 (#1991) Bumps [gradle/gradle-build-action](https://github.com/gradle/gradle-build-action) from 3.2.0 to 3.3.0. - [Release notes](https://github.com/gradle/gradle-build-action/releases) - [Commits](https://github.com/gradle/gradle-build-action/compare/fe59895742b4f984530980e4f693943577526b61...8baac4c8ef753599f92eeb509c246d09d6250fa6) --- updated-dependencies: - dependency-name: gradle/gradle-build-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/flutter_test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/flutter_test.yml b/.github/workflows/flutter_test.yml index c2423ce3db..e6d845bb72 100644 --- a/.github/workflows/flutter_test.yml +++ b/.github/workflows/flutter_test.yml @@ -54,7 +54,7 @@ jobs: run: flutter pub get - name: Gradle cache - uses: gradle/gradle-build-action@fe59895742b4f984530980e4f693943577526b61 + uses: gradle/gradle-build-action@8baac4c8ef753599f92eeb509c246d09d6250fa6 - name: AVD cache uses: actions/cache@v4 From 2b35b2ad53594ad1ae75ac9261b2e61aa07b8bfd Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 16 Apr 2024 13:31:32 +0200 Subject: [PATCH 139/237] chore: update scripts/update-symbol-collector.sh to 1.17.0 (#1988) Co-authored-by: GitHub --- .../flutter_symbol_collector/lib/src/symbol_collector_cli.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/flutter_symbol_collector/lib/src/symbol_collector_cli.dart b/scripts/flutter_symbol_collector/lib/src/symbol_collector_cli.dart index e4ab2d8906..4308921cdc 100644 --- a/scripts/flutter_symbol_collector/lib/src/symbol_collector_cli.dart +++ b/scripts/flutter_symbol_collector/lib/src/symbol_collector_cli.dart @@ -19,7 +19,7 @@ class SymbolCollectorCli { // https://github.com/getsentry/symbol-collector/releases @internal - static const version = '1.16.0'; + static const version = '1.17.0'; @internal late final String cli; From 1eb35437c54c3889fa34146c995c1353fb39bffd Mon Sep 17 00:00:00 2001 From: getsentry-bot Date: Tue, 16 Apr 2024 15:03:49 +0000 Subject: [PATCH 140/237] release: 7.20.0 --- CHANGELOG.md | 2 +- dart/lib/src/version.dart | 2 +- dart/pubspec.yaml | 2 +- dio/lib/src/version.dart | 2 +- dio/pubspec.yaml | 4 ++-- drift/lib/src/version.dart | 2 +- drift/pubspec.yaml | 4 ++-- file/lib/src/version.dart | 2 +- file/pubspec.yaml | 4 ++-- flutter/example/pubspec.yaml | 2 +- flutter/lib/src/version.dart | 2 +- flutter/pubspec.yaml | 4 ++-- hive/lib/src/version.dart | 2 +- hive/pubspec.yaml | 4 ++-- isar/lib/src/version.dart | 2 +- isar/pubspec.yaml | 4 ++-- logging/lib/src/version.dart | 2 +- logging/pubspec.yaml | 4 ++-- sqflite/lib/src/version.dart | 2 +- sqflite/pubspec.yaml | 4 ++-- 20 files changed, 28 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a3f6fba96..7dbc1dd7d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## Unreleased +## 7.20.0 ### Build diff --git a/dart/lib/src/version.dart b/dart/lib/src/version.dart index 8f035ff451..7e4666bc06 100644 --- a/dart/lib/src/version.dart +++ b/dart/lib/src/version.dart @@ -9,7 +9,7 @@ library version; /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.19.0'; +const String sdkVersion = '7.20.0'; String sdkName(bool isWeb) => isWeb ? _browserSdkName : _ioSdkName; diff --git a/dart/pubspec.yaml b/dart/pubspec.yaml index 87dd6ef93c..4294d86144 100644 --- a/dart/pubspec.yaml +++ b/dart/pubspec.yaml @@ -1,5 +1,5 @@ name: sentry -version: 7.19.0 +version: 7.20.0 description: > A crash reporting library for Dart that sends crash reports to Sentry.io. This library supports Dart VM and Web. For Flutter consider sentry_flutter instead. diff --git a/dio/lib/src/version.dart b/dio/lib/src/version.dart index 0a1978233f..396477f00f 100644 --- a/dio/lib/src/version.dart +++ b/dio/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.19.0'; +const String sdkVersion = '7.20.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_dio'; diff --git a/dio/pubspec.yaml b/dio/pubspec.yaml index 86fde090e9..62d1d90e77 100644 --- a/dio/pubspec.yaml +++ b/dio/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_dio description: An integration which adds support for performance tracing for the Dio package. -version: 7.19.0 +version: 7.20.0 homepage: https://docs.sentry.io/platforms/dart/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -19,7 +19,7 @@ platforms: dependencies: dio: ^5.0.0 - sentry: 7.19.0 + sentry: 7.20.0 dev_dependencies: meta: ^1.3.0 diff --git a/drift/lib/src/version.dart b/drift/lib/src/version.dart index 53bd1f6467..baed0fdd1b 100644 --- a/drift/lib/src/version.dart +++ b/drift/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.19.0'; +const String sdkVersion = '7.20.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_drift'; diff --git a/drift/pubspec.yaml b/drift/pubspec.yaml index d1c44549e9..9d93dc877f 100644 --- a/drift/pubspec.yaml +++ b/drift/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_drift description: An integration which adds support for performance tracing for the drift package. -version: 7.19.0 +version: 7.20.0 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -17,7 +17,7 @@ platforms: web: dependencies: - sentry: 7.19.0 + sentry: 7.20.0 meta: ^1.3.0 drift: ^2.13.0 diff --git a/file/lib/src/version.dart b/file/lib/src/version.dart index e24a6de0bc..ddc904ca24 100644 --- a/file/lib/src/version.dart +++ b/file/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.19.0'; +const String sdkVersion = '7.20.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_file'; diff --git a/file/pubspec.yaml b/file/pubspec.yaml index 4c06119cd7..3d054c5090 100644 --- a/file/pubspec.yaml +++ b/file/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_file description: An integration which adds support for performance tracing for dart.io.File. -version: 7.19.0 +version: 7.20.0 homepage: https://docs.sentry.io/platforms/dart/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -17,7 +17,7 @@ platforms: windows: dependencies: - sentry: 7.19.0 + sentry: 7.20.0 meta: ^1.3.0 dev_dependencies: diff --git a/flutter/example/pubspec.yaml b/flutter/example/pubspec.yaml index dd565be890..80bb0a3ff5 100644 --- a/flutter/example/pubspec.yaml +++ b/flutter/example/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_flutter_example description: Demonstrates how to use the sentry_flutter plugin. -version: 7.19.0 +version: 7.20.0 publish_to: 'none' # Remove this line if you wish to publish to pub.dev diff --git a/flutter/lib/src/version.dart b/flutter/lib/src/version.dart index 89821cce76..e9f6c225d1 100644 --- a/flutter/lib/src/version.dart +++ b/flutter/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.19.0'; +const String sdkVersion = '7.20.0'; /// The default SDK name reported to Sentry.io in the submitted events. const String sdkName = 'sentry.dart.flutter'; diff --git a/flutter/pubspec.yaml b/flutter/pubspec.yaml index acf38d8f06..34f6a7713d 100644 --- a/flutter/pubspec.yaml +++ b/flutter/pubspec.yaml @@ -1,5 +1,5 @@ name: sentry_flutter -version: 7.19.0 +version: 7.20.0 description: Sentry SDK for Flutter. This package aims to support different Flutter targets by relying on the many platforms supported by Sentry with native SDKs. homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart @@ -23,7 +23,7 @@ dependencies: sdk: flutter flutter_web_plugins: sdk: flutter - sentry: 7.19.0 + sentry: 7.20.0 package_info_plus: '>=1.0.0 <8.0.0' meta: ^1.3.0 ffi: ^2.0.0 diff --git a/hive/lib/src/version.dart b/hive/lib/src/version.dart index 9ae5c45c00..d0079c0f70 100644 --- a/hive/lib/src/version.dart +++ b/hive/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.19.0'; +const String sdkVersion = '7.20.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_hive'; diff --git a/hive/pubspec.yaml b/hive/pubspec.yaml index d2bd685a39..161e7796d9 100644 --- a/hive/pubspec.yaml +++ b/hive/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_hive description: An integration which adds support for performance tracing for the hive package. -version: 7.19.0 +version: 7.20.0 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -17,7 +17,7 @@ platforms: web: dependencies: - sentry: 7.19.0 + sentry: 7.20.0 hive: ^2.2.3 meta: ^1.3.0 diff --git a/isar/lib/src/version.dart b/isar/lib/src/version.dart index e6cd47c793..a61930b879 100644 --- a/isar/lib/src/version.dart +++ b/isar/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.19.0'; +const String sdkVersion = '7.20.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_isar'; diff --git a/isar/pubspec.yaml b/isar/pubspec.yaml index 66bde801bd..53aa85a5f8 100644 --- a/isar/pubspec.yaml +++ b/isar/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_isar description: An integration which adds support for performance tracing for the isar package. -version: 7.19.0 +version: 7.20.0 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -20,7 +20,7 @@ platforms: dependencies: isar: ^3.1.0 isar_flutter_libs: ^3.1.0 # contains Isar Core - sentry: 7.19.0 + sentry: 7.20.0 meta: ^1.3.0 path: ^1.8.3 diff --git a/logging/lib/src/version.dart b/logging/lib/src/version.dart index 023c1a52ff..fbbea58108 100644 --- a/logging/lib/src/version.dart +++ b/logging/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.19.0'; +const String sdkVersion = '7.20.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_logging'; diff --git a/logging/pubspec.yaml b/logging/pubspec.yaml index 4bbe3b14c6..04d4232f8f 100644 --- a/logging/pubspec.yaml +++ b/logging/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_logging description: An integration which adds support for recording log from the logging package. -version: 7.19.0 +version: 7.20.0 homepage: https://docs.sentry.io/platforms/dart/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -19,7 +19,7 @@ platforms: dependencies: logging: ^1.0.0 - sentry: 7.19.0 + sentry: 7.20.0 dev_dependencies: lints: ^3.0.0 diff --git a/sqflite/lib/src/version.dart b/sqflite/lib/src/version.dart index cc20b6cd9b..5b98e5939e 100644 --- a/sqflite/lib/src/version.dart +++ b/sqflite/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.19.0'; +const String sdkVersion = '7.20.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_sqflite'; diff --git a/sqflite/pubspec.yaml b/sqflite/pubspec.yaml index 0104813e5e..e8d317c214 100644 --- a/sqflite/pubspec.yaml +++ b/sqflite/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_sqflite description: An integration which adds support for performance tracing for the sqflite package. -version: 7.19.0 +version: 7.20.0 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -15,7 +15,7 @@ platforms: macos: dependencies: - sentry: 7.19.0 + sentry: 7.20.0 sqflite: ^2.0.0 sqflite_common: ^2.0.0 meta: ^1.3.0 From 82a93a737c95db9df421bfd140df14cf26591b5e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Apr 2024 13:09:35 +0200 Subject: [PATCH 141/237] build(deps): bump dart-lang/setup-dart from 1.6.2 to 1.6.4 (#1990) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.6.2 to 1.6.4. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/fedb1266e91cf51be2fdb382869461a434b920a3...f0ead981b4d9a35b37f30d36160575d60931ec30) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor --- .github/workflows/analyze.yml | 2 +- .github/workflows/dart.yml | 2 +- .github/workflows/diagrams.yml | 2 +- .github/workflows/dio.yml | 2 +- .github/workflows/e2e_dart.yml | 2 +- .github/workflows/file.yml | 2 +- .github/workflows/flutter-symbols.yml | 4 ++-- .github/workflows/format-and-fix.yml | 2 +- .github/workflows/hive.yml | 2 +- .github/workflows/logging.yml | 2 +- 10 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/analyze.yml b/.github/workflows/analyze.yml index b9988c0b92..bf31098e20 100644 --- a/.github/workflows/analyze.yml +++ b/.github/workflows/analyze.yml @@ -32,7 +32,7 @@ jobs: working-directory: ${{ inputs.package }} steps: - uses: actions/checkout@v4 - - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 # pin@v1 + - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 # pin@v1 if: ${{ inputs.sdk == 'dart' }} - uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 # pin@v2.16.0 if: ${{ inputs.sdk == 'flutter' }} diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml index 46a82a54af..897a4ad846 100644 --- a/.github/workflows/dart.yml +++ b/.github/workflows/dart.yml @@ -39,7 +39,7 @@ jobs: - os: macos-latest sdk: beta steps: - - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 # pin@v1 + - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 # pin@v1 with: sdk: ${{ matrix.sdk }} - uses: actions/checkout@v4 diff --git a/.github/workflows/diagrams.yml b/.github/workflows/diagrams.yml index a7671824cf..f78d5bbb67 100644 --- a/.github/workflows/diagrams.yml +++ b/.github/workflows/diagrams.yml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-latest name: "Create class diagrams of all packages" steps: - - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 # pin@v1 + - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 # pin@v1 with: sdk: stable diff --git a/.github/workflows/dio.yml b/.github/workflows/dio.yml index 7da74c1017..88abdf1ad5 100644 --- a/.github/workflows/dio.yml +++ b/.github/workflows/dio.yml @@ -40,7 +40,7 @@ jobs: - os: macos-latest sdk: beta steps: - - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 # pin@v1 + - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 # pin@v1 with: sdk: ${{ matrix.sdk }} - uses: actions/checkout@v4 diff --git a/.github/workflows/e2e_dart.yml b/.github/workflows/e2e_dart.yml index 8fb62ce108..00f52cc0f3 100644 --- a/.github/workflows/e2e_dart.yml +++ b/.github/workflows/e2e_dart.yml @@ -37,7 +37,7 @@ jobs: matrix: sdk: [stable, beta] steps: - - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 # pin@v1 + - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 # pin@v1 with: sdk: ${{ matrix.sdk }} - uses: actions/checkout@v4 diff --git a/.github/workflows/file.yml b/.github/workflows/file.yml index 6e677f59bb..f883957a2b 100644 --- a/.github/workflows/file.yml +++ b/.github/workflows/file.yml @@ -41,7 +41,7 @@ jobs: - os: macos-latest sdk: beta steps: - - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 # pin@v1 + - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 # pin@v1 with: sdk: ${{ matrix.sdk }} - uses: actions/checkout@v4 diff --git a/.github/workflows/flutter-symbols.yml b/.github/workflows/flutter-symbols.yml index e9fccdbbbc..5eb867b755 100644 --- a/.github/workflows/flutter-symbols.yml +++ b/.github/workflows/flutter-symbols.yml @@ -21,7 +21,7 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 # pin@v1 + - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 # pin@v1 - run: dart pub get @@ -33,7 +33,7 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 # pin@v1 + - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 # pin@v1 - run: dart pub get diff --git a/.github/workflows/format-and-fix.yml b/.github/workflows/format-and-fix.yml index 86711b626f..8d9ab178f5 100644 --- a/.github/workflows/format-and-fix.yml +++ b/.github/workflows/format-and-fix.yml @@ -30,7 +30,7 @@ jobs: working-directory: ${{ matrix.package.name }} steps: - uses: actions/checkout@v4 - - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 # pin@v1 + - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 # pin@v1 if: ${{ matrix.package.sdk == 'dart' }} - uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 # pin@v2.16.0 if: ${{ matrix.package.sdk == 'flutter' }} diff --git a/.github/workflows/hive.yml b/.github/workflows/hive.yml index be2fc02951..0131c0b584 100644 --- a/.github/workflows/hive.yml +++ b/.github/workflows/hive.yml @@ -40,7 +40,7 @@ jobs: - os: macos-latest sdk: beta steps: - - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 # pin@v1 + - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 # pin@v1 with: sdk: ${{ matrix.sdk }} - uses: actions/checkout@v4 diff --git a/.github/workflows/logging.yml b/.github/workflows/logging.yml index b1a692e044..3058fa2a6e 100644 --- a/.github/workflows/logging.yml +++ b/.github/workflows/logging.yml @@ -40,7 +40,7 @@ jobs: - os: macos-latest sdk: beta steps: - - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 # pin@v1 + - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 # pin@v1 with: sdk: ${{ matrix.sdk }} - uses: actions/checkout@v4 From 8f88a49d613434f898cd280880fbd122370dfffa Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Fri, 19 Apr 2024 12:45:46 +0200 Subject: [PATCH 142/237] Merge v8 into main (#1997) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Mark exceptions not handled by user as `handled: false` (#1535) * Refrain from overwriting the span status for unfinished spans (#1577) * update changelog * Do not leak extensions of external classes (#1576) * Make `hint` non-nullable in `BeforeSendCallback`, `BeforeBreadcrumbCall` and `EventProcessor` (#1574) * Load Device Contexts from Sentry Java (#1616) * Set ip_address to {{auto}} by default, even if sendDefaultPII is disabled (#1665) * chore: merge main into v8 branch (#1841) * ci: update actions (#1617) * Add tests for the Android and iOS plugin (#1587) * Normalize `data` properties of `SentryUser` and `Breadcrumb` before sending over method channel (#1591) * chore(deps): update Cocoa SDK to v8.11.0 (#1626) Co-authored-by: GitHub * Tracing without performance (#1621) * implement propagationContext * remove sampled and parentSpanId for now * update changelog * fix build error * create new propagation context on startTransaction if tracing is disabled * remove print * propagate trace for http requests * add tracing client test * fix tests * format * fix compile * tests * fix analysis score * fix analysis score * fix compilation * fix score * fix score * fix score * fix score * update tests * [starfish] add attributes to db spans data (#1629) * add db attibutes to spans * change variable names * update changelog * update changelog * update tests * update imports * update tests * remove unused import * couple dbName to db instance * format * use path pub * don't set dbName to null when db close() is called * [starfish] add http.request.method attribute to http spans (#1633) * add http.request.method to http spans * update changelog * Fix Android & iOS CI issues (#1627) * Disable scope sync for cloned scopes (#1628) * chore: update flutter/scripts/update-android.sh to 6.29.0 (#1630) Co-authored-by: GitHub * Discard empty stack frames (#1625) * Introduce workflow dispatch action for`format` & `fix --apply` (#1575) * feat/refactor: add cocoa FFI binding (#1631) * refactor: move native code to its own directory (#1638) * Log SDK errors to the console if the log level is `fatal` even if `debug` is disabled (#1635) * Fix autoPerformanceTracingEnabled flag in andorid plugin (#1640) * Add Sampling Decision to Trace Envelope Header (#1639) * add sampled flag * fmt * update changelog * redo fmt * fix tests * chore: update metrics/flutter.properties to 3.13.3 (#1632) Co-authored-by: GitHub * fix: add missing FFI depdendency (#1642) * release: 7.10.1 * ci: macos integration test (#1645) * fix: generated cocoa bindings (#1648) * Update uuid (#1647) Co-authored-by: Ivan Dlugos <6349682+vaind@users.noreply.github.com> * chore(deps): update Cocoa SDK to v8.12.0 (#1650) Co-authored-by: GitHub * Breadcrumbs for file I/O operations (#1649) * ci: don't run CI on markdown updates (#1651) * chore(deps): update Flutter SDK (metrics) to v3.13.6 (#1659) * chore: update metrics/flutter.properties to 3.13.6 * Update flutter.properties --------- Co-authored-by: GitHub Co-authored-by: Stefano * chore: update flutter/scripts/update-android.sh to 6.30.0 (#1660) * chore: update flutter/scripts/update-cocoa.sh to 8.13.0 (#1655) * Generate class diagrams (#1646) * Rename `options.devMode` to `options.automatedTestMode` (#1664) * chore: update flutter/scripts/update-cocoa.sh to 8.13.1 (#1677) Co-authored-by: GitHub * chore: update flutter/scripts/update-android.sh to 6.31.0 (#1676) * chore: update metrics/flutter.properties to 3.13.7 (#1674) Co-authored-by: GitHub * Add dependabot (#1670) * Bump codecov/codecov-action from 3.1.1 to 3.1.4 (#1680) * chore: update flutter/scripts/update-android.sh to 6.32.0 (#1688) Co-authored-by: GitHub * chore(deps): update Cocoa SDK to v8.14.2 (#1691) * chore: update flutter/scripts/update-cocoa.sh to 8.14.2 --------- Co-authored-by: GitHub Co-authored-by: GIancarlo Buenaflor * chore: update changelog (#1699) * Update changelog * release: 7.11.0 * Bump lints from 2.1.1 to 3.0.0 in /sqflite (#1697) Bumps [lints](https://github.com/dart-lang/lints) from 2.1.1 to 3.0.0. - [Release notes](https://github.com/dart-lang/lints/releases) - [Changelog](https://github.com/dart-lang/lints/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/lints/compare/v2.1.1...v3.0.0) --- updated-dependencies: - dependency-name: lints dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump lints from 2.1.1 to 3.0.0 in /logging (#1696) Bumps [lints](https://github.com/dart-lang/lints) from 2.1.1 to 3.0.0. - [Release notes](https://github.com/dart-lang/lints/releases) - [Changelog](https://github.com/dart-lang/lints/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/lints/compare/v2.1.1...v3.0.0) --- updated-dependencies: - dependency-name: lints dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump lints from 2.1.1 to 3.0.0 in /file (#1694) Bumps [lints](https://github.com/dart-lang/lints) from 2.1.1 to 3.0.0. - [Release notes](https://github.com/dart-lang/lints/releases) - [Changelog](https://github.com/dart-lang/lints/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/lints/compare/v2.1.1...v3.0.0) --- updated-dependencies: - dependency-name: lints dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump lints from 2.1.1 to 3.0.0 in /dio (#1693) Bumps [lints](https://github.com/dart-lang/lints) from 2.1.1 to 3.0.0. - [Release notes](https://github.com/dart-lang/lints/releases) - [Changelog](https://github.com/dart-lang/lints/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/lints/compare/v2.1.1...v3.0.0) --- updated-dependencies: - dependency-name: lints dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * feat: profiling for iOS/macOS (#1611) Co-authored-by: Bruno Garcia Co-authored-by: Denis Andrašec Co-authored-by: Stefano * chore: update metrics/flutter.properties to 3.13.9 (#1702) * chore: log warning if both tracesSampleRate and tracesSampler are set (#1701) * Log warning if both tracesSampleRate and tracesSampler are set * Update CHANGELOG * Update log * Update CHANGELOG * chore: flutter symbol collector CLI tool (#1673) * release: 7.12.0 * Add `SentryNavigatorObserver` current route to `event.app.contexts.viewNames` (#1545) * fix: coverage not ignoring generated binding.dart (#1707) * Remove coverage for binding.dart * Breadcrumbs for database operations (#1656) * Bump actions/checkout from 3 to 4 (#1683) Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump ScaCap/action-ktlint from 1.7.1 to 1.8.0 (#1681) Bumps [ScaCap/action-ktlint](https://github.com/scacap/action-ktlint) from 1.7.1 to 1.8.0. - [Release notes](https://github.com/scacap/action-ktlint/releases) - [Commits](https://github.com/scacap/action-ktlint/compare/2cf245b99bc91f73bc4c96a3d9d57bb5da3533ae...0ff81efa49425bd0df46caabd8005aafdc8f2cf2) --- updated-dependencies: - dependency-name: ScaCap/action-ktlint dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump styfle/cancel-workflow-action from 0.11.0 to 0.12.0 (#1682) Bumps [styfle/cancel-workflow-action](https://github.com/styfle/cancel-workflow-action) from 0.11.0 to 0.12.0. - [Release notes](https://github.com/styfle/cancel-workflow-action/releases) - [Commits](https://github.com/styfle/cancel-workflow-action/compare/b173b6ec0100793626c2d9e6b90435061f4fc3e5...01ce38bf961b4e243a6342cbade0dbc8ba3f0432) --- updated-dependencies: - dependency-name: styfle/cancel-workflow-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Stefano Co-authored-by: Giancarlo Buenaflor * Bump dart-lang/setup-dart from 1.3.0 to 1.6.0 (#1692) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.3.0 to 1.6.0. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/6a218f2413a3e78e9087f638a238f6b40893203d...b64355ae6ca0b5d484f0106a033dd1388965d06d) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor * chore: update flutter/scripts/update-android.sh to 6.33.0 (#1710) Co-authored-by: GitHub * build(deps): bump subosito/flutter-action from 2.10.0 to 2.12.0 (#1711) Bumps [subosito/flutter-action](https://github.com/subosito/flutter-action) from 2.10.0 to 2.12.0. - [Release notes](https://github.com/subosito/flutter-action/releases) - [Commits](https://github.com/subosito/flutter-action/compare/48cafc24713cca54bbe03cdc3a423187d413aafa...2783a3f08e1baf891508463f8c6653c258246225) --- updated-dependencies: - dependency-name: subosito/flutter-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Add `attachScreenshotOnlyWhenResumed` to options (#1700) * chore: update flutter/scripts/update-android.sh to 6.33.1 (#1713) Co-authored-by: GitHub * chore: update flutter/scripts/update-cocoa.sh to 8.15.0 (#1712) Co-authored-by: GitHub * chore: update flutter/scripts/update-cocoa.sh to 8.15.1 (#1714) Co-authored-by: GitHub * fix: unsupported types with expando (#1690) * Support string, int, double and bool as throwable for expando * Rename the test file and move it to utils folder{ * Remvoe ffi import * Update changelog * Try other url for dio pubspec doc url * Change doc url of logging pubspec * Remove unnecessary code * Update naming * Rename * chore: update flutter/scripts/update-cocoa.sh to 8.15.2 (#1717) Co-authored-by: GitHub * Parse message field in `PlatformException.message` (#1716) * Parse message field * changelog * Update CHANGELOG.md * Bump natiginfo/action-detekt-all from 1.21.0 to 1.23.1 (#1684) * Bump natiginfo/action-detekt-all from 1.21.0 to 1.23.1 Bumps [natiginfo/action-detekt-all](https://github.com/natiginfo/action-detekt-all) from 1.21.0 to 1.23.1. - [Release notes](https://github.com/natiginfo/action-detekt-all/releases) - [Commits](https://github.com/natiginfo/action-detekt-all/compare/e01de6ff0eef7c24131e8a133bf598cfac6ceeab...be3c18799c7c392b2f41a674beed9ced7ae2f21b) --- updated-dependencies: - dependency-name: natiginfo/action-detekt-all dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * fix braces * Add missing trailing comma --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor * build(deps): bump natiginfo/action-detekt-all from 1.23.1 to 1.23.3 (#1722) Bumps [natiginfo/action-detekt-all](https://github.com/natiginfo/action-detekt-all) from 1.23.1 to 1.23.3. - [Release notes](https://github.com/natiginfo/action-detekt-all/releases) - [Commits](https://github.com/natiginfo/action-detekt-all/compare/be3c18799c7c392b2f41a674beed9ced7ae2f21b...68eb02dd9f2c2686d5026f5957756064424261a9) --- updated-dependencies: - dependency-name: natiginfo/action-detekt-all dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Remove renderer on Dart:io platforms (#1723) * Remove renderer on dart:io platforms * Tests + changelog * Update CHANGELOG.md * Fix tests * fix more tests * feat: drift apm (#1709) * draft impl * improve code * Add open span * Refactor to extend lazy database * Update * SentryTransactionExecutor * Implement tracing batch and transactions * Update tests * update changelog * Formatting * Update workflows * Update deps * Fix analyze issues * Format * Add example * Update descriptions * Fix deps * Update run commands * Update workflow * Update example * Update workflow * Format * Fix dart analyze * Try changing deps * Add to craft * Change to flutter test * Revert flutter test mock * change dir manually * download and extract sqlite.dll for windows * Try downloading sqlite3 * set up dart * fix path to file * use pub get * Use flutter pub get * fix * skip windows test * fix analyze * fix drift.yml * format * Remove redundant test * Remove debug print * update trace origin * Improvements * Improvements * Add to flutter example * fix: setting the correct locale to contexts with navigatorKey (#1724) * Add localization with navigatorKey * Update CHANGELOG * Update tests * Update tests * Format * Remove unused import * Apply review improvements * Update CHANGELOG * APM for hive (#1672) * setup sentry hive library * Add SentryBox with first test * test added spans * Add sentry hive impl * introduce base box to avoid duplication * implement lazy box test * expose sentry hive and updata documentation * add hive to flutter example app * test throwing in base_box, cleanup * test lazy box error cases * test sentry hive impl failures * run fix & format * fix test failure race condition * add hive workflow, update other workflows * add changelog entry * remove path+provider from dev_dependencies * add coverage dev dependency * fix deprecation warnings * fix changelog * move span wrapping on own class to avoid duplication * add sentry box collection * test added spans, fix imports * test throwing code * fix changelog * change dbSystem value * change db system * remove unneccessary async & await * Fix analyze * Formatting * Add changelog symlink * Ignore hive coverage * Create symlink for dartdoc_options --------- Co-authored-by: Giancarlo Buenaflor * release: 7.13.0 * Fixes release of drift & hive (#1729) * Add integrations * Readd changelog * Add drift and hive to bump versions * Formatting and analyze * Update CHANGELOG and fix test * Update changelog * fix analyze issue * release: 7.13.1 * Fix formatting and analyze ci issues (#1733) * Fix analysis * Update readme * run format * Add drift and hive as craft registry target (#1731) * Add drift and hive as registry target * build(deps): bump dart-lang/setup-dart from 1.3.0 to 1.6.0 (#1743) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.3.0 to 1.6.0. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/v1.3...b64355ae6ca0b5d484f0106a033dd1388965d06d) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): update Android SDK to v6.34.0 (#1746) * chore: update flutter/scripts/update-android.sh to 6.34.0 * Update CHANGELOG --------- Co-authored-by: GitHub Co-authored-by: GIancarlo Buenaflor * deps: update `package_info_plus` constraints (#1749) * Update constraints * Update CHANGELOG * release: 7.13.2 * build(deps): bump codecov/codecov-action from 3.1.1 to 3.1.4 (#1742) Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 3.1.1 to 3.1.4. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/v3.1.1...eaaf4bedf32dbdc6b720b63067d99c4d77d6047d) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor * build(deps): bump styfle/cancel-workflow-action from 0.11.0 to 0.12.0 (#1741) Bumps [styfle/cancel-workflow-action](https://github.com/styfle/cancel-workflow-action) from 0.11.0 to 0.12.0. - [Release notes](https://github.com/styfle/cancel-workflow-action/releases) - [Commits](https://github.com/styfle/cancel-workflow-action/compare/0.11.0...01ce38bf961b4e243a6342cbade0dbc8ba3f0432) --- updated-dependencies: - dependency-name: styfle/cancel-workflow-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor * build(deps): bump actions/checkout from 3 to 4 (#1740) Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor * build(deps): bump VeryGoodOpenSource/very_good_coverage (#1739) Bumps [VeryGoodOpenSource/very_good_coverage](https://github.com/verygoodopensource/very_good_coverage) from 2.1.0 to 2.2.0. - [Release notes](https://github.com/verygoodopensource/very_good_coverage/releases) - [Changelog](https://github.com/VeryGoodOpenSource/very_good_coverage/blob/main/CHANGELOG.md) - [Commits](https://github.com/verygoodopensource/very_good_coverage/compare/e5c91bc7ce9843e87c800b3bcafdfb86fbe28491...3b475421464c564c0714d92ce02742bd81fa9eda) --- updated-dependencies: - dependency-name: VeryGoodOpenSource/very_good_coverage dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor * chore: update scripts/update-symbol-collector.sh to 1.13.0 (#1737) Co-authored-by: GitHub * chore: update scripts/update-symbol-collector.sh to 1.13.0 (#1754) Co-authored-by: GitHub * Add option to opt out of fatal level for automatically collected errors (#1738) * build(deps): bump natiginfo/action-detekt-all from 1.23.3 to 1.23.4 (#1758) Bumps [natiginfo/action-detekt-all](https://github.com/natiginfo/action-detekt-all) from 1.23.3 to 1.23.4. - [Release notes](https://github.com/natiginfo/action-detekt-all/releases) - [Commits](https://github.com/natiginfo/action-detekt-all/compare/68eb02dd9f2c2686d5026f5957756064424261a9...1349d3d957cba64d7b6b2752ef874d1e03e402a2) --- updated-dependencies: - dependency-name: natiginfo/action-detekt-all dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): update Cocoa SDK to v8.17.0 (#1761) * chore: update flutter/scripts/update-cocoa.sh to 8.17.0 * Apply format --------- Co-authored-by: GitHub Co-authored-by: GIancarlo Buenaflor * build(deps): bump subosito/flutter-action from 2.10.0 to 2.12.0 (#1759) Bumps [subosito/flutter-action](https://github.com/subosito/flutter-action) from 2.10.0 to 2.12.0. - [Release notes](https://github.com/subosito/flutter-action/releases) - [Commits](https://github.com/subosito/flutter-action/compare/v2.10.0...2783a3f08e1baf891508463f8c6653c258246225) --- updated-dependencies: - dependency-name: subosito/flutter-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor * chore: update metrics/flutter.properties to 3.16.1 (#1760) Co-authored-by: GitHub * fix(example): web obfuscation not working (#1766) * Add debug_meta to all events (#1756) * load_image_list_integration now appends debug_meta info to all non-transaction events with a stacktrace, instead of checking for Exception existence * chore: Update README to include drift and hive (#1735) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: GitHub Co-authored-by: GIancarlo Buenaflor Co-authored-by: Giancarlo Buenaflor Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: getsentry-bot Co-authored-by: Denis Andrašec * chore: update metrics/flutter.properties to 3.16.2 (#1769) Co-authored-by: GitHub * chore(deps): update Cocoa SDK to v8.17.1 (#1771) * chore: update flutter/scripts/update-cocoa.sh to 8.17.1 * Formatting --------- Co-authored-by: GitHub Co-authored-by: GIancarlo Buenaflor * Add `Hive` breadcrumbs (#1773) * improvements(example): fix router navigation issue and add improvements (#1767) * Change http url and add route navigation observer example * Remove comment * Improve sample * Format * Add padding * Fix analyze issues * build(deps): bump actions/setup-java from 3 to 4 (#1772) Bumps [actions/setup-java](https://github.com/actions/setup-java) from 3 to 4. - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/setup-java dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * docs: add new package release process (#1734) * add docs * Add flutter example step * Add analyze info * Update * Update new-package-release-checklist.md * fix(ci): compile error in example using flutter beta channel (#1783) * fix ci * chore(deps): update Cocoa SDK to v8.17.2 (#1787) * chore: update flutter/scripts/update-cocoa.sh to 8.17.2 --------- Co-authored-by: GitHub Co-authored-by: GIancarlo Buenaflor * chore: update flutter/scripts/update-android.sh to 7.0.0 (#1768) Co-authored-by: GitHub Co-authored-by: Giancarlo Buenaflor * release: 7.14.0 * Add `ConnectivityIntegration` for web (#1765) * Fix changelog (#1791) * build(deps): bump actions/upload-artifact from 3 to 4 (#1789) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 3 to 4. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * APM for isar (#1726) * Bump flutter_lints from 2.0.3 to 3.0.0 in /flutter (#1698) * Bump flutter_lints from 2.0.3 to 3.0.0 in /flutter Bumps [flutter_lints](https://github.com/flutter/packages/tree/main/packages) from 2.0.3 to 3.0.0. - [Release notes](https://github.com/flutter/packages/releases) - [Commits](https://github.com/flutter/packages/commits/pigeon-v3.0.0/packages) --- updated-dependencies: - dependency-name: flutter_lints dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] * Satisfy analyzer * Satisfy dart analyzer --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor * chore: update metrics/flutter.properties to 3.16.5 (#1793) Co-authored-by: GitHub * Bump lints from 2.1.1 to 3.0.0 in /dart (#1695) * Bump lints from 2.1.1 to 3.0.0 in /dart Bumps [lints](https://github.com/dart-lang/lints) from 2.1.1 to 3.0.0. - [Release notes](https://github.com/dart-lang/lints/releases) - [Changelog](https://github.com/dart-lang/lints/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/lints/compare/v2.1.1...v3.0.0) --- updated-dependencies: - dependency-name: lints dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] * update --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: GIancarlo Buenaflor * build(deps): bump reactivecircus/android-emulator-runner (#1779) Bumps [reactivecircus/android-emulator-runner](https://github.com/reactivecircus/android-emulator-runner) from 2.28.0 to 2.29.0. - [Release notes](https://github.com/reactivecircus/android-emulator-runner/releases) - [Changelog](https://github.com/ReactiveCircus/android-emulator-runner/blob/main/CHANGELOG.md) - [Commits](https://github.com/reactivecircus/android-emulator-runner/compare/d94c3fbe4fe6a29e4a5ba47c12fb47677c73656b...99a4aac18b4df9b3af66c4a1f04c1f23fa10c270) --- updated-dependencies: - dependency-name: reactivecircus/android-emulator-runner dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor * build(deps): bump subosito/flutter-action from 2.10.0 to 2.12.0 (#1796) Bumps [subosito/flutter-action](https://github.com/subosito/flutter-action) from 2.10.0 to 2.12.0. - [Release notes](https://github.com/subosito/flutter-action/releases) - [Commits](https://github.com/subosito/flutter-action/compare/v2.10.0...2783a3f08e1baf891508463f8c6653c258246225) --- updated-dependencies: - dependency-name: subosito/flutter-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * feat: spotlight support (#1786) * Implement spotlight support (screenshots are currently disabled and removed from the envelope) * build(deps): bump VeryGoodOpenSource/very_good_coverage (#1795) Bumps [VeryGoodOpenSource/very_good_coverage](https://github.com/verygoodopensource/very_good_coverage) from 2.1.0 to 2.2.0. - [Release notes](https://github.com/verygoodopensource/very_good_coverage/releases) - [Changelog](https://github.com/VeryGoodOpenSource/very_good_coverage/blob/main/CHANGELOG.md) - [Commits](https://github.com/verygoodopensource/very_good_coverage/compare/v2.1.0...3b475421464c564c0714d92ce02742bd81fa9eda) --- updated-dependencies: - dependency-name: VeryGoodOpenSource/very_good_coverage dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps): bump actions/setup-java from 3 to 4 (#1797) Bumps [actions/setup-java](https://github.com/actions/setup-java) from 3 to 4. - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/setup-java dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Update Path Filters (#1763) * Add app flavor to `flutter_context` (#1799) * Add app flavor * fix changelog * chore(deps): update Android SDK to v7.1.0 (#1788) * chore: update flutter/scripts/update-android.sh to 7.1.0 * Fix app start * format --------- Co-authored-by: GitHub Co-authored-by: GIancarlo Buenaflor * Add isar breadcrumbs (#1800) * chore: update flutter/scripts/update-cocoa.sh to 8.18.0 (#1803) Co-authored-by: GitHub * Add `beforeScreenshotCallback` to `SentryFlutterOptions` (#1805) * fix typo in docs (#1816) * chore: update metrics/flutter.properties to 3.16.7 (#1814) Co-authored-by: GitHub * Add support for `readTransaction` in `sqflite` (#1819) * ci: disable some tests temporarily (#1835) * release: 7.15.0 * Accept `Map` in `Hint` class (#1807) * build(deps): bump actions/cache from 3 to 4 (#1833) Bumps [actions/cache](https://github.com/actions/cache) from 3 to 4. - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/cache dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor * proper changelog * fix * pin version * format ktlint * fix ktlint * fix ktlint * fix ktlint * update detekt baseline * build(deps): bump dart-lang/setup-dart from 1.6.0 to 1.6.1 (#1817) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.6.0 to 1.6.1. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/b64355ae6ca0b5d484f0106a033dd1388965d06d...ca7e6fee45ffbd82b555a7ebfc236d2c86439f5b) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor * chore(deps): update Flutter SDK (metrics) to v3.16.8 (#1825) * chore: update metrics/flutter.properties to 3.16.8 * update path --------- Co-authored-by: GitHub Co-authored-by: Giancarlo Buenaflor * feat: tracing without performance for dio (#1837) * feat: tracing without performance for dio * chore: update CHANGELOG.md * chore: reenable testing sentry-dart on windows (#1838) * enable windows again * test with chrome * test with chrome * reenable windows test * chore: add isar to craft (#1843) * add isar * Update Changelog * chore(deps): update Cocoa SDK to v8.19.0 (#1844) * chore: update flutter/scripts/update-cocoa.sh to 8.19.0 --------- Co-authored-by: GitHub Co-authored-by: GIancarlo Buenaflor * feat: Add sentry widget that includes other sentry widgets (#1846) * add sentry widget * Update CHANGELOG.md * Update CHANGELOG.md * build(deps): bump styfle/cancel-workflow-action from 0.12.0 to 0.12.1 (#1849) Bumps [styfle/cancel-workflow-action](https://github.com/styfle/cancel-workflow-action) from 0.12.0 to 0.12.1. - [Release notes](https://github.com/styfle/cancel-workflow-action/releases) - [Commits](https://github.com/styfle/cancel-workflow-action/compare/01ce38bf961b4e243a6342cbade0dbc8ba3f0432...85880fa0301c86cca9da44039ee3bb12d3bedbfa) --- updated-dependencies: - dependency-name: styfle/cancel-workflow-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps): bump reactivecircus/android-emulator-runner (#1848) Bumps [reactivecircus/android-emulator-runner](https://github.com/reactivecircus/android-emulator-runner) from 2.29.0 to 2.30.1. - [Release notes](https://github.com/reactivecircus/android-emulator-runner/releases) - [Changelog](https://github.com/ReactiveCircus/android-emulator-runner/blob/main/CHANGELOG.md) - [Commits](https://github.com/reactivecircus/android-emulator-runner/compare/99a4aac18b4df9b3af66c4a1f04c1f23fa10c270...6b0df4b0efb23bb0ec63d881db79aefbc976e4b2) --- updated-dependencies: - dependency-name: reactivecircus/android-emulator-runner dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps): bump codecov/codecov-action from 3.1.4 to 3.1.5 (#1850) Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 3.1.4 to 3.1.5. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/eaaf4bedf32dbdc6b720b63067d99c4d77d6047d...4fe8c5f003fae66aa5ebb77cfd3e7bfbbda0b6b0) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor * chore(deps): update Android SDK to v7.2.0 (#1815) * chore: update flutter/scripts/update-android.sh to 7.2.0 * Update podfile * Update podfile * Update deployment target * update * update --------- Co-authored-by: GitHub Co-authored-by: GIancarlo Buenaflor * chore(deps): update Flutter SDK (metrics) to v3.16.9 (#1847) * chore: update metrics/flutter.properties to 3.16.9 * update * update --------- Co-authored-by: GitHub Co-authored-by: GIancarlo Buenaflor * chore(deps): update Symbol collector CLI to v1.14.0 (#1827) * chore: update scripts/update-symbol-collector.sh to 1.14.0 * update --------- Co-authored-by: GitHub Co-authored-by: GIancarlo Buenaflor * Update CHANGELOG.md (#1845) * chore: update flutter/scripts/update-android.sh to 7.3.0 (#1852) Co-authored-by: GitHub * release: 7.16.0 * Update CHANGELOG.md * Update .craft.yml * Update resources in readme --------- Signed-off-by: dependabot[bot] Co-authored-by: Ivan Dlugos <6349682+vaind@users.noreply.github.com> Co-authored-by: Denis Andrašec Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: GitHub Co-authored-by: getsentry-bot Co-authored-by: getsentry-bot Co-authored-by: Jonas Uekötter Co-authored-by: Stefano Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Bruno Garcia Co-authored-by: Stefano Co-authored-by: Oleg Magomedov <69794332+smart7even@users.noreply.github.com> Co-authored-by: Igor Khramtsov * chore(v8): update to min ios version 12 (#1821) * update to min ios version 12 * Update CHANGELOG * Update CHANGELOG * Update CHANGELOG * Re-enable iOS flutter integration test * Update CHANGELOG * v8 prep: merge main into 8.0.0 branch (#1871) * ci: update actions (#1617) * Add tests for the Android and iOS plugin (#1587) * Normalize `data` properties of `SentryUser` and `Breadcrumb` before sending over method channel (#1591) * chore(deps): update Cocoa SDK to v8.11.0 (#1626) Co-authored-by: GitHub * Tracing without performance (#1621) * implement propagationContext * remove sampled and parentSpanId for now * update changelog * fix build error * create new propagation context on startTransaction if tracing is disabled * remove print * propagate trace for http requests * add tracing client test * fix tests * format * fix compile * tests * fix analysis score * fix analysis score * fix compilation * fix score * fix score * fix score * fix score * update tests * [starfish] add attributes to db spans data (#1629) * add db attibutes to spans * change variable names * update changelog * update changelog * update tests * update imports * update tests * remove unused import * couple dbName to db instance * format * use path pub * don't set dbName to null when db close() is called * [starfish] add http.request.method attribute to http spans (#1633) * add http.request.method to http spans * update changelog * Fix Android & iOS CI issues (#1627) * Disable scope sync for cloned scopes (#1628) * chore: update flutter/scripts/update-android.sh to 6.29.0 (#1630) Co-authored-by: GitHub * Discard empty stack frames (#1625) * Introduce workflow dispatch action for`format` & `fix --apply` (#1575) * feat/refactor: add cocoa FFI binding (#1631) * refactor: move native code to its own directory (#1638) * Log SDK errors to the console if the log level is `fatal` even if `debug` is disabled (#1635) * Fix autoPerformanceTracingEnabled flag in andorid plugin (#1640) * Add Sampling Decision to Trace Envelope Header (#1639) * add sampled flag * fmt * update changelog * redo fmt * fix tests * chore: update metrics/flutter.properties to 3.13.3 (#1632) Co-authored-by: GitHub * fix: add missing FFI depdendency (#1642) * release: 7.10.1 * ci: macos integration test (#1645) * fix: generated cocoa bindings (#1648) * Update uuid (#1647) Co-authored-by: Ivan Dlugos <6349682+vaind@users.noreply.github.com> * chore(deps): update Cocoa SDK to v8.12.0 (#1650) Co-authored-by: GitHub * Breadcrumbs for file I/O operations (#1649) * ci: don't run CI on markdown updates (#1651) * chore(deps): update Flutter SDK (metrics) to v3.13.6 (#1659) * chore: update metrics/flutter.properties to 3.13.6 * Update flutter.properties --------- Co-authored-by: GitHub Co-authored-by: Stefano * chore: update flutter/scripts/update-android.sh to 6.30.0 (#1660) * chore: update flutter/scripts/update-cocoa.sh to 8.13.0 (#1655) * Generate class diagrams (#1646) * Rename `options.devMode` to `options.automatedTestMode` (#1664) * chore: update flutter/scripts/update-cocoa.sh to 8.13.1 (#1677) Co-authored-by: GitHub * chore: update flutter/scripts/update-android.sh to 6.31.0 (#1676) * chore: update metrics/flutter.properties to 3.13.7 (#1674) Co-authored-by: GitHub * Add dependabot (#1670) * Bump codecov/codecov-action from 3.1.1 to 3.1.4 (#1680) * chore: update flutter/scripts/update-android.sh to 6.32.0 (#1688) Co-authored-by: GitHub * chore(deps): update Cocoa SDK to v8.14.2 (#1691) * chore: update flutter/scripts/update-cocoa.sh to 8.14.2 --------- Co-authored-by: GitHub Co-authored-by: GIancarlo Buenaflor * chore: update changelog (#1699) * Update changelog * release: 7.11.0 * Bump lints from 2.1.1 to 3.0.0 in /sqflite (#1697) Bumps [lints](https://github.com/dart-lang/lints) from 2.1.1 to 3.0.0. - [Release notes](https://github.com/dart-lang/lints/releases) - [Changelog](https://github.com/dart-lang/lints/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/lints/compare/v2.1.1...v3.0.0) --- updated-dependencies: - dependency-name: lints dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump lints from 2.1.1 to 3.0.0 in /logging (#1696) Bumps [lints](https://github.com/dart-lang/lints) from 2.1.1 to 3.0.0. - [Release notes](https://github.com/dart-lang/lints/releases) - [Changelog](https://github.com/dart-lang/lints/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/lints/compare/v2.1.1...v3.0.0) --- updated-dependencies: - dependency-name: lints dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump lints from 2.1.1 to 3.0.0 in /file (#1694) Bumps [lints](https://github.com/dart-lang/lints) from 2.1.1 to 3.0.0. - [Release notes](https://github.com/dart-lang/lints/releases) - [Changelog](https://github.com/dart-lang/lints/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/lints/compare/v2.1.1...v3.0.0) --- updated-dependencies: - dependency-name: lints dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump lints from 2.1.1 to 3.0.0 in /dio (#1693) Bumps [lints](https://github.com/dart-lang/lints) from 2.1.1 to 3.0.0. - [Release notes](https://github.com/dart-lang/lints/releases) - [Changelog](https://github.com/dart-lang/lints/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/lints/compare/v2.1.1...v3.0.0) --- updated-dependencies: - dependency-name: lints dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * feat: profiling for iOS/macOS (#1611) Co-authored-by: Bruno Garcia Co-authored-by: Denis Andrašec Co-authored-by: Stefano * chore: update metrics/flutter.properties to 3.13.9 (#1702) * chore: log warning if both tracesSampleRate and tracesSampler are set (#1701) * Log warning if both tracesSampleRate and tracesSampler are set * Update CHANGELOG * Update log * Update CHANGELOG * chore: flutter symbol collector CLI tool (#1673) * release: 7.12.0 * Add `SentryNavigatorObserver` current route to `event.app.contexts.viewNames` (#1545) * fix: coverage not ignoring generated binding.dart (#1707) * Remove coverage for binding.dart * Breadcrumbs for database operations (#1656) * Bump actions/checkout from 3 to 4 (#1683) Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump ScaCap/action-ktlint from 1.7.1 to 1.8.0 (#1681) Bumps [ScaCap/action-ktlint](https://github.com/scacap/action-ktlint) from 1.7.1 to 1.8.0. - [Release notes](https://github.com/scacap/action-ktlint/releases) - [Commits](https://github.com/scacap/action-ktlint/compare/2cf245b99bc91f73bc4c96a3d9d57bb5da3533ae...0ff81efa49425bd0df46caabd8005aafdc8f2cf2) --- updated-dependencies: - dependency-name: ScaCap/action-ktlint dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump styfle/cancel-workflow-action from 0.11.0 to 0.12.0 (#1682) Bumps [styfle/cancel-workflow-action](https://github.com/styfle/cancel-workflow-action) from 0.11.0 to 0.12.0. - [Release notes](https://github.com/styfle/cancel-workflow-action/releases) - [Commits](https://github.com/styfle/cancel-workflow-action/compare/b173b6ec0100793626c2d9e6b90435061f4fc3e5...01ce38bf961b4e243a6342cbade0dbc8ba3f0432) --- updated-dependencies: - dependency-name: styfle/cancel-workflow-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Stefano Co-authored-by: Giancarlo Buenaflor * Bump dart-lang/setup-dart from 1.3.0 to 1.6.0 (#1692) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.3.0 to 1.6.0. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/6a218f2413a3e78e9087f638a238f6b40893203d...b64355ae6ca0b5d484f0106a033dd1388965d06d) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor * chore: update flutter/scripts/update-android.sh to 6.33.0 (#1710) Co-authored-by: GitHub * build(deps): bump subosito/flutter-action from 2.10.0 to 2.12.0 (#1711) Bumps [subosito/flutter-action](https://github.com/subosito/flutter-action) from 2.10.0 to 2.12.0. - [Release notes](https://github.com/subosito/flutter-action/releases) - [Commits](https://github.com/subosito/flutter-action/compare/48cafc24713cca54bbe03cdc3a423187d413aafa...2783a3f08e1baf891508463f8c6653c258246225) --- updated-dependencies: - dependency-name: subosito/flutter-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Add `attachScreenshotOnlyWhenResumed` to options (#1700) * chore: update flutter/scripts/update-android.sh to 6.33.1 (#1713) Co-authored-by: GitHub * chore: update flutter/scripts/update-cocoa.sh to 8.15.0 (#1712) Co-authored-by: GitHub * chore: update flutter/scripts/update-cocoa.sh to 8.15.1 (#1714) Co-authored-by: GitHub * fix: unsupported types with expando (#1690) * Support string, int, double and bool as throwable for expando * Rename the test file and move it to utils folder{ * Remvoe ffi import * Update changelog * Try other url for dio pubspec doc url * Change doc url of logging pubspec * Remove unnecessary code * Update naming * Rename * chore: update flutter/scripts/update-cocoa.sh to 8.15.2 (#1717) Co-authored-by: GitHub * Parse message field in `PlatformException.message` (#1716) * Parse message field * changelog * Update CHANGELOG.md * Bump natiginfo/action-detekt-all from 1.21.0 to 1.23.1 (#1684) * Bump natiginfo/action-detekt-all from 1.21.0 to 1.23.1 Bumps [natiginfo/action-detekt-all](https://github.com/natiginfo/action-detekt-all) from 1.21.0 to 1.23.1. - [Release notes](https://github.com/natiginfo/action-detekt-all/releases) - [Commits](https://github.com/natiginfo/action-detekt-all/compare/e01de6ff0eef7c24131e8a133bf598cfac6ceeab...be3c18799c7c392b2f41a674beed9ced7ae2f21b) --- updated-dependencies: - dependency-name: natiginfo/action-detekt-all dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * fix braces * Add missing trailing comma --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor * build(deps): bump natiginfo/action-detekt-all from 1.23.1 to 1.23.3 (#1722) Bumps [natiginfo/action-detekt-all](https://github.com/natiginfo/action-detekt-all) from 1.23.1 to 1.23.3. - [Release notes](https://github.com/natiginfo/action-detekt-all/releases) - [Commits](https://github.com/natiginfo/action-detekt-all/compare/be3c18799c7c392b2f41a674beed9ced7ae2f21b...68eb02dd9f2c2686d5026f5957756064424261a9) --- updated-dependencies: - dependency-name: natiginfo/action-detekt-all dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Remove renderer on Dart:io platforms (#1723) * Remove renderer on dart:io platforms * Tests + changelog * Update CHANGELOG.md * Fix tests * fix more tests * feat: drift apm (#1709) * draft impl * improve code * Add open span * Refactor to extend lazy database * Update * SentryTransactionExecutor * Implement tracing batch and transactions * Update tests * update changelog * Formatting * Update workflows * Update deps * Fix analyze issues * Format * Add example * Update descriptions * Fix deps * Update run commands * Update workflow * Update example * Update workflow * Format * Fix dart analyze * Try changing deps * Add to craft * Change to flutter test * Revert flutter test mock * change dir manually * download and extract sqlite.dll for windows * Try downloading sqlite3 * set up dart * fix path to file * use pub get * Use flutter pub get * fix * skip windows test * fix analyze * fix drift.yml * format * Remove redundant test * Remove debug print * update trace origin * Improvements * Improvements * Add to flutter example * fix: setting the correct locale to contexts with navigatorKey (#1724) * Add localization with navigatorKey * Update CHANGELOG * Update tests * Update tests * Format * Remove unused import * Apply review improvements * Update CHANGELOG * APM for hive (#1672) * setup sentry hive library * Add SentryBox with first test * test added spans * Add sentry hive impl * introduce base box to avoid duplication * implement lazy box test * expose sentry hive and updata documentation * add hive to flutter example app * test throwing in base_box, cleanup * test lazy box error cases * test sentry hive impl failures * run fix & format * fix test failure race condition * add hive workflow, update other workflows * add changelog entry * remove path+provider from dev_dependencies * add coverage dev dependency * fix deprecation warnings * fix changelog * move span wrapping on own class to avoid duplication * add sentry box collection * test added spans, fix imports * test throwing code * fix changelog * change dbSystem value * change db system * remove unneccessary async & await * Fix analyze * Formatting * Add changelog symlink * Ignore hive coverage * Create symlink for dartdoc_options --------- Co-authored-by: Giancarlo Buenaflor * release: 7.13.0 * Fixes release of drift & hive (#1729) * Add integrations * Readd changelog * Add drift and hive to bump versions * Formatting and analyze * Update CHANGELOG and fix test * Update changelog * fix analyze issue * release: 7.13.1 * Fix formatting and analyze ci issues (#1733) * Fix analysis * Update readme * run format * Add drift and hive as craft registry target (#1731) * Add drift and hive as registry target * build(deps): bump dart-lang/setup-dart from 1.3.0 to 1.6.0 (#1743) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.3.0 to 1.6.0. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/v1.3...b64355ae6ca0b5d484f0106a033dd1388965d06d) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): update Android SDK to v6.34.0 (#1746) * chore: update flutter/scripts/update-android.sh to 6.34.0 * Update CHANGELOG --------- Co-authored-by: GitHub Co-authored-by: GIancarlo Buenaflor * deps: update `package_info_plus` constraints (#1749) * Update constraints * Update CHANGELOG * release: 7.13.2 * build(deps): bump codecov/codecov-action from 3.1.1 to 3.1.4 (#1742) Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 3.1.1 to 3.1.4. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/v3.1.1...eaaf4bedf32dbdc6b720b63067d99c4d77d6047d) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor * build(deps): bump styfle/cancel-workflow-action from 0.11.0 to 0.12.0 (#1741) Bumps [styfle/cancel-workflow-action](https://github.com/styfle/cancel-workflow-action) from 0.11.0 to 0.12.0. - [Release notes](https://github.com/styfle/cancel-workflow-action/releases) - [Commits](https://github.com/styfle/cancel-workflow-action/compare/0.11.0...01ce38bf961b4e243a6342cbade0dbc8ba3f0432) --- updated-dependencies: - dependency-name: styfle/cancel-workflow-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor * build(deps): bump actions/checkout from 3 to 4 (#1740) Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor * build(deps): bump VeryGoodOpenSource/very_good_coverage (#1739) Bumps [VeryGoodOpenSource/very_good_coverage](https://github.com/verygoodopensource/very_good_coverage) from 2.1.0 to 2.2.0. - [Release notes](https://github.com/verygoodopensource/very_good_coverage/releases) - [Changelog](https://github.com/VeryGoodOpenSource/very_good_coverage/blob/main/CHANGELOG.md) - [Commits](https://github.com/verygoodopensource/very_good_coverage/compare/e5c91bc7ce9843e87c800b3bcafdfb86fbe28491...3b475421464c564c0714d92ce02742bd81fa9eda) --- updated-dependencies: - dependency-name: VeryGoodOpenSource/very_good_coverage dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor * chore: update scripts/update-symbol-collector.sh to 1.13.0 (#1737) Co-authored-by: GitHub * chore: update scripts/update-symbol-collector.sh to 1.13.0 (#1754) Co-authored-by: GitHub * Add option to opt out of fatal level for automatically collected errors (#1738) * build(deps): bump natiginfo/action-detekt-all from 1.23.3 to 1.23.4 (#1758) Bumps [natiginfo/action-detekt-all](https://github.com/natiginfo/action-detekt-all) from 1.23.3 to 1.23.4. - [Release notes](https://github.com/natiginfo/action-detekt-all/releases) - [Commits](https://github.com/natiginfo/action-detekt-all/compare/68eb02dd9f2c2686d5026f5957756064424261a9...1349d3d957cba64d7b6b2752ef874d1e03e402a2) --- updated-dependencies: - dependency-name: natiginfo/action-detekt-all dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): update Cocoa SDK to v8.17.0 (#1761) * chore: update flutter/scripts/update-cocoa.sh to 8.17.0 * Apply format --------- Co-authored-by: GitHub Co-authored-by: GIancarlo Buenaflor * build(deps): bump subosito/flutter-action from 2.10.0 to 2.12.0 (#1759) Bumps [subosito/flutter-action](https://github.com/subosito/flutter-action) from 2.10.0 to 2.12.0. - [Release notes](https://github.com/subosito/flutter-action/releases) - [Commits](https://github.com/subosito/flutter-action/compare/v2.10.0...2783a3f08e1baf891508463f8c6653c258246225) --- updated-dependencies: - dependency-name: subosito/flutter-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor * chore: update metrics/flutter.properties to 3.16.1 (#1760) Co-authored-by: GitHub * fix(example): web obfuscation not working (#1766) * Add debug_meta to all events (#1756) * load_image_list_integration now appends debug_meta info to all non-transaction events with a stacktrace, instead of checking for Exception existence * chore: Update README to include drift and hive (#1735) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: GitHub Co-authored-by: GIancarlo Buenaflor Co-authored-by: Giancarlo Buenaflor Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: getsentry-bot Co-authored-by: Denis Andrašec * chore: update metrics/flutter.properties to 3.16.2 (#1769) Co-authored-by: GitHub * chore(deps): update Cocoa SDK to v8.17.1 (#1771) * chore: update flutter/scripts/update-cocoa.sh to 8.17.1 * Formatting --------- Co-authored-by: GitHub Co-authored-by: GIancarlo Buenaflor * Add `Hive` breadcrumbs (#1773) * improvements(example): fix router navigation issue and add improvements (#1767) * Change http url and add route navigation observer example * Remove comment * Improve sample * Format * Add padding * Fix analyze issues * build(deps): bump actions/setup-java from 3 to 4 (#1772) Bumps [actions/setup-java](https://github.com/actions/setup-java) from 3 to 4. - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/setup-java dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * docs: add new package release process (#1734) * add docs * Add flutter example step * Add analyze info * Update * Update new-package-release-checklist.md * fix(ci): compile error in example using flutter beta channel (#1783) * fix ci * chore(deps): update Cocoa SDK to v8.17.2 (#1787) * chore: update flutter/scripts/update-cocoa.sh to 8.17.2 --------- Co-authored-by: GitHub Co-authored-by: GIancarlo Buenaflor * chore: update flutter/scripts/update-android.sh to 7.0.0 (#1768) Co-authored-by: GitHub Co-authored-by: Giancarlo Buenaflor * release: 7.14.0 * Add `ConnectivityIntegration` for web (#1765) * Fix changelog (#1791) * build(deps): bump actions/upload-artifact from 3 to 4 (#1789) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 3 to 4. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * APM for isar (#1726) * Bump flutter_lints from 2.0.3 to 3.0.0 in /flutter (#1698) * Bump flutter_lints from 2.0.3 to 3.0.0 in /flutter Bumps [flutter_lints](https://github.com/flutter/packages/tree/main/packages) from 2.0.3 to 3.0.0. - [Release notes](https://github.com/flutter/packages/releases) - [Commits](https://github.com/flutter/packages/commits/pigeon-v3.0.0/packages) --- updated-dependencies: - dependency-name: flutter_lints dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] * Satisfy analyzer * Satisfy dart analyzer --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor * chore: update metrics/flutter.properties to 3.16.5 (#1793) Co-authored-by: GitHub * Bump lints from 2.1.1 to 3.0.0 in /dart (#1695) * Bump lints from 2.1.1 to 3.0.0 in /dart Bumps [lints](https://github.com/dart-lang/lints) from 2.1.1 to 3.0.0. - [Release notes](https://github.com/dart-lang/lints/releases) - [Changelog](https://github.com/dart-lang/lints/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/lints/compare/v2.1.1...v3.0.0) --- updated-dependencies: - dependency-name: lints dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] * update --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: GIancarlo Buenaflor * build(deps): bump reactivecircus/android-emulator-runner (#1779) Bumps [reactivecircus/android-emulator-runner](https://github.com/reactivecircus/android-emulator-runner) from 2.28.0 to 2.29.0. - [Release notes](https://github.com/reactivecircus/android-emulator-runner/releases) - [Changelog](https://github.com/ReactiveCircus/android-emulator-runner/blob/main/CHANGELOG.md) - [Commits](https://github.com/reactivecircus/android-emulator-runner/compare/d94c3fbe4fe6a29e4a5ba47c12fb47677c73656b...99a4aac18b4df9b3af66c4a1f04c1f23fa10c270) --- updated-dependencies: - dependency-name: reactivecircus/android-emulator-runner dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor * build(deps): bump subosito/flutter-action from 2.10.0 to 2.12.0 (#1796) Bumps [subosito/flutter-action](https://github.com/subosito/flutter-action) from 2.10.0 to 2.12.0. - [Release notes](https://github.com/subosito/flutter-action/releases) - [Commits](https://github.com/subosito/flutter-action/compare/v2.10.0...2783a3f08e1baf891508463f8c6653c258246225) --- updated-dependencies: - dependency-name: subosito/flutter-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * feat: spotlight support (#1786) * Implement spotlight support (screenshots are currently disabled and removed from the envelope) * build(deps): bump VeryGoodOpenSource/very_good_coverage (#1795) Bumps [VeryGoodOpenSource/very_good_coverage](https://github.com/verygoodopensource/very_good_coverage) from 2.1.0 to 2.2.0. - [Release notes](https://github.com/verygoodopensource/very_good_coverage/releases) - [Changelog](https://github.com/VeryGoodOpenSource/very_good_coverage/blob/main/CHANGELOG.md) - [Commits](https://github.com/verygoodopensource/very_good_coverage/compare/v2.1.0...3b475421464c564c0714d92ce02742bd81fa9eda) --- updated-dependencies: - dependency-name: VeryGoodOpenSource/very_good_coverage dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps): bump actions/setup-java from 3 to 4 (#1797) Bumps [actions/setup-java](https://github.com/actions/setup-java) from 3 to 4. - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/setup-java dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Update Path Filters (#1763) * Add app flavor to `flutter_context` (#1799) * Add app flavor * fix changelog * chore(deps): update Android SDK to v7.1.0 (#1788) * chore: update flutter/scripts/update-android.sh to 7.1.0 * Fix app start * format --------- Co-authored-by: GitHub Co-authored-by: GIancarlo Buenaflor * Add isar breadcrumbs (#1800) * chore: update flutter/scripts/update-cocoa.sh to 8.18.0 (#1803) Co-authored-by: GitHub * Add `beforeScreenshotCallback` to `SentryFlutterOptions` (#1805) * fix typo in docs (#1816) * chore: update metrics/flutter.properties to 3.16.7 (#1814) Co-authored-by: GitHub * Add support for `readTransaction` in `sqflite` (#1819) * ci: disable some tests temporarily (#1835) * release: 7.15.0 * Accept `Map` in `Hint` class (#1807) * build(deps): bump actions/cache from 3 to 4 (#1833) Bumps [actions/cache](https://github.com/actions/cache) from 3 to 4. - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/cache dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor * build(deps): bump dart-lang/setup-dart from 1.6.0 to 1.6.1 (#1817) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.6.0 to 1.6.1. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/b64355ae6ca0b5d484f0106a033dd1388965d06d...ca7e6fee45ffbd82b555a7ebfc236d2c86439f5b) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor * chore(deps): update Flutter SDK (metrics) to v3.16.8 (#1825) * chore: update metrics/flutter.properties to 3.16.8 * update path --------- Co-authored-by: GitHub Co-authored-by: Giancarlo Buenaflor * feat: tracing without performance for dio (#1837) * feat: tracing without performance for dio * chore: update CHANGELOG.md * chore: reenable testing sentry-dart on windows (#1838) * enable windows again * test with chrome * test with chrome * reenable windows test * chore: add isar to craft (#1843) * add isar * Update Changelog * chore(deps): update Cocoa SDK to v8.19.0 (#1844) * chore: update flutter/scripts/update-cocoa.sh to 8.19.0 --------- Co-authored-by: GitHub Co-authored-by: GIancarlo Buenaflor * feat: Add sentry widget that includes other sentry widgets (#1846) * add sentry widget * Update CHANGELOG.md * Update CHANGELOG.md * build(deps): bump styfle/cancel-workflow-action from 0.12.0 to 0.12.1 (#1849) Bumps [styfle/cancel-workflow-action](https://github.com/styfle/cancel-workflow-action) from 0.12.0 to 0.12.1. - [Release notes](https://github.com/styfle/cancel-workflow-action/releases) - [Commits](https://github.com/styfle/cancel-workflow-action/compare/01ce38bf961b4e243a6342cbade0dbc8ba3f0432...85880fa0301c86cca9da44039ee3bb12d3bedbfa) --- updated-dependencies: - dependency-name: styfle/cancel-workflow-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps): bump reactivecircus/android-emulator-runner (#1848) Bumps [reactivecircus/android-emulator-runner](https://github.com/reactivecircus/android-emulator-runner) from 2.29.0 to 2.30.1. - [Release notes](https://github.com/reactivecircus/android-emulator-runner/releases) - [Changelog](https://github.com/ReactiveCircus/android-emulator-runner/blob/main/CHANGELOG.md) - [Commits](https://github.com/reactivecircus/android-emulator-runner/compare/99a4aac18b4df9b3af66c4a1f04c1f23fa10c270...6b0df4b0efb23bb0ec63d881db79aefbc976e4b2) --- updated-dependencies: - dependency-name: reactivecircus/android-emulator-runner dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps): bump codecov/codecov-action from 3.1.4 to 3.1.5 (#1850) Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 3.1.4 to 3.1.5. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/eaaf4bedf32dbdc6b720b63067d99c4d77d6047d...4fe8c5f003fae66aa5ebb77cfd3e7bfbbda0b6b0) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor * chore(deps): update Android SDK to v7.2.0 (#1815) * chore: update flutter/scripts/update-android.sh to 7.2.0 * Update podfile * Update podfile * Update deployment target * update * update --------- Co-authored-by: GitHub Co-authored-by: GIancarlo Buenaflor * chore(deps): update Flutter SDK (metrics) to v3.16.9 (#1847) * chore: update metrics/flutter.properties to 3.16.9 * update * update --------- Co-authored-by: GitHub Co-authored-by: GIancarlo Buenaflor * chore(deps): update Symbol collector CLI to v1.14.0 (#1827) * chore: update scripts/update-symbol-collector.sh to 1.14.0 * update --------- Co-authored-by: GitHub Co-authored-by: GIancarlo Buenaflor * Update CHANGELOG.md (#1845) * chore: update flutter/scripts/update-android.sh to 7.3.0 (#1852) Co-authored-by: GitHub * release: 7.16.0 * chore(sample): Upgrade SAGP to v4.2.0 in the flutter example app (#1860) * build(deps): bump dart-lang/setup-dart from 1.6.1 to 1.6.2 (#1864) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.6.1 to 1.6.2. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/ca7e6fee45ffbd82b555a7ebfc236d2c86439f5b...fedb1266e91cf51be2fdb382869461a434b920a3) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): update Cocoa SDK to v8.20.0 (#1856) * chore: update flutter/scripts/update-cocoa.sh to 8.20.0 * format --------- Co-authored-by: GitHub Co-authored-by: GIancarlo Buenaflor * build(deps): bump natiginfo/action-detekt-all from 1.23.4 to 1.23.5 (#1862) Bumps [natiginfo/action-detekt-all](https://github.com/natiginfo/action-detekt-all) from 1.23.4 to 1.23.5. - [Release notes](https://github.com/natiginfo/action-detekt-all/releases) - [Commits](https://github.com/natiginfo/action-detekt-all/compare/1349d3d957cba64d7b6b2752ef874d1e03e402a2...60495f27089d3432d83335c1f14e46ba61de5637) --- updated-dependencies: - dependency-name: natiginfo/action-detekt-all dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor * build(deps): bump codecov/codecov-action from 3.1.5 to 4.0.1 (#1863) Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 3.1.5 to 4.0.1. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/4fe8c5f003fae66aa5ebb77cfd3e7bfbbda0b6b0...e0b68c6749509c5f83f984dd99a76a1c1a231044) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor * chore(android): Remove dead code, cold start bool is now always present (#1861) * chore(android): Remove dead code, cold start bool is now always present * Update CHANGELOG.md --------- Co-authored-by: Giancarlo Buenaflor * chore: update scripts/update-symbol-collector.sh to 1.15.0 (#1853) Co-authored-by: GitHub * build(deps): bump gradle/gradle-build-action from 2 to 3 (#1851) * build(deps): bump gradle/gradle-build-action from 2 to 3 Bumps [gradle/gradle-build-action](https://github.com/gradle/gradle-build-action) from 2 to 3. - [Release notes](https://github.com/gradle/gradle-build-action/releases) - [Commits](https://github.com/gradle/gradle-build-action/compare/v2...v3) --- updated-dependencies: - dependency-name: gradle/gradle-build-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] * Update flutter_test.yml --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor * chore: update scripts/update-symbol-collector.sh to 1.15.0 (#1869) Co-authored-by: GitHub Co-authored-by: Giancarlo Buenaflor * merge main into release/8.0.0 * update * update * update * update * fix: remove Flutter dep from Drift integration (#1867) * Remove Flutter dep * Update CHANGELOG * Remove unused import * fix * fix * fix * Update flutter_test.yml * Update CHANGELOG.md --------- Signed-off-by: dependabot[bot] Co-authored-by: Ivan Dlugos <6349682+vaind@users.noreply.github.com> Co-authored-by: Denis Andrašec Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: GitHub Co-authored-by: getsentry-bot Co-authored-by: getsentry-bot Co-authored-by: Jonas Uekötter Co-authored-by: Stefano Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Bruno Garcia Co-authored-by: Stefano Co-authored-by: Oleg Magomedov <69794332+smart7even@users.noreply.github.com> Co-authored-by: Igor Khramtsov Co-authored-by: Kryštof Woldřich <31292499+krystofwoldrich@users.noreply.github.com> * release: 8.0.0-beta.2 * Update CHANGELOG * Testflight (#1938) * Setup testflight against v8 branch * enable run on pr * run on push * make executable * fix beta version number * push on main, release and workflow update * bump xcode default version to 15.0.1 * add newline * Add ITSAppUsesNonExemptEncryption to info.plist * select with xcodes * fix file extension * fix warnings * use correct property to remove warning * Update ktlint --------- Co-authored-by: GIancarlo Buenaflor * Merge branch 'main' into release/8.0.0 * Fix test compilation * Update CHANGELOG.md * Update CHANGELOG.md * Update CHANGELOG.md * Fix analyze issues * Apply formatter * Update versions to 8.0.0 (#1996) * Fix compilation * Exception aggregate mechanism (#1866) * Exception aggregate * changelog * Update CHANGELOG.md * fix json keys in test * Update dart/lib/src/protocol/mechanism.dart * Update CHANGELOG.md --------- Co-authored-by: Giancarlo Buenaflor * Update CHANGELOG.md * Update CHANGELOG --------- Signed-off-by: dependabot[bot] Co-authored-by: Denis Andrašec Co-authored-by: Ivan Dlugos <6349682+vaind@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: GitHub Co-authored-by: getsentry-bot Co-authored-by: getsentry-bot Co-authored-by: Jonas Uekötter Co-authored-by: Stefano Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Bruno Garcia Co-authored-by: Stefano Co-authored-by: Oleg Magomedov <69794332+smart7even@users.noreply.github.com> Co-authored-by: Igor Khramtsov Co-authored-by: Kryštof Woldřich <31292499+krystofwoldrich@users.noreply.github.com> --- .craft.yml | 3 +- .../workflows/flutter_integration_test.yml | 119 +++++++++ .github/workflows/flutter_test.yml | 5 +- .github/workflows/testflight.yml | 57 ++++ CHANGELOG.md | 60 +++++ dart/README.md | 11 +- dart/example/bin/example.dart | 2 +- dart/example_web/analysis_options.yaml | 5 + dart/example_web/pubspec.yaml | 2 +- dart/example_web/web/main.dart | 2 +- .../src/client_reports/discard_reason.dart | 21 -- .../src/client_reports/discarded_event.dart | 50 +++- dart/lib/src/event_processor.dart | 6 +- .../deduplication_event_processor.dart | 2 +- .../enricher/io_enricher_event_processor.dart | 2 +- .../web_enricher_event_processor.dart | 2 +- .../io_exception_event_processor.dart | 2 +- .../web_exception_event_processor.dart | 2 +- dart/lib/src/hint.dart | 8 +- .../http_client/failed_request_client.dart | 4 +- dart/lib/src/protocol/mechanism.dart | 52 ++++ dart/lib/src/protocol/sentry_request.dart | 9 +- dart/lib/src/protocol/sentry_response.dart | 10 +- .../src/run_zoned_guarded_integration.dart | 4 +- dart/lib/src/scope.dart | 16 +- dart/lib/src/sentry_client.dart | 80 ++---- dart/lib/src/sentry_isolate.dart | 5 +- dart/lib/src/sentry_options.dart | 12 +- dart/lib/src/sentry_tracer.dart | 9 - dart/lib/src/transport/data_category.dart | 47 ---- dart/lib/src/transport/rate_limit_parser.dart | 28 +- dart/lib/src/utils/http_sanitizer.dart | 3 +- dart/lib/src/utils/isolate_utils.dart | 3 + dart/lib/src/utils/iterable_extension.dart | 8 - dart/lib/src/utils/iterable_utils.dart | 17 ++ dart/lib/src/version.dart | 2 +- dart/pubspec.yaml | 2 +- .../deduplication_event_processor_test.dart | 24 +- .../enricher/io_enricher_test.dart | 20 +- .../enricher/web_enricher_test.dart | 22 +- .../io_exception_event_processor_test.dart | 4 + .../failed_request_client_test.dart | 2 +- dart/test/mocks.dart | 10 +- dart/test/protocol/mechanism_test.dart | 17 ++ dart/test/scope_test.dart | 68 +++-- dart/test/sentry_client_test.dart | 252 ++---------------- dart/test/sentry_tracer_test.dart | 22 +- dart/test/utils/http_sanitizer_test.dart | 2 +- dio/README.md | 9 +- dio/lib/src/dio_event_processor.dart | 2 +- dio/lib/src/failed_request_interceptor.dart | 4 +- dio/lib/src/version.dart | 2 +- dio/pubspec.yaml | 4 +- dio/test/dio_event_processor_test.dart | 22 +- dio/test/mocks.dart | 14 +- drift/README.md | 7 +- drift/lib/src/version.dart | 2 +- drift/pubspec.yaml | 4 +- file/lib/src/version.dart | 2 +- file/pubspec.yaml | 4 +- flutter/README.md | 7 +- .../kotlin/io/sentry/flutter/SentryFlutter.kt | 13 +- .../io/sentry/flutter/SentryFlutterPlugin.kt | 68 ++--- .../io/sentry/flutter/SentryFlutterTest.kt | 65 +++-- flutter/config/detekt-bl.xml | 3 +- .../integration_test/integration_test.dart | 2 +- .../ios/Flutter/AppFrameworkInfo.plist | 2 +- flutter/example/ios/Gemfile | 3 + flutter/example/ios/Podfile | 4 +- .../ios/Runner.xcodeproj/project.pbxproj | 23 +- flutter/example/ios/Runner/Info.plist | 10 +- .../ios/RunnerTests/SentryFlutterTests.swift | 2 - flutter/example/ios/fastlane/Appfile | 7 + flutter/example/ios/fastlane/Fastfile | 95 +++++++ flutter/example/ios/fastlane/Matchfile | 5 + flutter/example/lib/main.dart | 1 - flutter/example/pubspec.yaml | 2 +- flutter/ios/sentry_flutter.podspec | 2 +- ...id_platform_exception_event_processor.dart | 2 +- .../flutter_enricher_event_processor.dart | 6 +- .../flutter_exception_event_processor.dart | 2 +- .../native_app_start_event_processor.dart | 2 +- .../platform_exception_event_processor.dart | 2 +- .../screenshot_event_processor.dart | 4 +- .../widget_event_processor.dart | 2 +- .../flutter_error_integration.dart | 7 +- .../load_contexts_integration.dart | 21 +- .../load_image_list_integration.dart | 2 +- flutter/lib/src/sentry_flutter.dart | 2 +- .../sentry_user_interaction_widget.dart | 3 +- flutter/lib/src/version.dart | 2 +- .../view_hierarchy/sentry_tree_walker.dart | 2 +- .../view_hierarchy_event_processor.dart | 6 +- flutter/lib/src/widget_utils.dart | 10 +- flutter/pubspec.yaml | 4 +- ...atform_exception_event_processor_test.dart | 23 +- ...flutter_enricher_event_processor_test.dart | 34 +-- ...lutter_exception_event_processor_test.dart | 1 + ...atform_exception_event_processor_test.dart | 4 +- .../screenshot_event_processor_test.dart | 2 +- .../widget_event_processor_test.dart | 2 +- .../flutter_error_integration_test.dart | 6 +- .../load_contexts_integration_test.dart | 11 +- .../load_contexts_integrations_test.dart | 49 ++-- .../integrations/load_image_list_test.dart | 4 +- .../native_app_start_integration_test.dart | 18 +- flutter/test/load_image_list_test.dart | 4 +- flutter/test/sentry_flutter_test.dart | 3 +- .../view_hierarchy_event_processor_test.dart | 8 +- hive/README.md | 7 +- hive/lib/src/version.dart | 2 +- hive/pubspec.yaml | 4 +- isar/README.md | 7 +- isar/lib/src/version.dart | 2 +- isar/pubspec.yaml | 4 +- logging/README.md | 9 +- logging/lib/src/version.dart | 2 +- logging/pubspec.yaml | 4 +- min_version_test/ios/Podfile | 2 +- sqflite/README.md | 9 +- sqflite/lib/src/version.dart | 2 +- sqflite/pubspec.yaml | 4 +- 122 files changed, 1016 insertions(+), 795 deletions(-) create mode 100644 .github/workflows/flutter_integration_test.yml create mode 100644 .github/workflows/testflight.yml create mode 100644 dart/example_web/analysis_options.yaml delete mode 100644 dart/lib/src/utils/iterable_extension.dart create mode 100644 dart/lib/src/utils/iterable_utils.dart create mode 100644 flutter/example/ios/Gemfile create mode 100644 flutter/example/ios/fastlane/Appfile create mode 100644 flutter/example/ios/fastlane/Fastfile create mode 100644 flutter/example/ios/fastlane/Matchfile diff --git a/.craft.yml b/.craft.yml index ac5e86e3c7..5ff7ad5d33 100644 --- a/.craft.yml +++ b/.craft.yml @@ -25,5 +25,4 @@ targets: pub:sentry_sqflite: pub:sentry_drift: pub:sentry_hive: - # Initial release on pub.dev needed first before uncommenting - # pub:sentry_isar: + pub:sentry_isar: diff --git a/.github/workflows/flutter_integration_test.yml b/.github/workflows/flutter_integration_test.yml new file mode 100644 index 0000000000..86bcb2e2dd --- /dev/null +++ b/.github/workflows/flutter_integration_test.yml @@ -0,0 +1,119 @@ +name: flutter integration tests +on: + # Currently broken, enable after fixing + workflow_dispatch + # push: + # branches: + # - main + # - release/** + # pull_request: + # paths-ignore: +# - 'file/**' + +jobs: + cancel-previous-workflow: + runs-on: ubuntu-latest + steps: + - name: Cancel Previous Runs + uses: styfle/cancel-workflow-action@b173b6ec0100793626c2d9e6b90435061f4fc3e5 # pin@0.11.0 + with: + access_token: ${{ github.token }} + + test-android: + runs-on: macos-latest + timeout-minutes: 30 + defaults: + run: + working-directory: ./flutter/example + strategy: + fail-fast: false + matrix: + sdk: [ "stable", "beta" ] + steps: + - name: checkout + uses: actions/checkout@v3 + + - uses: actions/setup-java@v3 + with: + distribution: "adopt" + java-version: "11" + + - uses: subosito/flutter-action@48cafc24713cca54bbe03cdc3a423187d413aafa # pin@v2.10.0 + with: + channel: ${{ matrix.sdk }} + + - name: flutter upgrade + run: flutter upgrade + + - name: flutter pub get + run: flutter pub get + + - name: Gradle cache + uses: gradle/gradle-build-action@982da8e78c05368c70dac0351bb82647a9e9a5d2 # pin@v2.11.1 + + - name: AVD cache + uses: actions/cache@v3 + id: avd-cache + with: + path: | + ~/.android/avd/* + ~/.android/adb* + key: avd-21 + + - name: create AVD and generate snapshot for caching + if: steps.avd-cache.outputs.cache-hit != 'true' + uses: reactivecircus/android-emulator-runner@d94c3fbe4fe6a29e4a5ba47c12fb47677c73656b #pin@v2.28.0 + with: + working-directory: ./flutter/example + api-level: 21 + force-avd-creation: false + emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none + disable-animations: false + arch: x86_64 + profile: Nexus 6 + script: echo 'Generated AVD snapshot for caching.' + + - name: launch android emulator & run android integration test + uses: reactivecircus/android-emulator-runner@d94c3fbe4fe6a29e4a5ba47c12fb47677c73656b #pin@v2.28.0 + with: + working-directory: ./flutter/example + api-level: 21 + force-avd-creation: false + emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none + disable-animations: true + arch: x86_64 + profile: Nexus 6 + script: flutter test integration_test/integration_test.dart --verbose + + test-ios: + runs-on: macos-13 + timeout-minutes: 30 + defaults: + run: + working-directory: ./flutter/example + strategy: + fail-fast: false + matrix: + # 'beta' is flaky because of https://github.com/flutter/flutter/issues/124340 + sdk: [ "stable" ] + steps: + - name: checkout + uses: actions/checkout@v3 + + - uses: subosito/flutter-action@48cafc24713cca54bbe03cdc3a423187d413aafa # pin@v2.10.0 + with: + channel: ${{ matrix.sdk }} + + - name: flutter upgrade + run: flutter upgrade + + - name: flutter pub get + run: flutter pub get + + - name: launch ios simulator + run: | + simulator_id=$(xcrun simctl create sentryPhone com.apple.CoreSimulator.SimDeviceType.iPhone-14 com.apple.CoreSimulator.SimRuntime.iOS-16-2) + xcrun simctl boot ${simulator_id} + + - name: run ios integration test + run: flutter test integration_test/integration_test.dart --verbose diff --git a/.github/workflows/flutter_test.yml b/.github/workflows/flutter_test.yml index e6d845bb72..0f3e9369b4 100644 --- a/.github/workflows/flutter_test.yml +++ b/.github/workflows/flutter_test.yml @@ -54,7 +54,7 @@ jobs: run: flutter pub get - name: Gradle cache - uses: gradle/gradle-build-action@8baac4c8ef753599f92eeb509c246d09d6250fa6 + uses: gradle/gradle-build-action@8baac4c8ef753599f92eeb509c246d09d6250fa6 # pin@v3.0.0 - name: AVD cache uses: actions/cache@v4 @@ -120,8 +120,7 @@ jobs: fail-fast: false matrix: sdk: ["stable", "beta"] - # TODO: remove ios for now, will be fixed in v8 - target: ["macos"] + target: ["ios", "macos"] steps: - name: checkout uses: actions/checkout@v4 diff --git a/.github/workflows/testflight.yml b/.github/workflows/testflight.yml new file mode 100644 index 0000000000..3e05b6afbb --- /dev/null +++ b/.github/workflows/testflight.yml @@ -0,0 +1,57 @@ +name: Upload to Testflight +on: + push: + branches: + - main + - release/** + pull_request: + paths: + - '.github/workflows/testflight.yml' + +jobs: + upload_to_testflight: + name: Build and Upload to Testflight + runs-on: macos-13 + steps: + - uses: actions/checkout@v4 + - uses: subosito/flutter-action@48cafc24713cca54bbe03cdc3a423187d413aafa # pin@v2.10.0 + - run: xcodes select 15.0.1 + - uses: ruby/setup-ruby@250fcd6a742febb1123a77a841497ccaa8b9e939 # pin@v1.152.0 + with: + ruby-version: '2.7.5' + bundler-cache: true + + - name: flutter + working-directory: ./flutter/example + run: | + flutter upgrade + flutter pub get + flutter build ios --no-codesign + + - name: Install Fastlane + working-directory: ./flutter/example/ios + run: bundle install + + - name: Bump, Build & Upload App to TestFlight + working-directory: ./flutter/example/ios + env: + APP_STORE_CONNECT_KEY_ID: ${{ secrets.APP_STORE_CONNECT_KEY_ID }} + APP_STORE_CONNECT_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }} + APP_STORE_CONNECT_KEY: ${{ secrets.APP_STORE_CONNECT_KEY }} + FASTLANE_BUNDLE_VERSION: ${{ github.run_number }} + FASTLANE_KEYCHAIN_PASSWORD: ${{ secrets.FASTLANE_KEYCHAIN_PASSWORD }} + MATCH_GIT_PRIVATE_KEY: ${{ secrets.MATCH_GIT_PRIVATE_KEY }} + MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} + MATCH_USERNAME: ${{ secrets.MATCH_USERNAME }} + SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} + SENTRY_LOG_LEVEL: DEBUG + run: | + bundle exec fastlane bump_build_number + bundle exec fastlane build_release + bundle exec fastlane upload_testflight + + - name: Upload Symbols to Sentry + working-directory: ./flutter/example + env: + SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} + run: flutter packages pub run sentry_dart_plugin \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 7dbc1dd7d2..8acd561d6d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,31 @@ # Changelog +## Unreleased + +This release contains breaking changes, please read the changelog carefully. + +*Changes from the latest v7 release are included in this major release* + +### Breaking Changes + +- Bump iOS minimum deployment target from **11** to **12** ([#1821](https://github.com/getsentry/sentry-dart/pull/1821)) +- Mark exceptions not handled by the user as `handled: false` ([#1535](https://github.com/getsentry/sentry-dart/pull/1535)) + - This will affect your release health data, and is therefore considered a breaking change. +- Refrain from overwriting the span status for unfinished spans ([#1577](https://github.com/getsentry/sentry-dart/pull/1577)) + - Older self-hosted sentry instances will drop transactions containing unfinished spans. + - This change was introduced in [relay/#1690](https://github.com/getsentry/relay/pull/1690) and released with [22.12.0](https://github.com/getsentry/relay/releases/tag/22.12.0) +- Do not leak extensions of external classes ([#1576](https://github.com/getsentry/sentry-dart/pull/1576)) +- Make `hint` non-nullable in `BeforeSendCallback`, `BeforeBreadcrumbCall` and `EventProcessor` ([#1574](https://github.com/getsentry/sentry-dart/pull/1574)) + - This will affect your callbacks, making this a breaking change. +- Load Device Contexts from Sentry Java ([#1616](https://github.com/getsentry/sentry-dart/pull/1616)) + - Now the device context from Android is available in `BeforeSendCallback` +- Set ip_address to {{auto}} by default, even if sendDefaultPII is disabled ([#1665](https://github.com/getsentry/sentry-dart/pull/1665)) + - Instead use the "Prevent Storing of IP Addresses" option in the "Security & Privacy" project settings on sentry.io + +### Features + +- Add support for exception aggregates ([#1866](https://github.com/getsentry/sentry-dart/pull/1866)) + ## 7.20.0 ### Build @@ -117,6 +143,40 @@ - [changelog](https://github.com/getsentry/sentry-cocoa/blob/main/CHANGELOG.md#8200) - [diff](https://github.com/getsentry/sentry-cocoa/compare/8.19.0...8.20.0) +## 8.0.0-beta.2 + +### Breaking Changes + +- Bump iOS minimum deployment target from **11** to **12** ([#1821](https://github.com/getsentry/sentry-dart/pull/1821)) +- Mark exceptions not handled by the user as `handled: false` ([#1535](https://github.com/getsentry/sentry-dart/pull/1535)) + - This will affect your release health data, and is therefore considered a breaking change. +- Refrain from overwriting the span status for unfinished spans ([#1577](https://github.com/getsentry/sentry-dart/pull/1577)) + - Older self-hosted sentry instances will drop transactions containing unfinished spans. + - This change was introduced in [relay/#1690](https://github.com/getsentry/relay/pull/1690) and released with [22.12.0](https://github.com/getsentry/relay/releases/tag/22.12.0) +- Do not leak extensions of external classes ([#1576](https://github.com/getsentry/sentry-dart/pull/1576)) +- Make `hint` non-nullable in `BeforeSendCallback`, `BeforeBreadcrumbCall` and `EventProcessor` ([#1574](https://github.com/getsentry/sentry-dart/pull/1574)) + - This will affect your callbacks, making this a breaking change. +- Load Device Contexts from Sentry Java ([#1616](https://github.com/getsentry/sentry-dart/pull/1616)) + - Now the device context from Android is available in `BeforeSendCallback` +- Set ip_address to {{auto}} by default, even if sendDefaultPII is disabled ([#1665](https://github.com/getsentry/sentry-dart/pull/1665)) + - Instead use the "Prevent Storing of IP Addresses" option in the "Security & Privacy" project settings on sentry.io + +### Fixes + +- Remove Flutter dependency from Drift integration ([#1867](https://github.com/getsentry/sentry-dart/pull/1867)) +- Remove dead code, cold start bool is now always present ([#1861](https://github.com/getsentry/sentry-dart/pull/1861)) +- Fix iOS "Arithmetic Overflow" ([#1874](https://github.com/getsentry/sentry-dart/pull/1874)) + +### Dependencies + +- Bump Cocoa SDK from v8.19.0 to v8.20.0 ([#1856](https://github.com/getsentry/sentry-dart/pull/1856)) + - [changelog](https://github.com/getsentry/sentry-cocoa/blob/main/CHANGELOG.md#8200) + - [diff](https://github.com/getsentry/sentry-cocoa/compare/8.19.0...8.20.0) + +## 8.0.0-beta.1 + +This release is replaced by `8.0.0-beta.2` + ## 7.16.0 ### Features diff --git a/dart/README.md b/dart/README.md index e3cf3b6bb6..a6582faa16 100644 --- a/dart/README.md +++ b/dart/README.md @@ -184,8 +184,11 @@ Read more about [Automatic Instrumentation](https://docs.sentry.io/platforms/dar #### Resources -* [![Documentation](https://img.shields.io/badge/documentation-sentry.io-green.svg)](https://docs.sentry.io/platforms/dart/) -* [![Forum](https://img.shields.io/badge/forum-sentry-green.svg)](https://forum.sentry.io/c/sdks) -* [![Discord](https://img.shields.io/discord/621778831602221064)](https://discord.gg/Ww9hbqr) +#### Resources + +* [![Flutter docs](https://img.shields.io/badge/documentation-sentry.io-green.svg?label=flutter%20docs)](https://docs.sentry.io/platforms/flutter/) +* [![Dart docs](https://img.shields.io/badge/documentation-sentry.io-green.svg?label=dart%20docs)](https://docs.sentry.io/platforms/dart/) +* [![Discussions](https://img.shields.io/github/discussions/getsentry/sentry-dart.svg)](https://github.com/getsentry/sentry-dart/discussions) +* [![Discord Chat](https://img.shields.io/discord/621778831602221064?logo=discord&logoColor=ffffff&color=7389D8)](https://discord.gg/PXa5Apfe7K) * [![Stack Overflow](https://img.shields.io/badge/stack%20overflow-sentry-green.svg)](https://stackoverflow.com/questions/tagged/sentry) -* [![Twitter Follow](https://img.shields.io/twitter/follow/getsentry?label=getsentry&style=social)](https://twitter.com/intent/follow?screen_name=getsentry) +* [![Twitter Follow](https://img.shields.io/twitter/follow/getsentry?label=getsentry&style=social)](https://twitter.com/intent/follow?screen_name=getsentry) \ No newline at end of file diff --git a/dart/example/bin/example.dart b/dart/example/bin/example.dart index 5163f341f7..d7530f5874 100644 --- a/dart/example/bin/example.dart +++ b/dart/example/bin/example.dart @@ -104,7 +104,7 @@ Future decode() async { class TagEventProcessor implements EventProcessor { @override - SentryEvent? apply(SentryEvent event, {hint}) { + SentryEvent? apply(SentryEvent event, hint) { return event..tags?.addAll({'page-locale': 'en-us'}); } } diff --git a/dart/example_web/analysis_options.yaml b/dart/example_web/analysis_options.yaml new file mode 100644 index 0000000000..be16ace7d1 --- /dev/null +++ b/dart/example_web/analysis_options.yaml @@ -0,0 +1,5 @@ +include: package:lints/recommended.yaml + +analyzer: + errors: + path_does_not_exist: ignore diff --git a/dart/example_web/pubspec.yaml b/dart/example_web/pubspec.yaml index 2363aa83bb..7bcb64d06e 100644 --- a/dart/example_web/pubspec.yaml +++ b/dart/example_web/pubspec.yaml @@ -8,7 +8,7 @@ environment: dependencies: sentry: - path: ../../dart + path: ../../dart/ dev_dependencies: build_runner: ^2.4.2 diff --git a/dart/example_web/web/main.dart b/dart/example_web/web/main.dart index c396be5e83..3034effe9b 100644 --- a/dart/example_web/web/main.dart +++ b/dart/example_web/web/main.dart @@ -129,7 +129,7 @@ Future parseData() async { class TagEventProcessor implements EventProcessor { @override - SentryEvent? apply(SentryEvent event, {hint}) { + SentryEvent? apply(SentryEvent event, Hint hint) { return event..tags?.addAll({'page-locale': 'en-us'}); } } diff --git a/dart/lib/src/client_reports/discard_reason.dart b/dart/lib/src/client_reports/discard_reason.dart index 1b990f8dd2..81c3a45dd0 100644 --- a/dart/lib/src/client_reports/discard_reason.dart +++ b/dart/lib/src/client_reports/discard_reason.dart @@ -12,24 +12,3 @@ enum DiscardReason { cacheOverflow, rateLimitBackoff, } - -extension OutcomeExtension on DiscardReason { - String toStringValue() { - switch (this) { - case DiscardReason.beforeSend: - return 'before_send'; - case DiscardReason.eventProcessor: - return 'event_processor'; - case DiscardReason.sampleRate: - return 'sample_rate'; - case DiscardReason.networkError: - return 'network_error'; - case DiscardReason.queueOverflow: - return 'queue_overflow'; - case DiscardReason.cacheOverflow: - return 'cache_overflow'; - case DiscardReason.rateLimitBackoff: - return 'ratelimit_backoff'; - } - } -} diff --git a/dart/lib/src/client_reports/discarded_event.dart b/dart/lib/src/client_reports/discarded_event.dart index 0b989aa4cf..01caa31ca2 100644 --- a/dart/lib/src/client_reports/discarded_event.dart +++ b/dart/lib/src/client_reports/discarded_event.dart @@ -13,9 +13,55 @@ class DiscardedEvent { Map toJson() { return { - 'reason': reason.toStringValue(), - 'category': category.toStringValue(), + 'reason': reason._toStringValue(), + 'category': category._toStringValue(), 'quantity': quantity, }; } } + +extension _OutcomeExtension on DiscardReason { + String _toStringValue() { + switch (this) { + case DiscardReason.beforeSend: + return 'before_send'; + case DiscardReason.eventProcessor: + return 'event_processor'; + case DiscardReason.sampleRate: + return 'sample_rate'; + case DiscardReason.networkError: + return 'network_error'; + case DiscardReason.queueOverflow: + return 'queue_overflow'; + case DiscardReason.cacheOverflow: + return 'cache_overflow'; + case DiscardReason.rateLimitBackoff: + return 'ratelimit_backoff'; + } + } +} + +extension _DataCategoryExtension on DataCategory { + String _toStringValue() { + switch (this) { + case DataCategory.all: + return '__all__'; + case DataCategory.dataCategoryDefault: + return 'default'; + case DataCategory.error: + return 'error'; + case DataCategory.session: + return 'session'; + case DataCategory.transaction: + return 'transaction'; + case DataCategory.attachment: + return 'attachment'; + case DataCategory.security: + return 'security'; + case DataCategory.unknown: + return 'unknown'; + case DataCategory.metricBucket: + return 'metric_bucket'; + } + } +} diff --git a/dart/lib/src/event_processor.dart b/dart/lib/src/event_processor.dart index 94fcd77fd8..45005d7b0e 100644 --- a/dart/lib/src/event_processor.dart +++ b/dart/lib/src/event_processor.dart @@ -8,7 +8,7 @@ import 'protocol.dart'; /// null in case the event will be dropped and not sent. abstract class EventProcessor { FutureOr apply( - SentryEvent event, { - Hint? hint, - }); + SentryEvent event, + Hint hint, + ); } diff --git a/dart/lib/src/event_processor/deduplication_event_processor.dart b/dart/lib/src/event_processor/deduplication_event_processor.dart index 5c3bd4606e..8706082cf5 100644 --- a/dart/lib/src/event_processor/deduplication_event_processor.dart +++ b/dart/lib/src/event_processor/deduplication_event_processor.dart @@ -26,7 +26,7 @@ class DeduplicationEventProcessor implements EventProcessor { final SentryOptions _options; @override - SentryEvent? apply(SentryEvent event, {Hint? hint}) { + SentryEvent? apply(SentryEvent event, Hint hint) { if (event is SentryTransaction) { return event; } diff --git a/dart/lib/src/event_processor/enricher/io_enricher_event_processor.dart b/dart/lib/src/event_processor/enricher/io_enricher_event_processor.dart index 47e3481144..52243a8572 100644 --- a/dart/lib/src/event_processor/enricher/io_enricher_event_processor.dart +++ b/dart/lib/src/event_processor/enricher/io_enricher_event_processor.dart @@ -16,7 +16,7 @@ class IoEnricherEventProcessor implements EnricherEventProcessor { final SentryOptions _options; @override - SentryEvent? apply(SentryEvent event, {Hint? hint}) { + SentryEvent? apply(SentryEvent event, Hint hint) { // If there's a native integration available, it probably has better // information available than Flutter. diff --git a/dart/lib/src/event_processor/enricher/web_enricher_event_processor.dart b/dart/lib/src/event_processor/enricher/web_enricher_event_processor.dart index f7681eeeaf..e51cff4b71 100644 --- a/dart/lib/src/event_processor/enricher/web_enricher_event_processor.dart +++ b/dart/lib/src/event_processor/enricher/web_enricher_event_processor.dart @@ -21,7 +21,7 @@ class WebEnricherEventProcessor implements EnricherEventProcessor { final SentryOptions _options; @override - SentryEvent? apply(SentryEvent event, {Hint? hint}) { + SentryEvent? apply(SentryEvent event, Hint hint) { // Web has no native integration, so no need to check for it final contexts = event.contexts.copyWith( diff --git a/dart/lib/src/event_processor/exception/io_exception_event_processor.dart b/dart/lib/src/event_processor/exception/io_exception_event_processor.dart index 0f7763f35e..bb4049c00e 100644 --- a/dart/lib/src/event_processor/exception/io_exception_event_processor.dart +++ b/dart/lib/src/event_processor/exception/io_exception_event_processor.dart @@ -14,7 +14,7 @@ class IoExceptionEventProcessor implements ExceptionEventProcessor { final SentryOptions _options; @override - SentryEvent? apply(SentryEvent event, {Hint? hint}) { + SentryEvent? apply(SentryEvent event, Hint hint) { final throwable = event.throwable; if (throwable is HttpException) { return _applyHttpException(throwable, event); diff --git a/dart/lib/src/event_processor/exception/web_exception_event_processor.dart b/dart/lib/src/event_processor/exception/web_exception_event_processor.dart index ad57c9f5c2..6ce3be0fe0 100644 --- a/dart/lib/src/event_processor/exception/web_exception_event_processor.dart +++ b/dart/lib/src/event_processor/exception/web_exception_event_processor.dart @@ -8,5 +8,5 @@ ExceptionEventProcessor exceptionEventProcessor(SentryOptions _) => class WebExcptionEventProcessor implements ExceptionEventProcessor { @override - SentryEvent apply(SentryEvent event, {Hint? hint}) => event; + SentryEvent apply(SentryEvent event, Hint hint) => event; } diff --git a/dart/lib/src/hint.dart b/dart/lib/src/hint.dart index 41ea7a0deb..9df1b38365 100644 --- a/dart/lib/src/hint.dart +++ b/dart/lib/src/hint.dart @@ -12,8 +12,8 @@ import 'sentry_options.dart'; /// Example: /// /// ```dart -/// options.beforeSend = (event, {hint}) { -/// final syntheticException = hint?.get(TypeCheckHint.syntheticException); +/// options.beforeSend = (event, hint) { +/// final syntheticException = hint.get(TypeCheckHint.syntheticException); /// if (syntheticException is FlutterErrorDetails) { /// // Do something with hint data /// } @@ -29,14 +29,14 @@ import 'sentry_options.dart'; /// ```dart /// import 'dart:convert'; /// -/// options.beforeSend = (event, {hint}) { +/// options.beforeSend = (event, hint) { /// final text = 'This event should not be sent happen in prod. Investigate.'; /// final textAttachment = SentryAttachment.fromIntList( /// utf8.encode(text), /// 'event_info.txt', /// contentType: 'text/plain', /// ); -/// hint?.attachments.add(textAttachment); +/// hint.attachments.add(textAttachment); /// return event; /// }; /// ``` diff --git a/dart/lib/src/http_client/failed_request_client.dart b/dart/lib/src/http_client/failed_request_client.dart index dc07f407ed..446b88826c 100644 --- a/dart/lib/src/http_client/failed_request_client.dart +++ b/dart/lib/src/http_client/failed_request_client.dart @@ -138,7 +138,7 @@ class FailedRequestClient extends BaseClient { // Only check `failedRequestStatusCodes` & `failedRequestTargets` if no exception was thrown. if (exception == null) { - if (!failedRequestStatusCodes.containsStatusCode(statusCode)) { + if (!failedRequestStatusCodes._containsStatusCode(statusCode)) { return; } if (!containsTargetOrMatchesRegExp( @@ -249,7 +249,7 @@ class FailedRequestClient extends BaseClient { } extension _ListX on List { - bool containsStatusCode(int? statusCode) { + bool _containsStatusCode(int? statusCode) { if (statusCode == null) { return false; } diff --git a/dart/lib/src/protocol/mechanism.dart b/dart/lib/src/protocol/mechanism.dart index 2c06c954f6..22a6356800 100644 --- a/dart/lib/src/protocol/mechanism.dart +++ b/dart/lib/src/protocol/mechanism.dart @@ -44,6 +44,38 @@ class Mechanism { /// This may be because they are created at a central place (like a crash handler), and are all called the same: Error, Segfault etc. When the flag is set, Sentry will then try to use other information (top in-app frame function) rather than exception type and value in the UI for the primary event display. This flag should be set for all "segfaults" for instance as every single error group would look very similar otherwise. final bool? synthetic; + /// An optional boolean value, set `true` when the exception is the exception + /// group type specific to the platform or language. + /// The default is false when omitted. + /// For example, exceptions of type [PlatformException](https://api.flutter.dev/flutter/services/PlatformException-class.html) + /// have set it to `true`, others are set to `false`. + final bool? isExceptionGroup; + + /// An optional string value describing the source of the exception. + /// + /// The SDK should populate this with the name of the property or attribute of + /// the parent exception that this exception was acquired from. + /// In the case of an array, it should include the zero-based array index as + /// well. + final String? source; + + /// An optional numeric value providing an ID for the exception relative to + /// this specific event. + /// + /// The SDK should assign simple incrementing integers to each exception in + /// the tree, starting with 0 for the root of the tree. + /// In other words, when flattened into the list provided in the exception + /// values on the event, the last exception in the list should have ID 0, + /// the previous one should have ID 1, the next previous should have ID 2, etc. + final int? exceptionId; + + /// An optional numeric value pointing at the [exceptionId] that is the parent + /// of this exception. + /// + /// The SDK should assign this to all exceptions except the root exception + /// (the last to be listed in the exception values). + final int? parentId; + Mechanism({ required this.type, this.description, @@ -52,6 +84,10 @@ class Mechanism { this.synthetic, Map? meta, Map? data, + this.isExceptionGroup, + this.source, + this.exceptionId, + this.parentId, }) : _meta = meta != null ? Map.from(meta) : null, _data = data != null ? Map.from(data) : null; @@ -63,6 +99,10 @@ class Mechanism { Map? meta, Map? data, bool? synthetic, + bool? isExceptionGroup, + String? source, + int? exceptionId, + int? parentId, }) => Mechanism( type: type ?? this.type, @@ -72,6 +112,10 @@ class Mechanism { meta: meta ?? this.meta, data: data ?? this.data, synthetic: synthetic ?? this.synthetic, + isExceptionGroup: isExceptionGroup ?? this.isExceptionGroup, + source: source ?? this.source, + exceptionId: exceptionId ?? this.exceptionId, + parentId: parentId ?? this.parentId, ); /// Deserializes a [Mechanism] from JSON [Map]. @@ -94,6 +138,10 @@ class Mechanism { meta: meta, data: data, synthetic: json['synthetic'], + isExceptionGroup: json['is_exception_group'], + source: json['source'], + exceptionId: json['exception_id'], + parentId: json['parent_id'], ); } @@ -107,6 +155,10 @@ class Mechanism { if (_meta?.isNotEmpty ?? false) 'meta': _meta, if (_data?.isNotEmpty ?? false) 'data': _data, if (synthetic != null) 'synthetic': synthetic, + if (isExceptionGroup != null) 'is_exception_group': isExceptionGroup, + if (source != null) 'source': source, + if (exceptionId != null) 'exception_id': exceptionId, + if (parentId != null) 'parent_id': parentId, }; } } diff --git a/dart/lib/src/protocol/sentry_request.dart b/dart/lib/src/protocol/sentry_request.dart index 9689c8a974..b5ee7d003c 100644 --- a/dart/lib/src/protocol/sentry_request.dart +++ b/dart/lib/src/protocol/sentry_request.dart @@ -1,6 +1,6 @@ import 'package:meta/meta.dart'; -import '../utils/iterable_extension.dart'; +import '../utils/iterable_utils.dart'; import '../utils/http_sanitizer.dart'; /// The Request interface contains information on a HTTP request related to the event. @@ -85,9 +85,10 @@ class SentryRequest { _headers = headers != null ? Map.from(headers) : null, // Look for a 'Set-Cookie' header (case insensitive) if not given. cookies = cookies ?? - headers?.entries - .firstWhereOrNull((e) => e.key.toLowerCase() == 'cookie') - ?.value, + IterableUtils.firstWhereOrNull( + headers?.entries, + (MapEntry e) => e.key.toLowerCase() == 'cookie', + )?.value, _env = env != null ? Map.from(env) : null, _other = other != null ? Map.from(other) : null; diff --git a/dart/lib/src/protocol/sentry_response.dart b/dart/lib/src/protocol/sentry_response.dart index 91faaa37eb..6008ea8730 100644 --- a/dart/lib/src/protocol/sentry_response.dart +++ b/dart/lib/src/protocol/sentry_response.dart @@ -1,6 +1,6 @@ import 'package:meta/meta.dart'; import 'contexts.dart'; -import '../utils/iterable_extension.dart'; +import '../utils/iterable_utils.dart'; /// The response interface contains information on a HTTP request related to the event. @immutable @@ -53,9 +53,11 @@ class SentryResponse { _headers = headers != null ? Map.from(headers) : null, // Look for a 'Set-Cookie' header (case insensitive) if not given. cookies = cookies ?? - headers?.entries - .firstWhereOrNull((e) => e.key.toLowerCase() == 'set-cookie') - ?.value; + IterableUtils.firstWhereOrNull( + headers?.entries, + (MapEntry e) => + e.key.toLowerCase() == 'set-cookie', + )?.value; /// Deserializes a [SentryResponse] from JSON [Map]. factory SentryResponse.fromJson(Map json) { diff --git a/dart/lib/src/run_zoned_guarded_integration.dart b/dart/lib/src/run_zoned_guarded_integration.dart index 05ef5be2b0..20f0857e3b 100644 --- a/dart/lib/src/run_zoned_guarded_integration.dart +++ b/dart/lib/src/run_zoned_guarded_integration.dart @@ -44,8 +44,8 @@ class RunZonedGuardedIntegration extends Integration { stackTrace: stackTrace, ); - // runZonedGuarded doesn't crash the App. - final mechanism = Mechanism(type: 'runZonedGuarded', handled: true); + // runZonedGuarded doesn't crash the app, but is not handled by the user. + final mechanism = Mechanism(type: 'runZonedGuarded', handled: false); final throwableMechanism = ThrowableMechanism(mechanism, exception); final event = SentryEvent( diff --git a/dart/lib/src/scope.dart b/dart/lib/src/scope.dart index 4f36895131..3fef9a92a2 100644 --- a/dart/lib/src/scope.dart +++ b/dart/lib/src/scope.dart @@ -150,7 +150,7 @@ class Scope { Scope(this._options); - Breadcrumb? _addBreadCrumbSync(Breadcrumb breadcrumb, {Hint? hint}) { + Breadcrumb? _addBreadCrumbSync(Breadcrumb breadcrumb, Hint hint) { // bail out if maxBreadcrumbs is zero if (_options.maxBreadcrumbs == 0) { return null; @@ -162,7 +162,7 @@ class Scope { try { processedBreadcrumb = _options.beforeBreadcrumb!( processedBreadcrumb, - hint: hint, + hint, ); if (processedBreadcrumb == null) { _options.logger( @@ -196,7 +196,7 @@ class Scope { /// Adds a breadcrumb to the breadcrumbs queue Future addBreadcrumb(Breadcrumb breadcrumb, {Hint? hint}) async { - final addedBreadcrumb = _addBreadCrumbSync(breadcrumb, hint: hint); + final addedBreadcrumb = _addBreadCrumbSync(breadcrumb, hint ?? Hint()); if (addedBreadcrumb != null) { await _callScopeObservers((scopeObserver) async => await scopeObserver.addBreadcrumb(addedBreadcrumb)); @@ -282,9 +282,9 @@ class Scope { } Future applyToEvent( - SentryEvent event, { - Hint? hint, - }) async { + SentryEvent event, + Hint hint, + ) async { event = event.copyWith( transaction: event.transaction ?? transaction, user: _mergeUsers(user, event.user), @@ -332,7 +332,7 @@ class Scope { SentryEvent? processedEvent = event; for (final processor in _eventProcessors) { try { - final e = processor.apply(processedEvent!, hint: hint); + final e = processor.apply(processedEvent!, hint); if (e is Future) { processedEvent = await e; } else { @@ -442,7 +442,7 @@ class Scope { } for (final breadcrumb in List.from(_breadcrumbs)) { - clone._addBreadCrumbSync(breadcrumb); + clone._addBreadCrumbSync(breadcrumb, Hint()); } for (final eventProcessor in List.from(_eventProcessors)) { diff --git a/dart/lib/src/sentry_client.dart b/dart/lib/src/sentry_client.dart index 47c6fc0d8b..59610993ad 100644 --- a/dart/lib/src/sentry_client.dart +++ b/dart/lib/src/sentry_client.dart @@ -96,7 +96,7 @@ class SentryClient { hint ??= Hint(); if (scope != null) { - preparedEvent = await scope.applyToEvent(preparedEvent, hint: hint); + preparedEvent = await scope.applyToEvent(preparedEvent, hint); } else { _options.logger( SentryLevel.debug, 'No scope to apply on event was provided'); @@ -109,8 +109,8 @@ class SentryClient { preparedEvent = await _runEventProcessors( preparedEvent, + hint, eventProcessors: _options.eventProcessors, - hint: hint, ); // dropped by event processors @@ -120,7 +120,7 @@ class SentryClient { preparedEvent = await _runBeforeSend( preparedEvent, - hint: hint, + hint, ); // dropped by beforeSend @@ -128,8 +128,6 @@ class SentryClient { return _sentryId; } - preparedEvent = _eventWithoutBreadcrumbsIfNeeded(preparedEvent); - var attachments = List.from(scope?.attachments ?? []); attachments.addAll(hint.attachments); var screenshot = hint.screenshot; @@ -177,7 +175,7 @@ class SentryClient { platform: event.platform ?? sdkPlatform(_options.platformChecker.isWeb), ); - event = _applyDefaultPii(event); + event = _createUserOrSetDefaultIpAddress(event); if (event is SentryTransaction) { return event; @@ -257,20 +255,13 @@ class SentryClient { return event; } - /// This modifies the users IP address according - /// to [SentryOptions.sendDefaultPii]. - SentryEvent _applyDefaultPii(SentryEvent event) { - if (!_options.sendDefaultPii) { - return event; - } + SentryEvent _createUserOrSetDefaultIpAddress(SentryEvent event) { var user = event.user; if (user == null) { - user = SentryUser(ipAddress: _defaultIpAddress); - return event.copyWith(user: user); + return event.copyWith(user: SentryUser(ipAddress: _defaultIpAddress)); } else if (event.user?.ipAddress == null) { return event.copyWith(user: user.copyWith(ipAddress: _defaultIpAddress)); } - return event; } @@ -321,9 +312,11 @@ class SentryClient { SentryTransaction? preparedTransaction = _prepareEvent(transaction) as SentryTransaction; + final hint = Hint(); + if (scope != null) { - preparedTransaction = - await scope.applyToEvent(preparedTransaction) as SentryTransaction?; + preparedTransaction = await scope.applyToEvent(preparedTransaction, hint) + as SentryTransaction?; } else { _options.logger( SentryLevel.debug, 'No scope to apply on transaction was provided'); @@ -336,6 +329,7 @@ class SentryClient { preparedTransaction = await _runEventProcessors( preparedTransaction, + hint, eventProcessors: _options.eventProcessors, ) as SentryTransaction?; @@ -345,15 +339,13 @@ class SentryClient { } preparedTransaction = - await _runBeforeSend(preparedTransaction) as SentryTransaction?; + await _runBeforeSend(preparedTransaction, hint) as SentryTransaction?; // dropped by beforeSendTransaction if (preparedTransaction == null) { return _sentryId; } - preparedTransaction = _eventWithoutBreadcrumbsIfNeeded(preparedTransaction); - final attachments = scope?.attachments .where((element) => element.addToTransactions) .toList(); @@ -407,9 +399,9 @@ class SentryClient { } Future _runBeforeSend( - SentryEvent event, { - Hint? hint, - }) async { + SentryEvent event, + Hint hint, + ) async { SentryEvent? eventOrTransaction = event; final beforeSend = _options.beforeSend; @@ -426,7 +418,7 @@ class SentryClient { eventOrTransaction = e; } } else if (beforeSend != null) { - final e = beforeSend(event, hint: hint); + final e = beforeSend(event, hint); if (e is Future) { eventOrTransaction = await e; } else { @@ -457,14 +449,14 @@ class SentryClient { } Future _runEventProcessors( - SentryEvent event, { - Hint? hint, + SentryEvent event, + Hint hint, { required List eventProcessors, }) async { SentryEvent? processedEvent = event; for (final processor in eventProcessors) { try { - final e = processor.apply(processedEvent!, hint: hint); + final e = processor.apply(processedEvent!, hint); if (e is Future) { processedEvent = await e; } else { @@ -507,40 +499,6 @@ class SentryClient { _options.recorder.recordLostEvent(reason, category); } - T _eventWithoutBreadcrumbsIfNeeded(T event) { - if (_shouldRemoveBreadcrumbs(event)) { - return event.copyWith(breadcrumbs: []) as T; - } else { - return event; - } - } - - /// We do this to avoid duplicate breadcrumbs on Android as sentry-android applies the breadcrumbs - /// from the native scope onto every envelope sent through it. This scope will contain the breadcrumbs - /// sent through the scope sync feature. This causes duplicate breadcrumbs. - /// We then remove the breadcrumbs in all cases but if it is handled == false, - /// this is a signal that the app would crash and android would lose the breadcrumbs by the time the app is restarted to read - /// the envelope. - bool _shouldRemoveBreadcrumbs(SentryEvent event) { - if (_options.platformChecker.isWeb) { - return false; - } - - final isAndroid = _options.platformChecker.platform.isAndroid; - final enableScopeSync = _options.enableScopeSync; - - if (!isAndroid || !enableScopeSync) { - return false; - } - - final mechanisms = - (event.exceptions ?? []).map((e) => e.mechanism).whereType(); - final hasNoMechanism = mechanisms.isEmpty; - final hasOnlyHandledMechanism = - mechanisms.every((e) => (e.handled ?? true)); - return hasNoMechanism || hasOnlyHandledMechanism; - } - Future _attachClientReportsAndSend(SentryEnvelope envelope) { final clientReport = _options.recorder.flush(); envelope.addClientReport(clientReport); diff --git a/dart/lib/src/sentry_isolate.dart b/dart/lib/src/sentry_isolate.dart index 0af2978e24..9998544d5b 100644 --- a/dart/lib/src/sentry_isolate.dart +++ b/dart/lib/src/sentry_isolate.dart @@ -69,9 +69,10 @@ class SentryIsolate { stackTrace == null ? null : StackTrace.fromString(stackTrace), ); - // Isolate errors don't crash the App. - final mechanism = Mechanism(type: 'isolateError', handled: true); + // Isolate errors don't crash the app, but is not handled by the user. + final mechanism = Mechanism(type: 'isolateError', handled: false); final throwableMechanism = ThrowableMechanism(mechanism, throwable); + final event = SentryEvent( throwable: throwableMechanism, level: hub.options.markAutomaticallyCollectedErrorsAsFatal diff --git a/dart/lib/src/sentry_options.dart b/dart/lib/src/sentry_options.dart index eea642ae48..956f81c056 100644 --- a/dart/lib/src/sentry_options.dart +++ b/dart/lib/src/sentry_options.dart @@ -529,9 +529,9 @@ class SentryOptions { /// This function is called with an SDK specific event object and can return a modified event /// object or nothing to skip reporting the event typedef BeforeSendCallback = FutureOr Function( - SentryEvent event, { - Hint? hint, -}); + SentryEvent event, + Hint hint, +); /// This function is called with an SDK specific transaction object and can return a modified transaction /// object or nothing to skip reporting the transaction @@ -542,9 +542,9 @@ typedef BeforeSendTransactionCallback = FutureOr Function( /// This function is called with an SDK specific breadcrumb object before the breadcrumb is added /// to the scope. When nothing is returned from the function, the breadcrumb is dropped typedef BeforeBreadcrumbCallback = Breadcrumb? Function( - Breadcrumb? breadcrumb, { - Hint? hint, -}); + Breadcrumb? breadcrumb, + Hint hint, +); /// This function is called right before a metric is about to be emitted. /// Can return true to emit the metric, or false to drop it. diff --git a/dart/lib/src/sentry_tracer.dart b/dart/lib/src/sentry_tracer.dart index d9ea75d256..2326db0716 100644 --- a/dart/lib/src/sentry_tracer.dart +++ b/dart/lib/src/sentry_tracer.dart @@ -100,15 +100,6 @@ class SentryTracer extends ISentrySpan { _children.removeWhere( (span) => !_hasSpanSuitableTimestamps(span, commonEndTimestamp)); - // finish unfinished spans otherwise transaction gets dropped - final spansToBeFinished = _children.where((span) => !span.finished); - for (final span in spansToBeFinished) { - await span.finish( - status: SpanStatus.deadlineExceeded(), - endTimestamp: commonEndTimestamp, - ); - } - var _rootEndTimestamp = commonEndTimestamp; // Trim the end timestamp of the transaction to the very last timestamp of child spans diff --git a/dart/lib/src/transport/data_category.dart b/dart/lib/src/transport/data_category.dart index f21da18ed7..ecdb1c9500 100644 --- a/dart/lib/src/transport/data_category.dart +++ b/dart/lib/src/transport/data_category.dart @@ -10,50 +10,3 @@ enum DataCategory { metricBucket, unknown } - -extension DataCategoryExtension on DataCategory { - static DataCategory fromStringValue(String stringValue) { - switch (stringValue) { - case '__all__': - return DataCategory.all; - case 'default': - return DataCategory.dataCategoryDefault; - case 'error': - return DataCategory.error; - case 'session': - return DataCategory.session; - case 'transaction': - return DataCategory.transaction; - case 'attachment': - return DataCategory.attachment; - case 'security': - return DataCategory.security; - case 'metric_bucket': - return DataCategory.metricBucket; - } - return DataCategory.unknown; - } - - String toStringValue() { - switch (this) { - case DataCategory.all: - return '__all__'; - case DataCategory.dataCategoryDefault: - return 'default'; - case DataCategory.error: - return 'error'; - case DataCategory.session: - return 'session'; - case DataCategory.transaction: - return 'transaction'; - case DataCategory.attachment: - return 'attachment'; - case DataCategory.security: - return 'security'; - case DataCategory.metricBucket: - return 'metric_bucket'; - case DataCategory.unknown: - return 'unknown'; - } - } -} diff --git a/dart/lib/src/transport/rate_limit_parser.dart b/dart/lib/src/transport/rate_limit_parser.dart index 03391e0210..1cf1a7e3e1 100644 --- a/dart/lib/src/transport/rate_limit_parser.dart +++ b/dart/lib/src/transport/rate_limit_parser.dart @@ -30,8 +30,8 @@ class RateLimitParser { if (allCategories.isNotEmpty) { final categoryValues = allCategories.split(';'); for (final categoryValue in categoryValues) { - final category = DataCategoryExtension.fromStringValue(categoryValue); - // Metric buckets rate limit can have namespaces + final category = _DataCategoryExtension._fromStringValue( + categoryValue); // Metric buckets rate limit can have namespaces if (category == DataCategory.metricBucket) { final namespaces = durationAndCategories.length > 4 ? durationAndCategories[4] @@ -67,3 +67,27 @@ class RateLimitParser { } } } + +extension _DataCategoryExtension on DataCategory { + static DataCategory _fromStringValue(String stringValue) { + switch (stringValue) { + case '__all__': + return DataCategory.all; + case 'default': + return DataCategory.dataCategoryDefault; + case 'error': + return DataCategory.error; + case 'session': + return DataCategory.session; + case 'transaction': + return DataCategory.transaction; + case 'attachment': + return DataCategory.attachment; + case 'security': + return DataCategory.security; + case 'metric_bucket': + return DataCategory.metricBucket; + } + return DataCategory.unknown; + } +} diff --git a/dart/lib/src/utils/http_sanitizer.dart b/dart/lib/src/utils/http_sanitizer.dart index c131cc0c4e..2e5de505a9 100644 --- a/dart/lib/src/utils/http_sanitizer.dart +++ b/dart/lib/src/utils/http_sanitizer.dart @@ -60,7 +60,7 @@ class HttpSanitizer { } } -extension UriPath on Uri { +extension _UriPath on Uri { String _urlWithRedactedAuth() { var buffer = ''; if (scheme.isNotEmpty) { @@ -78,6 +78,7 @@ extension UriPath on Uri { } } +@internal extension SanitizedSentryRequest on SentryRequest { SentryRequest sanitized() { final urlDetails = HttpSanitizer.sanitizeUrl(url) ?? UrlDetails(); diff --git a/dart/lib/src/utils/isolate_utils.dart b/dart/lib/src/utils/isolate_utils.dart index ce523b0d63..3e9c4b20bc 100644 --- a/dart/lib/src/utils/isolate_utils.dart +++ b/dart/lib/src/utils/isolate_utils.dart @@ -1,4 +1,7 @@ +import 'package:meta/meta.dart'; + import '_io_get_isolate_name.dart' if (dart.library.html) '_web_get_isolate_name.dart' as isolate_getter; +@internal String? getIsolateName() => isolate_getter.getIsolateName(); diff --git a/dart/lib/src/utils/iterable_extension.dart b/dart/lib/src/utils/iterable_extension.dart deleted file mode 100644 index 34c2c60943..0000000000 --- a/dart/lib/src/utils/iterable_extension.dart +++ /dev/null @@ -1,8 +0,0 @@ -extension IterableExtension on Iterable { - T? firstWhereOrNull(bool Function(T item) predicate) { - for (var item in this) { - if (predicate(item)) return item; - } - return null; - } -} diff --git a/dart/lib/src/utils/iterable_utils.dart b/dart/lib/src/utils/iterable_utils.dart new file mode 100644 index 0000000000..c2fb5e5c69 --- /dev/null +++ b/dart/lib/src/utils/iterable_utils.dart @@ -0,0 +1,17 @@ +import 'package:meta/meta.dart'; + +@internal +class IterableUtils { + static T? firstWhereOrNull( + Iterable? iterable, + bool Function(T item) test, + ) { + if (iterable == null) { + return null; + } + for (var item in iterable) { + if (test(item)) return item; + } + return null; + } +} diff --git a/dart/lib/src/version.dart b/dart/lib/src/version.dart index 7e4666bc06..a62754b2dc 100644 --- a/dart/lib/src/version.dart +++ b/dart/lib/src/version.dart @@ -9,7 +9,7 @@ library version; /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.20.0'; +const String sdkVersion = '8.0.0'; String sdkName(bool isWeb) => isWeb ? _browserSdkName : _ioSdkName; diff --git a/dart/pubspec.yaml b/dart/pubspec.yaml index 4294d86144..bc2ef30452 100644 --- a/dart/pubspec.yaml +++ b/dart/pubspec.yaml @@ -1,5 +1,5 @@ name: sentry -version: 7.20.0 +version: 8.0.0 description: > A crash reporting library for Dart that sends crash reports to Sentry.io. This library supports Dart VM and Web. For Flutter consider sentry_flutter instead. diff --git a/dart/test/event_processor/deduplication_event_processor_test.dart b/dart/test/event_processor/deduplication_event_processor_test.dart index 54592351bb..3e17fe4065 100644 --- a/dart/test/event_processor/deduplication_event_processor_test.dart +++ b/dart/test/event_processor/deduplication_event_processor_test.dart @@ -15,16 +15,16 @@ void main() { final sut = fixture.getSut(true); var ogEvent = _createEvent('foo'); - expect(sut.apply(ogEvent), isNotNull); - expect(sut.apply(ogEvent), isNull); + expect(sut.apply(ogEvent, Hint()), isNotNull); + expect(sut.apply(ogEvent, Hint()), isNull); }); test('does not deduplicate if disabled', () { final sut = fixture.getSut(false); var ogEvent = _createEvent('foo'); - expect(sut.apply(ogEvent), isNotNull); - expect(sut.apply(ogEvent), isNotNull); + expect(sut.apply(ogEvent, Hint()), isNotNull); + expect(sut.apply(ogEvent, Hint()), isNotNull); }); test('does not deduplicate if different events', () { @@ -32,16 +32,16 @@ void main() { var fooEvent = _createEvent('foo'); var barEvent = _createEvent('bar'); - expect(sut.apply(fooEvent), isNotNull); - expect(sut.apply(barEvent), isNotNull); + expect(sut.apply(fooEvent, Hint()), isNotNull); + expect(sut.apply(barEvent, Hint()), isNotNull); }); test('does not deduplicate transaction', () { final sut = fixture.getSut(true); final transaction = _createTransaction(fixture.hub); - expect(sut.apply(transaction), isNotNull); - expect(sut.apply(transaction), isNotNull); + expect(sut.apply(transaction, Hint()), isNotNull); + expect(sut.apply(transaction, Hint()), isNotNull); }); test('exceptions to keep for deduplication', () { @@ -51,10 +51,10 @@ void main() { var barEvent = _createEvent('bar'); var fooBarEvent = _createEvent('foo bar'); - expect(sut.apply(fooEvent), isNotNull); - expect(sut.apply(barEvent), isNotNull); - expect(sut.apply(fooBarEvent), isNotNull); - expect(sut.apply(fooEvent), isNotNull); + expect(sut.apply(fooEvent, Hint()), isNotNull); + expect(sut.apply(barEvent, Hint()), isNotNull); + expect(sut.apply(fooBarEvent, Hint()), isNotNull); + expect(sut.apply(fooEvent, Hint()), isNotNull); }); test('integration test', () async { diff --git a/dart/test/event_processor/enricher/io_enricher_test.dart b/dart/test/event_processor/enricher/io_enricher_test.dart index 1704960edc..72080cba3f 100644 --- a/dart/test/event_processor/enricher/io_enricher_test.dart +++ b/dart/test/event_processor/enricher/io_enricher_test.dart @@ -17,7 +17,7 @@ void main() { test('adds dart runtime', () { final enricher = fixture.getSut(); - final event = enricher.apply(SentryEvent()); + final event = enricher.apply(SentryEvent(), Hint()); expect(event?.contexts.runtimes, isNotEmpty); final dartRuntime = event?.contexts.runtimes @@ -31,7 +31,7 @@ void main() { var event = SentryEvent(contexts: Contexts(runtimes: [runtime])); final enricher = fixture.getSut(); - event = enricher.apply(event)!; + event = enricher.apply(event, Hint())!; expect(event.contexts.runtimes.contains(runtime), true); // second runtime is Dart runtime @@ -42,7 +42,7 @@ void main() { 'does not add device, os and culture if native integration is available', () { final enricher = fixture.getSut(hasNativeIntegration: true); - final event = enricher.apply(SentryEvent()); + final event = enricher.apply(SentryEvent(), Hint()); expect(event?.contexts.device, isNull); expect(event?.contexts.operatingSystem, isNull); @@ -52,7 +52,7 @@ void main() { test('adds device, os and culture if no native integration is available', () { final enricher = fixture.getSut(hasNativeIntegration: false); - final event = enricher.apply(SentryEvent()); + final event = enricher.apply(SentryEvent(), Hint()); expect(event?.contexts.device, isNotNull); expect(event?.contexts.operatingSystem, isNotNull); @@ -61,14 +61,14 @@ void main() { test('device has name', () { final enricher = fixture.getSut(); - final event = enricher.apply(SentryEvent()); + final event = enricher.apply(SentryEvent(), Hint()); expect(event?.contexts.device?.name, isNotNull); }); test('culture has locale and timezone', () { final enricher = fixture.getSut(); - final event = enricher.apply(SentryEvent()); + final event = enricher.apply(SentryEvent(), Hint()); expect(event?.contexts.culture?.locale, isNotNull); expect(event?.contexts.culture?.timezone, isNotNull); @@ -76,7 +76,7 @@ void main() { test('os has name and version', () { final enricher = fixture.getSut(); - final event = enricher.apply(SentryEvent()); + final event = enricher.apply(SentryEvent(), Hint()); expect(event?.contexts.operatingSystem?.name, isNotNull); expect(event?.contexts.operatingSystem?.version, isNotNull); @@ -84,7 +84,7 @@ void main() { test('adds Dart context with PII', () { final enricher = fixture.getSut(includePii: true); - final event = enricher.apply(SentryEvent()); + final event = enricher.apply(SentryEvent(), Hint()); final dartContext = event?.contexts['dart_context']; expect(dartContext, isNotNull); @@ -97,7 +97,7 @@ void main() { test('adds Dart context without PII', () { final enricher = fixture.getSut(includePii: false); - final event = enricher.apply(SentryEvent()); + final event = enricher.apply(SentryEvent(), Hint()); final dartContext = event?.contexts['dart_context']; expect(dartContext, isNotNull); @@ -131,7 +131,7 @@ void main() { hasNativeIntegration: false, ); - final event = enricher.apply(fakeEvent); + final event = enricher.apply(fakeEvent, Hint()); // contexts.device expect( diff --git a/dart/test/event_processor/enricher/web_enricher_test.dart b/dart/test/event_processor/enricher/web_enricher_test.dart index 60076e506a..e5d5b2efec 100644 --- a/dart/test/event_processor/enricher/web_enricher_test.dart +++ b/dart/test/event_processor/enricher/web_enricher_test.dart @@ -20,21 +20,21 @@ void main() { test('add path as transaction if transaction is null', () { var enricher = fixture.getSut(); - final event = enricher.apply(SentryEvent()); + final event = enricher.apply(SentryEvent(), Hint()); expect(event?.transaction, isNotNull); }); test("don't overwrite transaction", () { var enricher = fixture.getSut(); - final event = enricher.apply(SentryEvent(transaction: 'foobar')); + final event = enricher.apply(SentryEvent(transaction: 'foobar'), Hint()); expect(event?.transaction, 'foobar'); }); test('add request with user-agent header', () { var enricher = fixture.getSut(); - final event = enricher.apply(SentryEvent()); + final event = enricher.apply(SentryEvent(), Hint()); expect(event?.request?.headers['User-Agent'], isNotNull); expect(event?.request?.url, isNotNull); @@ -50,7 +50,7 @@ void main() { ), ); var enricher = fixture.getSut(); - event = enricher.apply(event)!; + event = enricher.apply(event, Hint())!; expect(event.request?.headers['User-Agent'], isNotNull); expect(event.request?.headers['foo'], 'bar'); @@ -68,7 +68,7 @@ void main() { ), ); var enricher = fixture.getSut(); - event = enricher.apply(event)!; + event = enricher.apply(event, Hint())!; expect(event.request?.headers['Authorization'], isNull); expect(event.request?.headers['authorization'], isNull); @@ -84,7 +84,7 @@ void main() { ), ); var enricher = fixture.getSut(); - event = enricher.apply(event)!; + event = enricher.apply(event, Hint())!; expect(event.request?.headers['User-Agent'], 'best browser agent'); expect(event.request?.url, 'foo.bar'); @@ -92,14 +92,14 @@ void main() { test('adds device and os', () { var enricher = fixture.getSut(); - final event = enricher.apply(SentryEvent()); + final event = enricher.apply(SentryEvent(), Hint()); expect(event?.contexts.device, isNotNull); }); test('adds Dart context', () { final enricher = fixture.getSut(); - final event = enricher.apply(SentryEvent()); + final event = enricher.apply(SentryEvent(), Hint()); final dartContext = event?.contexts['dart_context']; expect(dartContext, isNotNull); @@ -108,14 +108,14 @@ void main() { test('device has screendensity', () { var enricher = fixture.getSut(); - final event = enricher.apply(SentryEvent()); + final event = enricher.apply(SentryEvent(), Hint()); expect(event?.contexts.device?.screenDensity, isNotNull); }); test('culture has timezone', () { var enricher = fixture.getSut(); - final event = enricher.apply(SentryEvent()); + final event = enricher.apply(SentryEvent(), Hint()); expect(event?.contexts.culture?.timezone, isNotNull); }); @@ -142,7 +142,7 @@ void main() { final enricher = fixture.getSut(); - final event = enricher.apply(fakeEvent); + final event = enricher.apply(fakeEvent, Hint()); // contexts.device expect( diff --git a/dart/test/event_processor/exception/io_exception_event_processor_test.dart b/dart/test/event_processor/exception/io_exception_event_processor_test.dart index 14d2720df2..5d4d771a08 100644 --- a/dart/test/event_processor/exception/io_exception_event_processor_test.dart +++ b/dart/test/event_processor/exception/io_exception_event_processor_test.dart @@ -23,6 +23,7 @@ void main() { uri: Uri.parse('https://example.org/foo/bar?foo=bar'), ), ), + Hint(), ); expect(event?.request, isNotNull); @@ -36,6 +37,7 @@ void main() { SentryEvent( throwable: HttpException(''), ), + Hint(), ); expect(event?.request, isNull); @@ -55,6 +57,7 @@ void main() { ), ), ), + Hint(), ); expect(event?.request, isNotNull); @@ -81,6 +84,7 @@ void main() { OSError('Oh no :(', 42), ), ), + Hint(), ); // Due to the test setup, there's no SentryException for the FileSystemException. diff --git a/dart/test/http_client/failed_request_client_test.dart b/dart/test/http_client/failed_request_client_test.dart index 9c450f8bd2..2ac9a74c8e 100644 --- a/dart/test/http_client/failed_request_client_test.dart +++ b/dart/test/http_client/failed_request_client_test.dart @@ -332,7 +332,7 @@ void main() { final sut = fixture.getSut(client: client); Hint? eventHint; - fixture.options.addEventProcessor(FunctionEventProcessor((event, {hint}) { + fixture.options.addEventProcessor(FunctionEventProcessor((event, hint) { eventHint = hint; return event; })); diff --git a/dart/test/mocks.dart b/dart/test/mocks.dart index 1c79599a6b..7c960c8a07 100644 --- a/dart/test/mocks.dart +++ b/dart/test/mocks.dart @@ -132,7 +132,7 @@ final Map> fakeMetrics = { /// Always returns null and thus drops all events class DropAllEventProcessor implements EventProcessor { @override - SentryEvent? apply(SentryEvent event, {hint}) { + SentryEvent? apply(SentryEvent event, Hint hint) { return null; } } @@ -143,13 +143,13 @@ class FunctionEventProcessor implements EventProcessor { final EventProcessorFunction applyFunction; @override - SentryEvent? apply(SentryEvent event, {hint}) { - return applyFunction(event, hint: hint); + SentryEvent? apply(SentryEvent event, Hint hint) { + return applyFunction(event, hint); } } -typedef EventProcessorFunction = SentryEvent? Function(SentryEvent event, - {Hint? hint}); +typedef EventProcessorFunction = SentryEvent? Function( + SentryEvent event, Hint hint); var fakeEnvelope = SentryEnvelope.fromEvent( fakeEvent, diff --git a/dart/test/protocol/mechanism_test.dart b/dart/test/protocol/mechanism_test.dart index 4b484d2ca3..857a0529a9 100644 --- a/dart/test/protocol/mechanism_test.dart +++ b/dart/test/protocol/mechanism_test.dart @@ -11,6 +11,10 @@ void main() { synthetic: true, meta: {'key': 'value'}, data: {'keyb': 'valueb'}, + isExceptionGroup: false, + exceptionId: 0, + parentId: 0, + source: 'source', ); final mechanismJson = { @@ -21,6 +25,10 @@ void main() { 'meta': {'key': 'value'}, 'data': {'keyb': 'valueb'}, 'synthetic': true, + 'is_exception_group': false, + 'source': 'source', + 'exception_id': 0, + 'parent_id': 0, }; group('json', () { @@ -51,6 +59,7 @@ void main() { expect(data.toJson(), copy.toJson()); }); + test('copyWith takes new values', () { final data = mechanism; @@ -62,6 +71,10 @@ void main() { synthetic: false, meta: {'key1': 'value1'}, data: {'keyb1': 'valueb1'}, + exceptionId: 1, + parentId: 1, + isExceptionGroup: false, + source: 'foo', ); expect('type1', copy.type); @@ -71,6 +84,10 @@ void main() { expect(false, copy.synthetic); expect({'key1': 'value1'}, copy.meta); expect({'keyb1': 'valueb1'}, copy.data); + expect(1, copy.exceptionId); + expect(1, copy.parentId); + expect(false, copy.isExceptionGroup); + expect('foo', copy.source); }); }); } diff --git a/dart/test/scope_test.dart b/dart/test/scope_test.dart index 6f21e5e63c..66cc543b6b 100644 --- a/dart/test/scope_test.dart +++ b/dart/test/scope_test.dart @@ -98,6 +98,26 @@ void main() { expect(sut.breadcrumbs.last, breadcrumb); }); + test('beforeBreadcrumb called with user provided hint', () { + Hint? actual; + BeforeBreadcrumbCallback bb = (_, hint) { + actual = hint; + return null; + }; + final sut = fixture.getSut( + beforeBreadcrumbCallback: bb, + ); + + final breadcrumb = Breadcrumb( + message: 'test log', + timestamp: DateTime.utc(2019), + ); + final hint = Hint.withMap({'user-name': 'joe dirt'}); + sut.addBreadcrumb(breadcrumb, hint: hint); + + expect(actual?.get('user-name'), 'joe dirt'); + }); + test('Executes and drops $Breadcrumb', () { final sut = fixture.getSut( beforeBreadcrumbCallback: fixture.beforeBreadcrumbCallback, @@ -412,7 +432,7 @@ void main() { await scope.setContexts('theme', 'material'); await scope.setUser(scopeUser); - final updatedEvent = await scope.applyToEvent(event); + final updatedEvent = await scope.applyToEvent(event, Hint()); expect(updatedEvent?.user, scopeUser); expect(updatedEvent?.transaction, '/example/app'); @@ -433,7 +453,7 @@ void main() { final scope = Scope(SentryOptions(dsn: fakeDsn)) ..span = fixture.sentryTracer; - final updatedEvent = await scope.applyToEvent(event); + final updatedEvent = await scope.applyToEvent(event, Hint()); expect(updatedEvent?.contexts['trace'] is SentryTraceContext, true); }); @@ -456,7 +476,7 @@ void main() { await scope.addBreadcrumb(breadcrumb); await scope.setUser(scopeUser); - final updatedEvent = await scope.applyToEvent(event); + final updatedEvent = await scope.applyToEvent(event, Hint()); expect(updatedEvent?.user, isNotNull); expect(updatedEvent?.user?.id, eventUser.id); @@ -504,7 +524,7 @@ void main() { SentryOperatingSystem(name: 'context-os'), ); - final updatedEvent = await scope.applyToEvent(event); + final updatedEvent = await scope.applyToEvent(event, Hint()); expect(updatedEvent?.contexts[SentryDevice.type].name, 'event-device'); expect(updatedEvent?.contexts[SentryApp.type].name, 'event-app'); @@ -534,7 +554,7 @@ void main() { await scope.setContexts('location', {'city': 'London'}); await scope.setContexts('items', [1, 2, 3]); - final updatedEvent = await scope.applyToEvent(event); + final updatedEvent = await scope.applyToEvent(event, Hint()); expect(updatedEvent?.contexts[SentryDevice.type].name, 'context-device'); expect(updatedEvent?.contexts[SentryApp.type].name, 'context-app'); @@ -559,7 +579,7 @@ void main() { final scope = Scope(SentryOptions(dsn: fakeDsn)) ..level = SentryLevel.error; - final updatedEvent = await scope.applyToEvent(event); + final updatedEvent = await scope.applyToEvent(event, Hint()); expect(updatedEvent?.level, SentryLevel.error); }); @@ -569,7 +589,7 @@ void main() { final scope = Scope(SentryOptions(dsn: fakeDsn)) ..span = fixture.sentryTracer; - final updatedEvent = await scope.applyToEvent(event); + final updatedEvent = await scope.applyToEvent(event, Hint()); expect(updatedEvent?.transaction, 'name'); }); @@ -581,7 +601,7 @@ void main() { sut.addEventProcessor(fixture.processor); final event = SentryEvent(); - var newEvent = await sut.applyToEvent(event); + var newEvent = await sut.applyToEvent(event, Hint()); expect(newEvent, isNull); }); @@ -590,7 +610,7 @@ void main() { var tr = SentryTransaction(fixture.sentryTracer); final scope = Scope(SentryOptions(dsn: fakeDsn))..fingerprint = ['test']; - final updatedTr = await scope.applyToEvent(tr); + final updatedTr = await scope.applyToEvent(tr, Hint()); expect(updatedTr?.fingerprint, isNull); }); @@ -599,7 +619,7 @@ void main() { var tr = SentryTransaction(fixture.sentryTracer); final scope = Scope(SentryOptions(dsn: fakeDsn))..level = SentryLevel.error; - final updatedTr = await scope.applyToEvent(tr); + final updatedTr = await scope.applyToEvent(tr, Hint()); expect(updatedTr?.level, isNull); }); @@ -608,7 +628,7 @@ void main() { var tr = SentryTransaction(fixture.sentryTracer); final scope = Scope(SentryOptions(dsn: fakeDsn))..level = SentryLevel.error; - final updatedTr = await scope.applyToEvent(tr); + final updatedTr = await scope.applyToEvent(tr, Hint()); expect(updatedTr?.contexts.trace?.sampled, isTrue); }); @@ -625,9 +645,9 @@ void main() { final sut = fixture.getSut( scopeObserver: fixture.mockScopeObserver, beforeBreadcrumbCallback: ( - Breadcrumb? breadcrumb, { - Hint? hint, - }) { + Breadcrumb? breadcrumb, + Hint hint, + ) { return breadcrumb?.copyWith(message: "modified"); }, ); @@ -698,9 +718,9 @@ void main() { final sut = fixture.getSut( beforeBreadcrumbCallback: ( - Breadcrumb? breadcrumb, { - Hint? hint, - }) { + Breadcrumb? breadcrumb, + Hint hint, + ) { throw exception; }, debug: true); @@ -722,9 +742,9 @@ void main() { final sut = fixture.getSut( beforeBreadcrumbCallback: ( - Breadcrumb? breadcrumb, { - Hint? hint, - }) { + Breadcrumb? breadcrumb, + Hint hint, + ) { if (numberOfBeforeBreadcrumbCalls > 0) { throw exception; } @@ -785,11 +805,11 @@ class Fixture { EventProcessor get processor => DropAllEventProcessor(); - Breadcrumb? beforeBreadcrumbCallback(Breadcrumb? breadcrumb, {Hint? hint}) => + Breadcrumb? beforeBreadcrumbCallback(Breadcrumb? breadcrumb, Hint hint) => null; - Breadcrumb? beforeBreadcrumbMutateCallback(Breadcrumb? breadcrumb, - {Hint? hint}) => + Breadcrumb? beforeBreadcrumbMutateCallback( + Breadcrumb? breadcrumb, Hint hint) => breadcrumb?.copyWith(message: 'new message'); void mockLogger( @@ -810,7 +830,7 @@ class AddTagsEventProcessor implements EventProcessor { AddTagsEventProcessor(this.tags); @override - SentryEvent? apply(SentryEvent event, {hint}) { + SentryEvent? apply(SentryEvent event, Hint hint) { return event..tags?.addAll(tags); } } diff --git a/dart/test/sentry_client_test.dart b/dart/test/sentry_client_test.dart index ca7718ba32..89a5620acc 100644 --- a/dart/test/sentry_client_test.dart +++ b/dart/test/sentry_client_test.dart @@ -13,6 +13,7 @@ import 'package:sentry/src/sentry_item_type.dart'; import 'package:sentry/src/sentry_stack_trace_factory.dart'; import 'package:sentry/src/sentry_tracer.dart'; import 'package:sentry/src/transport/data_category.dart'; +import 'package:sentry/src/utils/iterable_utils.dart'; import 'package:sentry/src/transport/spotlight_http_transport.dart'; import 'package:test/test.dart'; @@ -937,25 +938,14 @@ void main() { }); }); - group('SentryClient: apply default pii', () { + group('SentryClient: sets user & user ip', () { late Fixture fixture; setUp(() { fixture = Fixture(); }); - test('sendDefaultPii is disabled', () async { - final client = fixture.getSut(sendDefaultPii: false); - - await client.captureEvent(fakeEvent); - - final capturedEnvelope = fixture.transport.envelopes.first; - final capturedEvent = await eventFromEnvelope(capturedEnvelope); - - expect(capturedEvent.user?.toJson(), fakeEvent.user?.toJson()); - }); - - test('sendDefaultPii is enabled and event has no user', () async { + test('event has no user', () async { final client = fixture.getSut(sendDefaultPii: true); var fakeEvent = SentryEvent(); @@ -969,8 +959,7 @@ void main() { expect(capturedEvent.user?.ipAddress, '{{auto}}'); }); - test('sendDefaultPii is enabled and event has a user with IP address', - () async { + test('event has a user with IP address', () async { final client = fixture.getSut(sendDefaultPii: true); await client.captureEvent(fakeEvent); @@ -986,8 +975,7 @@ void main() { expect(capturedEvent.user?.email, fakeEvent.user!.email); }); - test('sendDefaultPii is enabled and event has a user without IP address', - () async { + test('event has a user without IP address', () async { final client = fixture.getSut(sendDefaultPii: true); final event = fakeEvent.copyWith(user: fakeUser); @@ -1150,7 +1138,7 @@ void main() { test('thrown error is handled', () async { final exception = Exception("before send exception"); - final beforeSendCallback = (SentryEvent event, {Hint? hint}) { + final beforeSendCallback = (SentryEvent event, Hint hint) { throw exception; }; @@ -1170,7 +1158,7 @@ void main() { setUp(() { fixture = Fixture(); fixture.options.addEventProcessor(FunctionEventProcessor( - (event, {hint}) => event + (event, hint) => event ..tags!.addAll({'theme': 'material'}) // ignore: deprecated_member_use_from_same_package ..extra!['host'] = '0.0.0.1' @@ -1212,8 +1200,8 @@ void main() { var executed = false; - final client = fixture.getSut( - eventProcessor: FunctionEventProcessor((event, {hint}) { + final client = + fixture.getSut(eventProcessor: FunctionEventProcessor((event, hint) { expect(myHint, hint); executed = true; return event; @@ -1227,8 +1215,8 @@ void main() { test('should create hint when none was provided', () async { var executed = false; - final client = fixture.getSut( - eventProcessor: FunctionEventProcessor((event, {hint}) { + final client = + fixture.getSut(eventProcessor: FunctionEventProcessor((event, hint) { expect(hint, isNotNull); executed = true; return event; @@ -1264,201 +1252,6 @@ void main() { }); }); - group('Breadcrumbs', () { - late Fixture fixture; - - setUp(() { - fixture = Fixture(); - }); - - test('Clears breadcrumbs on Android for transaction', () async { - fixture.options.enableScopeSync = true; - fixture.options.platformChecker = - MockPlatformChecker(platform: MockPlatform.android()); - - final client = fixture.getSut(); - final transaction = SentryTransaction( - fixture.tracer, - breadcrumbs: [ - Breadcrumb(), - ], - ); - await client.captureTransaction(transaction); - - final capturedEnvelope = (fixture.transport).envelopes.first; - final capturedTransaction = - await transactionFromEnvelope(capturedEnvelope); - - expect((capturedTransaction['breadcrumbs'] ?? []).isEmpty, true); - }); - - test('Clears breadcrumbs on Android if mechanism.handled is true for event', - () async { - fixture.options.enableScopeSync = true; - fixture.options.platformChecker = - MockPlatformChecker(platform: MockPlatform.android()); - - final client = fixture.getSut(); - final event = SentryEvent(exceptions: [ - SentryException( - type: "type", - value: "value", - mechanism: Mechanism( - type: 'type', - handled: true, - ), - ) - ], breadcrumbs: [ - Breadcrumb() - ]); - await client.captureEvent(event); - - final capturedEnvelope = (fixture.transport).envelopes.first; - final capturedEvent = await eventFromEnvelope(capturedEnvelope); - - expect((capturedEvent.breadcrumbs ?? []).isEmpty, true); - }); - - test('Clears breadcrumbs on Android if mechanism.handled is null for event', - () async { - fixture.options.enableScopeSync = true; - fixture.options.platformChecker = - MockPlatformChecker(platform: MockPlatform.android()); - - final client = fixture.getSut(); - final event = SentryEvent(exceptions: [ - SentryException( - type: "type", - value: "value", - mechanism: Mechanism(type: 'type'), - ) - ], breadcrumbs: [ - Breadcrumb() - ]); - await client.captureEvent(event); - - final capturedEnvelope = (fixture.transport).envelopes.first; - final capturedEvent = await eventFromEnvelope(capturedEnvelope); - - expect((capturedEvent.breadcrumbs ?? []).isEmpty, true); - }); - - test('Clears breadcrumbs on Android if theres no mechanism for event', - () async { - fixture.options.enableScopeSync = true; - fixture.options.platformChecker = - MockPlatformChecker(platform: MockPlatform.android()); - - final client = fixture.getSut(); - final event = SentryEvent(exceptions: [ - SentryException( - type: "type", - value: "value", - ) - ], breadcrumbs: [ - Breadcrumb() - ]); - await client.captureEvent(event); - - final capturedEnvelope = (fixture.transport).envelopes.first; - final capturedEvent = await eventFromEnvelope(capturedEnvelope); - - expect((capturedEvent.breadcrumbs ?? []).isEmpty, true); - }); - - test( - 'Does not clear breadcrumbs on Android if mechanism.handled is false for event', - () async { - fixture.options.enableScopeSync = true; - fixture.options.platformChecker = - MockPlatformChecker(platform: MockPlatform.android()); - - final client = fixture.getSut(); - final event = SentryEvent(exceptions: [ - SentryException( - type: "type", - value: "value", - mechanism: Mechanism( - type: 'type', - handled: false, - ), - ) - ], breadcrumbs: [ - Breadcrumb() - ]); - await client.captureEvent(event); - - final capturedEnvelope = (fixture.transport).envelopes.first; - final capturedEvent = await eventFromEnvelope(capturedEnvelope); - - expect((capturedEvent.breadcrumbs ?? []).isNotEmpty, true); - }); - - test( - 'Does not clear breadcrumbs on Android if any mechanism.handled is false for event', - () async { - fixture.options.enableScopeSync = true; - fixture.options.platformChecker = - MockPlatformChecker(platform: MockPlatform.android()); - - final client = fixture.getSut(); - final event = SentryEvent(exceptions: [ - SentryException( - type: "type", - value: "value", - mechanism: Mechanism( - type: 'type', - handled: true, - ), - ), - SentryException( - type: "type", - value: "value", - mechanism: Mechanism( - type: 'type', - handled: false, - ), - ) - ], breadcrumbs: [ - Breadcrumb() - ]); - await client.captureEvent(event); - - final capturedEnvelope = (fixture.transport).envelopes.first; - final capturedEvent = await eventFromEnvelope(capturedEnvelope); - - expect((capturedEvent.breadcrumbs ?? []).isNotEmpty, true); - }); - - test('web breadcrumbs exist on web Android devices', () async { - fixture.options.enableScopeSync = true; - fixture.options.platformChecker = MockPlatformChecker( - platform: MockPlatform.android(), - isWebValue: true, - ); - - final client = fixture.getSut(); - final event = SentryEvent(exceptions: [ - SentryException( - type: "type", - value: "value", - mechanism: Mechanism( - type: 'type', - handled: true, - ), - ), - ], breadcrumbs: [ - Breadcrumb(), - ]); - await client.captureEvent(event); - - final capturedEnvelope = (fixture.transport).envelopes.first; - final capturedEvent = await eventFromEnvelope(capturedEnvelope); - - expect((capturedEvent.breadcrumbs ?? []).isNotEmpty, true); - }); - }); - group('ClientReportRecorder', () { late Fixture fixture; @@ -1538,8 +1331,10 @@ void main() { await sut.captureEvent(fakeEvent, hint: hint); final capturedEnvelope = (fixture.transport).envelopes.first; - final attachmentItem = capturedEnvelope.items.firstWhereOrNull( - (element) => element.header.type == SentryItemType.attachment); + final attachmentItem = IterableUtils.firstWhereOrNull( + capturedEnvelope.items, + (SentryEnvelopeItem e) => e.header.type == SentryItemType.attachment, + ); expect(attachmentItem?.header.attachmentType, SentryAttachment.typeAttachmentDefault); }); @@ -1754,9 +1549,9 @@ Future> transactionFromEnvelope( } SentryEvent? beforeSendCallbackDropEvent( - SentryEvent event, { - Hint? hint, -}) => + SentryEvent event, + Hint hint, +) => null; SentryTransaction? beforeSendTransactionCallbackDropEvent( @@ -1765,9 +1560,9 @@ SentryTransaction? beforeSendTransactionCallbackDropEvent( null; Future asyncBeforeSendCallbackDropEvent( - SentryEvent event, { - Hint? hint, -}) async { + SentryEvent event, + Hint hint, +) async { await Future.delayed(Duration(milliseconds: 200)); return null; } @@ -1778,7 +1573,7 @@ Future asyncBeforeSendTransactionCallbackDropEvent( return null; } -SentryEvent? beforeSendCallback(SentryEvent event, {Hint? hint}) { +SentryEvent? beforeSendCallback(SentryEvent event, Hint hint) { return event ..tags!.addAll({'theme': 'material'}) // ignore: deprecated_member_use_from_same_package @@ -1856,8 +1651,7 @@ class Fixture { return client; } - Future droppingBeforeSend(SentryEvent event, - {Hint? hint}) async { + Future droppingBeforeSend(SentryEvent event, Hint hint) async { return null; } diff --git a/dart/test/sentry_tracer_test.dart b/dart/test/sentry_tracer_test.dart index 77914e66d3..7ba5e80fac 100644 --- a/dart/test/sentry_tracer_test.dart +++ b/dart/test/sentry_tracer_test.dart @@ -68,24 +68,7 @@ void main() { expect(sut.endTimestamp, endTimestamp); }); - test( - 'tracer finish sets given end timestamp to all children while finishing them', - () async { - final sut = fixture.getSut(); - - final childA = sut.startChild('operation-a', description: 'description'); - final childB = sut.startChild('operation-b', description: 'description'); - final endTimestamp = getUtcDateTime(); - - await sut.finish(endTimestamp: endTimestamp); - await childA.finish(); - await childB.finish(); - - expect(childA.endTimestamp, endTimestamp); - expect(childB.endTimestamp, endTimestamp); - }); - - test('tracer finishes unfinished spans', () async { + test('tracer does not finish unfinished spans', () async { final sut = fixture.getSut(); sut.startChild('child'); @@ -94,7 +77,8 @@ void main() { final tr = fixture.hub.captureTransactionCalls.first; final child = tr.transaction.spans.first; - expect(child.status.toString(), 'deadline_exceeded'); + expect(child.status, isNull); + expect(child.endTimestamp, isNull); }); test('tracer sets data to extra', () async { diff --git a/dart/test/utils/http_sanitizer_test.dart b/dart/test/utils/http_sanitizer_test.dart index f9967c2778..2a4e0a58be 100644 --- a/dart/test/utils/http_sanitizer_test.dart +++ b/dart/test/utils/http_sanitizer_test.dart @@ -182,7 +182,7 @@ void main() { }); } -extension StringExtension on String { +extension _StringExtension on String { String _capitalize() { return "${this[0].toUpperCase()}${substring(1).toLowerCase()}"; } diff --git a/dio/README.md b/dio/README.md index 72c1cbeaa8..a8cf767237 100644 --- a/dio/README.md +++ b/dio/README.md @@ -49,8 +49,9 @@ Depending on your configuration, this adds performance tracing and http breadcru #### Resources -* [![Documentation](https://img.shields.io/badge/documentation-sentry.io-green.svg)](https://docs.sentry.io/platforms/dart/) -* [![Forum](https://img.shields.io/badge/forum-sentry-green.svg)](https://forum.sentry.io/c/sdks) -* [![Discord](https://img.shields.io/discord/621778831602221064)](https://discord.gg/Ww9hbqr) +* [![Flutter docs](https://img.shields.io/badge/documentation-sentry.io-green.svg?label=flutter%20docs)](https://docs.sentry.io/platforms/flutter/) +* [![Dart docs](https://img.shields.io/badge/documentation-sentry.io-green.svg?label=dart%20docs)](https://docs.sentry.io/platforms/dart/) +* [![Discussions](https://img.shields.io/github/discussions/getsentry/sentry-dart.svg)](https://github.com/getsentry/sentry-dart/discussions) +* [![Discord Chat](https://img.shields.io/discord/621778831602221064?logo=discord&logoColor=ffffff&color=7389D8)](https://discord.gg/PXa5Apfe7K) * [![Stack Overflow](https://img.shields.io/badge/stack%20overflow-sentry-green.svg)](https://stackoverflow.com/questions/tagged/sentry) -* [![Twitter Follow](https://img.shields.io/twitter/follow/getsentry?label=getsentry&style=social)](https://twitter.com/intent/follow?screen_name=getsentry) +* [![Twitter Follow](https://img.shields.io/twitter/follow/getsentry?label=getsentry&style=social)](https://twitter.com/intent/follow?screen_name=getsentry) \ No newline at end of file diff --git a/dio/lib/src/dio_event_processor.dart b/dio/lib/src/dio_event_processor.dart index 3a9603abd1..afeb692be4 100644 --- a/dio/lib/src/dio_event_processor.dart +++ b/dio/lib/src/dio_event_processor.dart @@ -15,7 +15,7 @@ class DioEventProcessor implements EventProcessor { final SentryOptions _options; @override - SentryEvent? apply(SentryEvent event, {Hint? hint}) { + SentryEvent? apply(SentryEvent event, Hint hint) { if (event is SentryTransaction) { return event; } diff --git a/dio/lib/src/failed_request_interceptor.dart b/dio/lib/src/failed_request_interceptor.dart index 994da6121e..cd36f60549 100644 --- a/dio/lib/src/failed_request_interceptor.dart +++ b/dio/lib/src/failed_request_interceptor.dart @@ -30,7 +30,7 @@ class FailedRequestInterceptor extends Interceptor { final cfr = _captureFailedRequests ?? _hub.options.captureFailedRequests; final containsStatusCode = - _failedRequestStatusCodes.containsStatusCode(err.response?.statusCode); + _failedRequestStatusCodes._containsStatusCode(err.response?.statusCode); final containsRequestTarget = containsTargetOrMatchesRegExp( _failedRequestTargets, err.requestOptions.path, @@ -49,7 +49,7 @@ class FailedRequestInterceptor extends Interceptor { } extension _ListX on List { - bool containsStatusCode(int? statusCode) { + bool _containsStatusCode(int? statusCode) { if (statusCode == null) { return false; } diff --git a/dio/lib/src/version.dart b/dio/lib/src/version.dart index 396477f00f..73fa6fc4a4 100644 --- a/dio/lib/src/version.dart +++ b/dio/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.20.0'; +const String sdkVersion = '8.0.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_dio'; diff --git a/dio/pubspec.yaml b/dio/pubspec.yaml index 62d1d90e77..9862c54b69 100644 --- a/dio/pubspec.yaml +++ b/dio/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_dio description: An integration which adds support for performance tracing for the Dio package. -version: 7.20.0 +version: 8.0.0 homepage: https://docs.sentry.io/platforms/dart/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -19,7 +19,7 @@ platforms: dependencies: dio: ^5.0.0 - sentry: 7.20.0 + sentry: 8.0.0 dev_dependencies: meta: ^1.3.0 diff --git a/dio/test/dio_event_processor_test.dart b/dio/test/dio_event_processor_test.dart index 3cd060ea8e..af4a94ab8d 100644 --- a/dio/test/dio_event_processor_test.dart +++ b/dio/test/dio_event_processor_test.dart @@ -24,7 +24,7 @@ void main() { throwable: Exception(), exceptions: [fixture.sentryError(throwable)], ); - final processedEvent = sut.apply(event) as SentryEvent; + final processedEvent = sut.apply(event, Hint()) as SentryEvent; expect(event, processedEvent); }); @@ -42,7 +42,7 @@ void main() { request: SentryRequest(), exceptions: [fixture.sentryError(dioError)], ); - final processedEvent = sut.apply(event) as SentryEvent; + final processedEvent = sut.apply(event, Hint()) as SentryEvent; expect(event.throwable, processedEvent.throwable); expect(event.request, processedEvent.request); @@ -70,7 +70,7 @@ void main() { fixture.sentryError(dioError), ], ); - final processedEvent = sut.apply(event) as SentryEvent; + final processedEvent = sut.apply(event, Hint()) as SentryEvent; expect(processedEvent.throwable, event.throwable); expect(processedEvent.request?.method, 'POST'); @@ -99,7 +99,7 @@ void main() { fixture.sentryError(dioError), ], ); - final processedEvent = sut.apply(event) as SentryEvent; + final processedEvent = sut.apply(event, Hint()) as SentryEvent; expect(processedEvent.throwable, event.throwable); expect(processedEvent.request?.method, 'GET'); @@ -128,7 +128,7 @@ void main() { fixture.sentryError(dioError), ], ); - final processedEvent = sut.apply(event) as SentryEvent; + final processedEvent = sut.apply(event, Hint()) as SentryEvent; expect(processedEvent.request?.headers, {}); }); @@ -180,7 +180,7 @@ void main() { fixture.sentryError(dioError), ], ); - final processedEvent = sut.apply(event) as SentryEvent; + final processedEvent = sut.apply(event, Hint()) as SentryEvent; final capturedRequest = processedEvent.request; expect(capturedRequest, isNotNull); @@ -222,7 +222,7 @@ void main() { fixture.sentryError(dioError), ], ); - final processedEvent = sut.apply(event) as SentryEvent; + final processedEvent = sut.apply(event, Hint()) as SentryEvent; expect(processedEvent.throwable, event.throwable); expect(processedEvent.contexts.response, isNotNull); @@ -263,7 +263,7 @@ void main() { fixture.sentryError(dioError), ], ); - final processedEvent = sut.apply(event) as SentryEvent; + final processedEvent = sut.apply(event, Hint()) as SentryEvent; expect(processedEvent.throwable, event.throwable); expect(processedEvent.contexts.response, isNotNull); @@ -323,7 +323,7 @@ void main() { fixture.sentryError(dioError), ], ); - final processedEvent = sut.apply(event) as SentryEvent; + final processedEvent = sut.apply(event, Hint()) as SentryEvent; final capturedResponse = processedEvent.contexts.response; expect(capturedResponse, isNotNull); @@ -378,7 +378,7 @@ void main() { fixture.sentryError(dioError), ], ); - final processedEvent = sut.apply(event) as SentryEvent; + final processedEvent = sut.apply(event, Hint()) as SentryEvent; final capturedResponse = processedEvent.contexts.response; expect(capturedResponse, isNotNull); @@ -413,7 +413,7 @@ void main() { exceptions: exceptions, ); - final processedEvent = sut.apply(event) as SentryEvent; + final processedEvent = sut.apply(event, Hint()) as SentryEvent; expect(processedEvent.exceptions?.length, 2); diff --git a/dio/test/mocks.dart b/dio/test/mocks.dart index 5ed6dcd00a..30e53c5772 100644 --- a/dio/test/mocks.dart +++ b/dio/test/mocks.dart @@ -98,7 +98,7 @@ final fakeEvent = SentryEvent( /// Doesn't do anything with the events class NoOpEventProcessor implements EventProcessor { @override - SentryEvent? apply(SentryEvent event, {Hint? hint}) { + SentryEvent? apply(SentryEvent event, Hint hint) { return event; } } @@ -106,7 +106,7 @@ class NoOpEventProcessor implements EventProcessor { /// Always returns null and thus drops all events class DropAllEventProcessor implements EventProcessor { @override - SentryEvent? apply(SentryEvent event, {Hint? hint}) { + SentryEvent? apply(SentryEvent event, Hint hint) { return null; } } @@ -117,15 +117,15 @@ class FunctionEventProcessor implements EventProcessor { final EventProcessorFunction applyFunction; @override - SentryEvent? apply(SentryEvent event, {Hint? hint}) { - return applyFunction(event, hint: hint); + SentryEvent? apply(SentryEvent event, Hint hint) { + return applyFunction(event, hint); } } typedef EventProcessorFunction = SentryEvent? Function( - SentryEvent event, { - Hint? hint, -}); + SentryEvent event, + Hint hint, +); var fakeEnvelope = SentryEnvelope.fromEvent( fakeEvent, diff --git a/drift/README.md b/drift/README.md index 43d26893e4..57b335700a 100644 --- a/drift/README.md +++ b/drift/README.md @@ -74,8 +74,9 @@ Future runApp() async { #### Resources -* [![Documentation](https://img.shields.io/badge/documentation-sentry.io-green.svg)](https://docs.sentry.io/platforms/dart/) -* [![Forum](https://img.shields.io/badge/forum-sentry-green.svg)](https://forum.sentry.io/c/sdks) -* [![Discord](https://img.shields.io/discord/621778831602221064)](https://discord.gg/Ww9hbqr) +* [![Flutter docs](https://img.shields.io/badge/documentation-sentry.io-green.svg?label=flutter%20docs)](https://docs.sentry.io/platforms/flutter/) +* [![Dart docs](https://img.shields.io/badge/documentation-sentry.io-green.svg?label=dart%20docs)](https://docs.sentry.io/platforms/dart/) +* [![Discussions](https://img.shields.io/github/discussions/getsentry/sentry-dart.svg)](https://github.com/getsentry/sentry-dart/discussions) +* [![Discord Chat](https://img.shields.io/discord/621778831602221064?logo=discord&logoColor=ffffff&color=7389D8)](https://discord.gg/PXa5Apfe7K) * [![Stack Overflow](https://img.shields.io/badge/stack%20overflow-sentry-green.svg)](https://stackoverflow.com/questions/tagged/sentry) * [![Twitter Follow](https://img.shields.io/twitter/follow/getsentry?label=getsentry&style=social)](https://twitter.com/intent/follow?screen_name=getsentry) diff --git a/drift/lib/src/version.dart b/drift/lib/src/version.dart index baed0fdd1b..d71a56fddd 100644 --- a/drift/lib/src/version.dart +++ b/drift/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.20.0'; +const String sdkVersion = '8.0.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_drift'; diff --git a/drift/pubspec.yaml b/drift/pubspec.yaml index 9d93dc877f..d468e90a12 100644 --- a/drift/pubspec.yaml +++ b/drift/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_drift description: An integration which adds support for performance tracing for the drift package. -version: 7.20.0 +version: 8.0.0 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -17,7 +17,7 @@ platforms: web: dependencies: - sentry: 7.20.0 + sentry: 8.0.0 meta: ^1.3.0 drift: ^2.13.0 diff --git a/file/lib/src/version.dart b/file/lib/src/version.dart index ddc904ca24..cead856a2f 100644 --- a/file/lib/src/version.dart +++ b/file/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.20.0'; +const String sdkVersion = '8.0.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_file'; diff --git a/file/pubspec.yaml b/file/pubspec.yaml index 3d054c5090..3871d9ab38 100644 --- a/file/pubspec.yaml +++ b/file/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_file description: An integration which adds support for performance tracing for dart.io.File. -version: 7.20.0 +version: 8.0.0 homepage: https://docs.sentry.io/platforms/dart/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -17,7 +17,7 @@ platforms: windows: dependencies: - sentry: 7.20.0 + sentry: 8.0.0 meta: ^1.3.0 dev_dependencies: diff --git a/flutter/README.md b/flutter/README.md index 41e835aea8..b6b7f55d8b 100644 --- a/flutter/README.md +++ b/flutter/README.md @@ -127,8 +127,9 @@ Or [try out the Alpha version of the Sentry Dart Plugin](https://github.com/gets #### Resources -* [![Documentation](https://img.shields.io/badge/documentation-sentry.io-green.svg)](https://docs.sentry.io/platforms/flutter/) -* [![Forum](https://img.shields.io/badge/forum-sentry-green.svg)](https://forum.sentry.io/c/sdks) -* [![Discord](https://img.shields.io/discord/621778831602221064)](https://discord.gg/Ww9hbqr) +* [![Flutter docs](https://img.shields.io/badge/documentation-sentry.io-green.svg?label=flutter%20docs)](https://docs.sentry.io/platforms/flutter/) +* [![Dart docs](https://img.shields.io/badge/documentation-sentry.io-green.svg?label=dart%20docs)](https://docs.sentry.io/platforms/dart/) +* [![Discussions](https://img.shields.io/github/discussions/getsentry/sentry-dart.svg)](https://github.com/getsentry/sentry-dart/discussions) +* [![Discord Chat](https://img.shields.io/discord/621778831602221064?logo=discord&logoColor=ffffff&color=7389D8)](https://discord.gg/PXa5Apfe7K) * [![Stack Overflow](https://img.shields.io/badge/stack%20overflow-sentry-green.svg)](https://stackoverflow.com/questions/tagged/sentry) * [![Twitter Follow](https://img.shields.io/twitter/follow/getsentry?label=getsentry&style=social)](https://twitter.com/intent/follow?screen_name=getsentry) diff --git a/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutter.kt b/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutter.kt index 962414c6a9..c06a8b0dc2 100644 --- a/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutter.kt +++ b/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutter.kt @@ -8,12 +8,14 @@ import java.util.Locale class SentryFlutter( private val androidSdk: String, - private val nativeSdk: String + private val nativeSdk: String, ) { - var autoPerformanceTracingEnabled = false - fun updateOptions(options: SentryAndroidOptions, data: Map) { + fun updateOptions( + options: SentryAndroidOptions, + data: Map, + ) { data.getIfNotNull("dsn") { options.dsn = it } @@ -122,7 +124,10 @@ class SentryFlutter( // Call the `completion` closure if cast to map value with `key` and type `T` is successful. @Suppress("UNCHECKED_CAST") -private fun Map.getIfNotNull(key: String, callback: (T) -> Unit) { +private fun Map.getIfNotNull( + key: String, + callback: (T) -> Unit, +) { (get(key) as? T)?.let { callback(it) } diff --git a/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutterPlugin.kt b/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutterPlugin.kt index ea9ab9d17e..5aad15a0b3 100644 --- a/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutterPlugin.kt +++ b/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutterPlugin.kt @@ -16,10 +16,9 @@ import io.sentry.Hint import io.sentry.HubAdapter import io.sentry.Sentry import io.sentry.SentryEvent -import io.sentry.SentryLevel import io.sentry.SentryOptions import io.sentry.android.core.ActivityFramesTracker -import io.sentry.android.core.BuildConfig.VERSION_NAME +import io.sentry.android.core.InternalSentrySdk import io.sentry.android.core.LoadClass import io.sentry.android.core.SentryAndroid import io.sentry.android.core.SentryAndroidOptions @@ -28,10 +27,7 @@ import io.sentry.protocol.DebugImage import io.sentry.protocol.SdkVersion import io.sentry.protocol.SentryId import io.sentry.protocol.User -import java.io.File import java.lang.ref.WeakReference -import java.util.Locale -import java.util.UUID class SentryFlutterPlugin : FlutterPlugin, MethodCallHandler, ActivityAware { private lateinit var channel: MethodChannel @@ -46,10 +42,11 @@ class SentryFlutterPlugin : FlutterPlugin, MethodCallHandler, ActivityAware { channel = MethodChannel(flutterPluginBinding.binaryMessenger, "sentry_flutter") channel.setMethodCallHandler(this) - sentryFlutter = SentryFlutter( - androidSdk = androidSdk, - nativeSdk = nativeSdk - ) + sentryFlutter = + SentryFlutter( + androidSdk = androidSdk, + nativeSdk = nativeSdk, + ) } override fun onMethodCall(call: MethodCall, result: Result) { @@ -70,6 +67,7 @@ class SentryFlutterPlugin : FlutterPlugin, MethodCallHandler, ActivityAware { "removeExtra" -> removeExtra(call.argument("key"), result) "setTag" -> setTag(call.argument("key"), call.argument("value"), result) "removeTag" -> removeTag(call.argument("key"), result) + "loadContexts" -> loadContexts(result) else -> result.notImplemented() } } @@ -99,18 +97,6 @@ class SentryFlutterPlugin : FlutterPlugin, MethodCallHandler, ActivityAware { // Stub } - private fun writeEnvelope(envelope: ByteArray): Boolean { - val options = HubAdapter.getInstance().options - if (options.outboxPath.isNullOrEmpty()) { - return false - } - - val file = File(options.outboxPath, UUID.randomUUID().toString()) - file.writeBytes(envelope) - - return true - } - private fun initNativeSdk(call: MethodCall, result: Result) { if (!this::context.isInitialized) { result.error("1", "Context is null", null) @@ -142,7 +128,8 @@ class SentryFlutterPlugin : FlutterPlugin, MethodCallHandler, ActivityAware { } val appStartTime = AppStartMetrics.getInstance().appStartTimeSpan.startTimestamp - val isColdStart = AppStartMetrics.getInstance().appStartType == AppStartMetrics.AppStartType.COLD + val isColdStart = + AppStartMetrics.getInstance().appStartType == AppStartMetrics.AppStartType.COLD if (appStartTime == null) { Log.w("Sentry", "App start won't be sent due to missing appStartTime") @@ -151,7 +138,7 @@ class SentryFlutterPlugin : FlutterPlugin, MethodCallHandler, ActivityAware { val appStartTimeMillis = DateUtils.nanosToMillis(appStartTime.nanoTimestamp().toDouble()) val item = mapOf( "appStartTime" to appStartTimeMillis, - "isColdStart" to isColdStart + "isColdStart" to isColdStart, ) result.success(item) } @@ -192,7 +179,7 @@ class SentryFlutterPlugin : FlutterPlugin, MethodCallHandler, ActivityAware { val frames = mapOf( "totalFrames" to total, "slowFrames" to slow, - "frozenFrames" to frozen + "frozenFrames" to frozen, ) result.success(frames) } @@ -293,20 +280,19 @@ class SentryFlutterPlugin : FlutterPlugin, MethodCallHandler, ActivityAware { result.error("1", "The Sentry Android SDK is disabled", null) return } - - val args = call.arguments() as List? ?: listOf() + val args = call.arguments() as List? ?: listOf() if (args.isNotEmpty()) { val event = args.first() as ByteArray? - if (event != null && event.isNotEmpty()) { - if (!writeEnvelope(event)) { - result.error("2", "SentryOptions or outboxPath are null or empty", null) + val id = InternalSentrySdk.captureEnvelope(event) + if (id != null) { + result.success("") + } else { + result.error("2", "Failed to capture envelope", null) } - result.success("") return } } - result.error("3", "Envelope is null or empty", null) } @@ -344,7 +330,7 @@ class SentryFlutterPlugin : FlutterPlugin, MethodCallHandler, ActivityAware { } private class BeforeSendCallbackImpl( - private val sdkVersion: SdkVersion? + private val sdkVersion: SdkVersion?, ) : SentryOptions.BeforeSendCallback { override fun execute(event: SentryEvent, hint: Hint): SentryEvent { setEventOriginTag(event) @@ -372,7 +358,7 @@ class SentryFlutterPlugin : FlutterPlugin, MethodCallHandler, ActivityAware { private fun setEventEnvironmentTag( event: SentryEvent, origin: String = "android", - environment: String + environment: String, ) { event.setTag("event.origin", origin) event.setTag("event.environment", environment) @@ -391,4 +377,20 @@ class SentryFlutterPlugin : FlutterPlugin, MethodCallHandler, ActivityAware { } } } + + private fun loadContexts(result: Result) { + val options = HubAdapter.getInstance().options + if (options !is SentryAndroidOptions) { + result.success(null) + return + } + val currentScope = InternalSentrySdk.getCurrentScope() + val serializedScope = + InternalSentrySdk.serializeScope( + context, + options, + currentScope, + ) + result.success(serializedScope) + } } diff --git a/flutter/android/src/test/kotlin/io/sentry/flutter/SentryFlutterTest.kt b/flutter/android/src/test/kotlin/io/sentry/flutter/SentryFlutterTest.kt index 3a5c8678f8..724559bb76 100644 --- a/flutter/android/src/test/kotlin/io/sentry/flutter/SentryFlutterTest.kt +++ b/flutter/android/src/test/kotlin/io/sentry/flutter/SentryFlutterTest.kt @@ -8,7 +8,6 @@ import org.junit.Before import org.junit.Test class SentryFlutterTest { - private lateinit var fixture: Fixture @Before @@ -53,7 +52,7 @@ class SentryFlutterTest { assertEquals(BuildConfig.VERSION_NAME, fixture.options.sdkVersion?.version) assertEquals( "sentry.java.android.flutter/${BuildConfig.VERSION_NAME}", - fixture.options.sentryClientName + fixture.options.sentryClientName, ) assertEquals("fixture-nativeSdk", fixture.options.nativeSdkName) @@ -73,8 +72,8 @@ class SentryFlutterTest { sut.updateOptions( fixture.options, mapOf( - "diagnosticLevel" to "warning" - ) + "diagnosticLevel" to "warning", + ), ) // Then @@ -90,8 +89,8 @@ class SentryFlutterTest { sut.updateOptions( fixture.options, mapOf( - "enableNativeCrashHandling" to false - ) + "enableNativeCrashHandling" to false, + ), ) // Then @@ -101,39 +100,39 @@ class SentryFlutterTest { } class Fixture { - var options = SentryAndroidOptions() - val data = mapOf( - "dsn" to "fixture-dsn", - "debug" to true, - "environment" to "fixture-environment", - "release" to "fixture-release", - "dist" to "fixture-dist", - "enableAutoSessionTracking" to false, - "autoSessionTrackingIntervalMillis" to 9001L, - "anrTimeoutIntervalMillis" to 9002L, - "attachThreads" to true, - "attachStacktrace" to false, - "enableAutoNativeBreadcrumbs" to false, - "maxBreadcrumbs" to 9003, - "maxCacheItems" to 9004, - "anrEnabled" to false, - "sendDefaultPii" to true, - "enableNdkScopeSync" to false, - "proguardUuid" to "fixture-proguardUuid", - "enableNativeCrashHandling" to false, - "sendClientReports" to false, - "maxAttachmentSize" to 9005L, - "enableAutoPerformanceTracing" to true, - "connectionTimeoutMillis" to 9006, - "readTimeoutMillis" to 9007 - ) + val data = + mapOf( + "dsn" to "fixture-dsn", + "debug" to true, + "environment" to "fixture-environment", + "release" to "fixture-release", + "dist" to "fixture-dist", + "enableAutoSessionTracking" to false, + "autoSessionTrackingIntervalMillis" to 9001L, + "anrTimeoutIntervalMillis" to 9002L, + "attachThreads" to true, + "attachStacktrace" to false, + "enableAutoNativeBreadcrumbs" to false, + "maxBreadcrumbs" to 9003, + "maxCacheItems" to 9004, + "anrEnabled" to false, + "sendDefaultPii" to true, + "enableNdkScopeSync" to false, + "proguardUuid" to "fixture-proguardUuid", + "enableNativeCrashHandling" to false, + "sendClientReports" to false, + "maxAttachmentSize" to 9005L, + "enableAutoPerformanceTracing" to true, + "connectionTimeoutMillis" to 9006, + "readTimeoutMillis" to 9007, + ) fun getSut(): SentryFlutter { return SentryFlutter( androidSdk = "sentry.java.android.flutter", - nativeSdk = "fixture-nativeSdk" + nativeSdk = "fixture-nativeSdk", ) } } diff --git a/flutter/config/detekt-bl.xml b/flutter/config/detekt-bl.xml index bf2e55e08b..bfd59bc97e 100644 --- a/flutter/config/detekt-bl.xml +++ b/flutter/config/detekt-bl.xml @@ -2,9 +2,8 @@ - ComplexMethod:SentryFlutterPlugin.kt$SentryFlutterPlugin$override fun onMethodCall(call: MethodCall, result: Result) CyclomaticComplexMethod:SentryFlutterPlugin.kt$SentryFlutterPlugin$override fun onMethodCall(call: MethodCall, result: Result) - LongMethod:SentryFlutter.kt$SentryFlutter$fun updateOptions(options: SentryAndroidOptions, data: Map<String, Any>) + LongMethod:SentryFlutter.kt$SentryFlutter$fun updateOptions( options: SentryAndroidOptions, data: Map<String, Any>, ) MagicNumber:MainActivity.kt$MainActivity$6_000 TooGenericExceptionCaught:MainActivity.kt$MainActivity$e: Exception TooGenericExceptionThrown:MainActivity.kt$MainActivity$throw Exception("Catch this java exception thrown from Kotlin thread!") diff --git a/flutter/example/integration_test/integration_test.dart b/flutter/example/integration_test/integration_test.dart index f292d04cfc..570b8c1fe2 100644 --- a/flutter/example/integration_test/integration_test.dart +++ b/flutter/example/integration_test/integration_test.dart @@ -203,7 +203,7 @@ void main() { class Fixture { SentryEvent? sentEvent; - FutureOr beforeSend(SentryEvent event, {Hint? hint}) async { + FutureOr beforeSend(SentryEvent event, Hint hint) async { sentEvent = event; return event; } diff --git a/flutter/example/ios/Flutter/AppFrameworkInfo.plist b/flutter/example/ios/Flutter/AppFrameworkInfo.plist index 1bdf525f9f..b7506dd05b 100644 --- a/flutter/example/ios/Flutter/AppFrameworkInfo.plist +++ b/flutter/example/ios/Flutter/AppFrameworkInfo.plist @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 11.0 + 12.0 diff --git a/flutter/example/ios/Gemfile b/flutter/example/ios/Gemfile new file mode 100644 index 0000000000..7a118b49be --- /dev/null +++ b/flutter/example/ios/Gemfile @@ -0,0 +1,3 @@ +source "https://rubygems.org" + +gem "fastlane" diff --git a/flutter/example/ios/Podfile b/flutter/example/ios/Podfile index 877d653518..8cb4ddb285 100644 --- a/flutter/example/ios/Podfile +++ b/flutter/example/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -platform :ios, '11.0' +platform :ios, '12.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' @@ -44,7 +44,7 @@ post_install do |installer| installer.pods_project.targets.each do |target| flutter_additional_ios_build_settings(target) target.build_configurations.each do |config| - config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '11.0' + config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '12.0' end end end diff --git a/flutter/example/ios/Runner.xcodeproj/project.pbxproj b/flutter/example/ios/Runner.xcodeproj/project.pbxproj index 29c58327af..f8c39c79d5 100644 --- a/flutter/example/ios/Runner.xcodeproj/project.pbxproj +++ b/flutter/example/ios/Runner.xcodeproj/project.pbxproj @@ -221,7 +221,7 @@ attributes = { BuildIndependentTargetsInParallel = YES; LastSwiftUpdateCheck = 1430; - LastUpgradeCheck = 1430; + LastUpgradeCheck = 1510; ORGANIZATIONNAME = ""; TargetAttributes = { 92B25CE92A80EB3100884BDF = { @@ -460,7 +460,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -483,6 +483,7 @@ "$(PROJECT_DIR)/Flutter", ); INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -491,7 +492,7 @@ "$(inherited)", "$(PROJECT_DIR)/Flutter", ); - PRODUCT_BUNDLE_IDENTIFIER = io.sentry.flutter.example; + PRODUCT_BUNDLE_IDENTIFIER = io.sentry.flutter.sample; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; @@ -518,7 +519,7 @@ MARKETING_VERSION = 1.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = io.sentry.flutter.example.RunnerTests; + PRODUCT_BUNDLE_IDENTIFIER = io.sentry.flutter.sample.RunnerTests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_EMIT_LOC_STRINGS = NO; @@ -547,7 +548,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 16.2; MARKETING_VERSION = 1.0; MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = io.sentry.flutter.example.RunnerTests; + PRODUCT_BUNDLE_IDENTIFIER = io.sentry.flutter.sample.RunnerTests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = NO; SWIFT_VERSION = 5.0; @@ -574,7 +575,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 16.2; MARKETING_VERSION = 1.0; MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = io.sentry.flutter.example.RunnerTests; + PRODUCT_BUNDLE_IDENTIFIER = io.sentry.flutter.sample.RunnerTests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = NO; SWIFT_VERSION = 5.0; @@ -631,7 +632,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -681,7 +682,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -706,6 +707,7 @@ "$(PROJECT_DIR)/Flutter", ); INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -714,7 +716,7 @@ "$(inherited)", "$(PROJECT_DIR)/Flutter", ); - PRODUCT_BUNDLE_IDENTIFIER = io.sentry.flutter.example; + PRODUCT_BUNDLE_IDENTIFIER = io.sentry.flutter.sample; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; @@ -737,6 +739,7 @@ "$(PROJECT_DIR)/Flutter", ); INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -745,7 +748,7 @@ "$(inherited)", "$(PROJECT_DIR)/Flutter", ); - PRODUCT_BUNDLE_IDENTIFIER = io.sentry.flutter.example; + PRODUCT_BUNDLE_IDENTIFIER = io.sentry.flutter.sample; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; diff --git a/flutter/example/ios/Runner/Info.plist b/flutter/example/ios/Runner/Info.plist index 91d89f84d6..1023c8c85e 100644 --- a/flutter/example/ios/Runner/Info.plist +++ b/flutter/example/ios/Runner/Info.plist @@ -2,6 +2,10 @@ + ITSAppUsesNonExemptEncryption + + CADisableMinimumFrameDurationOnPhone + CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) CFBundleExecutable @@ -22,6 +26,8 @@ $(FLUTTER_BUILD_NUMBER) LSRequiresIPhoneOS + UIApplicationSupportsIndirectInputEvents + UILaunchStoryboardName LaunchScreen UIMainStoryboardFile @@ -41,9 +47,5 @@ UIViewControllerBasedStatusBarAppearance - CADisableMinimumFrameDurationOnPhone - - UIApplicationSupportsIndirectInputEvents - diff --git a/flutter/example/ios/RunnerTests/SentryFlutterTests.swift b/flutter/example/ios/RunnerTests/SentryFlutterTests.swift index 9dbb70ba51..057b2363b5 100644 --- a/flutter/example/ios/RunnerTests/SentryFlutterTests.swift +++ b/flutter/example/ios/RunnerTests/SentryFlutterTests.swift @@ -41,7 +41,6 @@ final class SentryFlutterTests: XCTestCase { "enableWatchdogTerminationTracking": false, "sendClientReports": false, "maxAttachmentSize": NSNumber(value: 9004), - "recordHttpBreadcrumbs": false, "captureFailedRequests": false, "enableAppHangTracking": false, "appHangTimeoutIntervalMillis": NSNumber(value: 10000) @@ -66,7 +65,6 @@ final class SentryFlutterTests: XCTestCase { XCTAssertEqual(false, fixture.options.enableWatchdogTerminationTracking) XCTAssertEqual(false, fixture.options.sendClientReports) XCTAssertEqual(9004, fixture.options.maxAttachmentSize) - XCTAssertEqual(false, fixture.options.enableNetworkBreadcrumbs) XCTAssertEqual(false, fixture.options.enableCaptureFailedRequests) XCTAssertEqual(false, fixture.options.enableAppHangTracking) XCTAssertEqual(10, fixture.options.appHangTimeoutInterval) diff --git a/flutter/example/ios/fastlane/Appfile b/flutter/example/ios/fastlane/Appfile new file mode 100644 index 0000000000..1f85333eac --- /dev/null +++ b/flutter/example/ios/fastlane/Appfile @@ -0,0 +1,7 @@ +app_identifier("io.sentry.flutter.sample") # The bundle identifier of your app + +itc_team_id("96157806") # App Store Connect Team ID +team_id("97JCY7859U") # Developer Portal Team ID + +# For more information about the Appfile, see: +# https://docs.fastlane.tools/advanced/#appfile diff --git a/flutter/example/ios/fastlane/Fastfile b/flutter/example/ios/fastlane/Fastfile new file mode 100644 index 0000000000..e14ca13d3c --- /dev/null +++ b/flutter/example/ios/fastlane/Fastfile @@ -0,0 +1,95 @@ +default_platform(:ios) + +platform :ios do + + desc "Bump Build Number" + lane :bump_build_number do + fetch_api_key() + + version_string = get_version_number(xcodeproj: "./Runner.xcodeproj") + version_parts = version_string.split(".") + + # Remove last digit if necessary + if version_parts.length > 3 + version_parts.pop + end + + new_version = version_parts.join(".") + + increment_version_number( + version_number: new_version, + xcodeproj: "./Runner.xcodeproj" + ) + increment_build_number( + build_number: latest_testflight_build_number + 1, + xcodeproj: "./Runner.xcodeproj" + ) + end + + desc "Build Release" + lane :build_release do + + setup_ci + + disable_automatic_code_signing + + sync_code_signing( + type: "development", + readonly: true, + app_identifier: ["io.sentry.flutter.sample"] + ) + + sync_code_signing( + type: "appstore", + readonly: true, + app_identifier: ["io.sentry.flutter.sample"] + ) + + update_project_provisioning( + xcodeproj: "Runner.xcodeproj", + target_filter: "Runner", + profile: ENV["sigh_io.sentry.flutter.sample_appstore_profile-path"], + build_configuration: "Release" + ) + + build_app( + workspace: "Runner.xcworkspace", + scheme: "Runner", + configuration: "Release", + clean: true, + include_symbols: true, + export_method: "app-store", + output_directory:"./build/", + export_options: { + method: "app-store", + provisioningProfiles: { + "io.sentry.flutter.sample" => ENV["sigh_io.sentry.flutter.sample_appstore_profile-name"] + } + }, + codesigning_identity: ENV["sigh_io.sentry.flutter.sample_appstore_certificate-name"], + output_name: "sentry_flutter_sample.ipa" + ) + + delete_keychain( + name: "fastlane_tmp_keychain" + ) unless is_ci + end + + desc "Upload to TestFlight" + lane :upload_testflight do + fetch_api_key() + testflight( + skip_waiting_for_build_processing: true, + ipa: "./build/sentry_flutter_sample.ipa" + ) + end + + desc "Fetch ASC API Key" + lane :fetch_api_key do + app_store_connect_api_key( + key_id: ENV["APP_STORE_CONNECT_KEY_ID"], + issuer_id: ENV["APP_STORE_CONNECT_ISSUER_ID"], + key_content: ENV["APP_STORE_CONNECT_KEY"] + ) + end +end diff --git a/flutter/example/ios/fastlane/Matchfile b/flutter/example/ios/fastlane/Matchfile new file mode 100644 index 0000000000..054fef1c37 --- /dev/null +++ b/flutter/example/ios/fastlane/Matchfile @@ -0,0 +1,5 @@ +git_url("git@github.com:getsentry/codesigning.git") +storage_mode("git") +username("bot@getsentry.com") # Your Apple Developer Portal username + +# The docs are available on https://docs.fastlane.tools/actions/match diff --git a/flutter/example/lib/main.dart b/flutter/example/lib/main.dart index c7f202f4f9..86da143e31 100644 --- a/flutter/example/lib/main.dart +++ b/flutter/example/lib/main.dart @@ -496,7 +496,6 @@ class MainScaffold extends StatelessWidget { TooltipButton( onPressed: () async { final id = await Sentry.captureMessage('UserFeedback'); - if (!context.mounted) return; await showDialog( context: context, diff --git a/flutter/example/pubspec.yaml b/flutter/example/pubspec.yaml index 80bb0a3ff5..ef571be2a7 100644 --- a/flutter/example/pubspec.yaml +++ b/flutter/example/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_flutter_example description: Demonstrates how to use the sentry_flutter plugin. -version: 7.20.0 +version: 8.0.0 publish_to: 'none' # Remove this line if you wish to publish to pub.dev diff --git a/flutter/ios/sentry_flutter.podspec b/flutter/ios/sentry_flutter.podspec index c55470dc37..184a5ae7d2 100644 --- a/flutter/ios/sentry_flutter.podspec +++ b/flutter/ios/sentry_flutter.podspec @@ -19,7 +19,7 @@ Sentry SDK for Flutter with support to native through sentry-cocoa. s.dependency 'Sentry/HybridSDK', '8.21.0' s.ios.dependency 'Flutter' s.osx.dependency 'FlutterMacOS' - s.ios.deployment_target = '11.0' + s.ios.deployment_target = '12.0' # Flutter 3.7 requires 10.14 s.osx.deployment_target = '10.13' diff --git a/flutter/lib/src/event_processor/android_platform_exception_event_processor.dart b/flutter/lib/src/event_processor/android_platform_exception_event_processor.dart index c784f5b221..6570dedd81 100644 --- a/flutter/lib/src/event_processor/android_platform_exception_event_processor.dart +++ b/flutter/lib/src/event_processor/android_platform_exception_event_processor.dart @@ -16,7 +16,7 @@ class AndroidPlatformExceptionEventProcessor implements EventProcessor { final SentryFlutterOptions _options; @override - Future apply(SentryEvent event, {Hint? hint}) async { + Future apply(SentryEvent event, Hint hint) async { if (event is SentryTransaction) { return event; } diff --git a/flutter/lib/src/event_processor/flutter_enricher_event_processor.dart b/flutter/lib/src/event_processor/flutter_enricher_event_processor.dart index 615c7a4974..0ea1b731d6 100644 --- a/flutter/lib/src/event_processor/flutter_enricher_event_processor.dart +++ b/flutter/lib/src/event_processor/flutter_enricher_event_processor.dart @@ -32,9 +32,9 @@ class FlutterEnricherEventProcessor implements EventProcessor { @override Future apply( - SentryEvent event, { - Hint? hint, - }) async { + SentryEvent event, + Hint hint, + ) async { // If there's a native integration available, it probably has better // information available than Flutter. final device = diff --git a/flutter/lib/src/event_processor/flutter_exception_event_processor.dart b/flutter/lib/src/event_processor/flutter_exception_event_processor.dart index e0f4b6af14..05f9fd6595 100644 --- a/flutter/lib/src/event_processor/flutter_exception_event_processor.dart +++ b/flutter/lib/src/event_processor/flutter_exception_event_processor.dart @@ -3,7 +3,7 @@ import 'package:sentry/sentry.dart'; class FlutterExceptionEventProcessor implements EventProcessor { @override - SentryEvent? apply(SentryEvent event, {Hint? hint}) { + SentryEvent? apply(SentryEvent event, Hint hint) { if (event is SentryTransaction) { return event; } diff --git a/flutter/lib/src/event_processor/native_app_start_event_processor.dart b/flutter/lib/src/event_processor/native_app_start_event_processor.dart index fd1a5ec169..f75bbc4833 100644 --- a/flutter/lib/src/event_processor/native_app_start_event_processor.dart +++ b/flutter/lib/src/event_processor/native_app_start_event_processor.dart @@ -13,7 +13,7 @@ class NativeAppStartEventProcessor implements EventProcessor { NativeAppStartEventProcessor(this._native); @override - Future apply(SentryEvent event, {Hint? hint}) async { + Future apply(SentryEvent event, Hint hint) async { if (_native.didAddAppStartMeasurement || event is! SentryTransaction) { return event; } diff --git a/flutter/lib/src/event_processor/platform_exception_event_processor.dart b/flutter/lib/src/event_processor/platform_exception_event_processor.dart index d403509ae9..2bf33e60f9 100644 --- a/flutter/lib/src/event_processor/platform_exception_event_processor.dart +++ b/flutter/lib/src/event_processor/platform_exception_event_processor.dart @@ -4,7 +4,7 @@ import 'package:sentry/sentry.dart'; /// Add code & message from [PlatformException] to [SentryException] class PlatformExceptionEventProcessor implements EventProcessor { @override - SentryEvent? apply(SentryEvent event, {Hint? hint}) { + SentryEvent? apply(SentryEvent event, Hint hint) { if (event is SentryTransaction) { return event; } diff --git a/flutter/lib/src/event_processor/screenshot_event_processor.dart b/flutter/lib/src/event_processor/screenshot_event_processor.dart index 48e0a4c4d6..8981afe7b1 100644 --- a/flutter/lib/src/event_processor/screenshot_event_processor.dart +++ b/flutter/lib/src/event_processor/screenshot_event_processor.dart @@ -20,7 +20,7 @@ class ScreenshotEventProcessor implements EventProcessor { sentryScreenshotWidgetGlobalKey.currentContext != null; @override - Future apply(SentryEvent event, {Hint? hint}) async { + Future apply(SentryEvent event, Hint hint) async { if (event is SentryTransaction) { return event; } @@ -78,7 +78,7 @@ class ScreenshotEventProcessor implements EventProcessor { final bytes = await _createScreenshot(); if (bytes != null) { - hint?.screenshot = SentryAttachment.fromScreenshotData(bytes); + hint.screenshot = SentryAttachment.fromScreenshotData(bytes); } return event; } diff --git a/flutter/lib/src/event_processor/widget_event_processor.dart b/flutter/lib/src/event_processor/widget_event_processor.dart index 88e9159d4d..c297585f49 100644 --- a/flutter/lib/src/event_processor/widget_event_processor.dart +++ b/flutter/lib/src/event_processor/widget_event_processor.dart @@ -6,7 +6,7 @@ import '../../sentry_flutter.dart'; class WidgetEventProcessor implements EventProcessor { @override - FutureOr apply(SentryEvent event, {Hint? hint}) { + FutureOr apply(SentryEvent event, Hint hint) { if (event is SentryTransaction) { return event; } diff --git a/flutter/lib/src/integrations/flutter_error_integration.dart b/flutter/lib/src/integrations/flutter_error_integration.dart index 3f88b99361..c1a6d57a1d 100644 --- a/flutter/lib/src/integrations/flutter_error_integration.dart +++ b/flutter/lib/src/integrations/flutter_error_integration.dart @@ -54,11 +54,8 @@ class FlutterErrorIntegration implements Integration { stackTrace: errorDetails.stack, ); - // FlutterError doesn't crash the App. - final mechanism = Mechanism( - type: 'FlutterError', - handled: true, - ); + // FlutterError doesn't crash the app, but is not handled by the user. + final mechanism = Mechanism(type: 'FlutterError', handled: false); final throwableMechanism = ThrowableMechanism(mechanism, exception); var event = SentryEvent( diff --git a/flutter/lib/src/integrations/load_contexts_integration.dart b/flutter/lib/src/integrations/load_contexts_integration.dart index c77981d35c..df8b52b97a 100644 --- a/flutter/lib/src/integrations/load_contexts_integration.dart +++ b/flutter/lib/src/integrations/load_contexts_integration.dart @@ -4,21 +4,16 @@ import 'package:flutter/services.dart'; import 'package:sentry/sentry.dart'; import '../sentry_flutter_options.dart'; -/// Load Device's Contexts from the iOS SDK. +/// Load Device's Contexts from the iOS & Android SDKs. /// -/// This integration calls the iOS SDK via Message channel to load the -/// Device's contexts before sending the event back to the iOS SDK via +/// This integration calls the iOS & Android SDKs via Message channel to load +/// the Device's contexts before sending the event back to the SDK via /// Message channel (already enriched with all the information). /// /// The Device's contexts are: /// App, Device and OS. /// -/// ps. This integration won't be run on Android because the Device's Contexts -/// is set on Android when the event is sent to the Android SDK via -/// the Message channel. -/// We intend to unify this behaviour in the future. -/// -/// This integration is only executed on iOS & MacOS Apps. +/// This integration is only executed on iOS, macOS & Android Apps. class LoadContextsIntegration extends Integration { final MethodChannel _channel; @@ -40,7 +35,7 @@ class _LoadContextsIntegrationEventProcessor implements EventProcessor { final SentryFlutterOptions _options; @override - Future apply(SentryEvent event, {Hint? hint}) async { + Future apply(SentryEvent event, Hint hint) async { try { final loadContexts = await _channel.invokeMethod('loadContexts'); @@ -163,7 +158,7 @@ class _LoadContextsIntegrationEventProcessor implements EventProcessor { ); if (beforeBreadcrumb != null) { - final processedBreadcrumb = beforeBreadcrumb(breadcrumb); + final processedBreadcrumb = beforeBreadcrumb(breadcrumb, Hint()); if (processedBreadcrumb != null) { breadcrumbs.add(processedBreadcrumb); } @@ -204,8 +199,8 @@ class _LoadContextsIntegrationEventProcessor implements EventProcessor { event = event.copyWith(sdk: sdk); } - // on iOS, captureEnvelope does not call the beforeSend callback, - // hence we need to add these tags here. + // captureEnvelope does not call the beforeSend callback, hence we need to + // add these tags here. if (event.sdk?.name == 'sentry.dart.flutter') { final tags = event.tags ?? {}; tags['event.origin'] = 'flutter'; diff --git a/flutter/lib/src/integrations/load_image_list_integration.dart b/flutter/lib/src/integrations/load_image_list_integration.dart index 8838ae0e4b..ae08d93946 100644 --- a/flutter/lib/src/integrations/load_image_list_integration.dart +++ b/flutter/lib/src/integrations/load_image_list_integration.dart @@ -54,7 +54,7 @@ class _LoadImageListIntegrationEventProcessor implements EventProcessor { final SentryFlutterOptions _options; @override - Future apply(SentryEvent event, {Hint? hint}) async { + Future apply(SentryEvent event, Hint hint) async { if (event.needsSymbolication()) { try { // we call on every event because the loaded image list is cached diff --git a/flutter/lib/src/sentry_flutter.dart b/flutter/lib/src/sentry_flutter.dart index 6c4e2c243b..1931e86981 100644 --- a/flutter/lib/src/sentry_flutter.dart +++ b/flutter/lib/src/sentry_flutter.dart @@ -160,7 +160,7 @@ mixin SentryFlutter { // Will enrich events with device context, native packages and integrations if (platformChecker.hasNativeIntegration && !platformChecker.isWeb && - (platform.isIOS || platform.isMacOS)) { + (platform.isIOS || platform.isMacOS || platform.isAndroid)) { integrations.add(LoadContextsIntegration(channel)); } diff --git a/flutter/lib/src/user_interaction/sentry_user_interaction_widget.dart b/flutter/lib/src/user_interaction/sentry_user_interaction_widget.dart index 45af49b14d..018f750a2e 100644 --- a/flutter/lib/src/user_interaction/sentry_user_interaction_widget.dart +++ b/flutter/lib/src/user_interaction/sentry_user_interaction_widget.dart @@ -317,7 +317,8 @@ class _SentryUserInteractionWidgetState void _onTappedAt(Offset position) { final tappedWidget = _getElementAt(position); - final keyValue = tappedWidget?.element.widget.key?.toStringValue(); + final keyValue = + WidgetUtils.toStringValue(tappedWidget?.element.widget.key); if (tappedWidget == null || keyValue == null) { return; } diff --git a/flutter/lib/src/version.dart b/flutter/lib/src/version.dart index e9f6c225d1..233de685ed 100644 --- a/flutter/lib/src/version.dart +++ b/flutter/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.20.0'; +const String sdkVersion = '8.0.0'; /// The default SDK name reported to Sentry.io in the submitted events. const String sdkName = 'sentry.dart.flutter'; diff --git a/flutter/lib/src/view_hierarchy/sentry_tree_walker.dart b/flutter/lib/src/view_hierarchy/sentry_tree_walker.dart index 2a85bf49be..41b03f4808 100644 --- a/flutter/lib/src/view_hierarchy/sentry_tree_walker.dart +++ b/flutter/lib/src/view_hierarchy/sentry_tree_walker.dart @@ -281,7 +281,7 @@ class _TreeWalker { return SentryViewHierarchyElement( element.widget.runtimeType.toString(), depth: element.depth, - identifier: element.widget.key?.toStringValue(), + identifier: WidgetUtils.toStringValue(element.widget.key), width: width, height: height, x: x, diff --git a/flutter/lib/src/view_hierarchy/view_hierarchy_event_processor.dart b/flutter/lib/src/view_hierarchy/view_hierarchy_event_processor.dart index 99d43ad982..c3fefe52f5 100644 --- a/flutter/lib/src/view_hierarchy/view_hierarchy_event_processor.dart +++ b/flutter/lib/src/view_hierarchy/view_hierarchy_event_processor.dart @@ -1,7 +1,7 @@ import '../../sentry_flutter.dart'; import 'sentry_tree_walker.dart'; -/// A [EventProcessor] that renders an ASCII represention of the entire view +/// A [EventProcessor] that renders an ASCII representation of the entire view /// hierarchy of the application when an error happens and includes it as an /// attachment to the [Hint]. class SentryViewHierarchyEventProcessor implements EventProcessor { @@ -10,7 +10,7 @@ class SentryViewHierarchyEventProcessor implements EventProcessor { final SentryFlutterOptions _options; @override - SentryEvent? apply(SentryEvent event, {Hint? hint}) { + SentryEvent? apply(SentryEvent event, Hint hint) { if (event is SentryTransaction) { return event; } @@ -31,7 +31,7 @@ class SentryViewHierarchyEventProcessor implements EventProcessor { final viewHierarchy = SentryAttachment.fromViewHierarchy(sentryViewHierarchy); - hint?.viewHierarchy = viewHierarchy; + hint.viewHierarchy = viewHierarchy; return event; } } diff --git a/flutter/lib/src/widget_utils.dart b/flutter/lib/src/widget_utils.dart index 9d63b8d5a3..97d51a990a 100644 --- a/flutter/lib/src/widget_utils.dart +++ b/flutter/lib/src/widget_utils.dart @@ -1,8 +1,12 @@ import 'package:flutter/widgets.dart'; +import 'package:meta/meta.dart'; -extension WidgetExtension on Key { - String? toStringValue() { - final key = this; +@internal +class WidgetUtils { + static String? toStringValue(Key? key) { + if (key == null) { + return null; + } if (key is ValueKey) { return key.value; } else if (key is ValueKey) { diff --git a/flutter/pubspec.yaml b/flutter/pubspec.yaml index 34f6a7713d..040bbc47cb 100644 --- a/flutter/pubspec.yaml +++ b/flutter/pubspec.yaml @@ -1,5 +1,5 @@ name: sentry_flutter -version: 7.20.0 +version: 8.0.0 description: Sentry SDK for Flutter. This package aims to support different Flutter targets by relying on the many platforms supported by Sentry with native SDKs. homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart @@ -23,7 +23,7 @@ dependencies: sdk: flutter flutter_web_plugins: sdk: flutter - sentry: 7.20.0 + sentry: 8.0.0 package_info_plus: '>=1.0.0 <8.0.0' meta: ^1.3.0 ffi: ^2.0.0 diff --git a/flutter/test/android_platform_exception_event_processor_test.dart b/flutter/test/android_platform_exception_event_processor_test.dart index f98bedbe26..5e916f06a3 100644 --- a/flutter/test/android_platform_exception_event_processor_test.dart +++ b/flutter/test/android_platform_exception_event_processor_test.dart @@ -26,8 +26,8 @@ void main() { group(AndroidPlatformExceptionEventProcessor, () { test('exception is correctly parsed', () async { - final platformExceptionEvent = - await fixture.processor.apply(fixture.eventWithPlatformStackTrace); + final platformExceptionEvent = await fixture.processor + .apply(fixture.eventWithPlatformStackTrace, Hint()); final exceptions = platformExceptionEvent!.exceptions!; expect(exceptions.length, 3); @@ -54,8 +54,8 @@ void main() { test( 'Dart thread is current and not crashed if Android exception is present', () async { - final platformExceptionEvent = - await fixture.processor.apply(fixture.eventWithPlatformStackTrace); + final platformExceptionEvent = await fixture.processor + .apply(fixture.eventWithPlatformStackTrace, Hint()); final exceptions = platformExceptionEvent!.exceptions!; expect(exceptions.length, 3); @@ -65,8 +65,8 @@ void main() { }); test('platformexception has Android thread attached', () async { - final platformExceptionEvent = - await fixture.processor.apply(fixture.eventWithPlatformStackTrace); + final platformExceptionEvent = await fixture.processor + .apply(fixture.eventWithPlatformStackTrace, Hint()); final exceptions = platformExceptionEvent!.exceptions!; expect(exceptions.length, 3); @@ -85,8 +85,8 @@ void main() { fixture.options.attachThreads = false; final threadCount = fixture.eventWithPlatformStackTrace.threads?.length; - final platformExceptionEvent = - await fixture.processor.apply(fixture.eventWithPlatformStackTrace); + final platformExceptionEvent = await fixture.processor + .apply(fixture.eventWithPlatformStackTrace, Hint()); final exceptions = platformExceptionEvent!.exceptions!; expect(exceptions.length, 3); @@ -103,14 +103,15 @@ void main() { throwable: null, ); - final platformExceptionEvent = await fixture.processor.apply(event); + final platformExceptionEvent = + await fixture.processor.apply(event, Hint()); expect(event, platformExceptionEvent); }); test('does nothing if PlatformException has no stackTrace', () async { - final platformExceptionEvent = - await fixture.processor.apply(fixture.eventWithoutPlatformStackTrace); + final platformExceptionEvent = await fixture.processor + .apply(fixture.eventWithoutPlatformStackTrace, Hint()); expect(fixture.eventWithoutPlatformStackTrace, platformExceptionEvent); }); diff --git a/flutter/test/event_processor/flutter_enricher_event_processor_test.dart b/flutter/test/event_processor/flutter_enricher_event_processor_test.dart index 5fbc1d7034..892e7ff517 100644 --- a/flutter/test/event_processor/flutter_enricher_event_processor_test.dart +++ b/flutter/test/event_processor/flutter_enricher_event_processor_test.dart @@ -39,7 +39,7 @@ void main() { binding: () => tester.binding, ); - final event = await enricher.apply(SentryEvent()); + final event = await enricher.apply(SentryEvent(), Hint()); debugBrightnessOverride = null; debugDefaultTargetPlatformOverride = null; @@ -65,7 +65,7 @@ void main() { binding: () => tester.binding, ); - final event = await enricher.apply(SentryEvent()); + final event = await enricher.apply(SentryEvent(), Hint()); debugBrightnessOverride = null; debugDefaultTargetPlatformOverride = null; @@ -81,7 +81,7 @@ void main() { binding: () => tester.binding, ); - final event = await enricher.apply(SentryEvent()); + final event = await enricher.apply(SentryEvent(), Hint()); final accessibility = event?.contexts['accessibility']; @@ -98,7 +98,7 @@ void main() { binding: () => tester.binding, ); - final event = await enricher.apply(SentryEvent()); + final event = await enricher.apply(SentryEvent(), Hint()); final culture = event?.contexts.culture; @@ -133,7 +133,7 @@ void main() { }, ); - final event = await enricher.apply(SentryEvent()); + final event = await enricher.apply(SentryEvent(), Hint()); expect(event?.contexts.culture?.locale, 'de-DE'); }); @@ -144,7 +144,7 @@ void main() { ); tester.binding.handleAppLifecycleStateChanged(AppLifecycleState.resumed); - final event = await enricher.apply(SentryEvent()); + final event = await enricher.apply(SentryEvent(), Hint()); final app = event?.contexts.app; @@ -157,7 +157,7 @@ void main() { ); tester.binding.handleAppLifecycleStateChanged(AppLifecycleState.inactive); - final event = await enricher.apply(SentryEvent()); + final event = await enricher.apply(SentryEvent(), Hint()); final app = event?.contexts.app; @@ -175,7 +175,7 @@ void main() { final event = SentryEvent(); event.contexts.app = SentryApp(name: appName); - final mutatedEvent = await enricher.apply(event); + final mutatedEvent = await enricher.apply(event, Hint()); final app = mutatedEvent?.contexts.app; @@ -190,7 +190,7 @@ void main() { hasNativeIntegration: true, ); - final event = await enricher.apply(SentryEvent()); + final event = await enricher.apply(SentryEvent(), Hint()); expect(event?.contexts.device, isNull); }); @@ -202,7 +202,7 @@ void main() { hasNativeIntegration: false, ); - final event = await enricher.apply(SentryEvent()); + final event = await enricher.apply(SentryEvent(), Hint()); expect(event?.contexts.device, isNotNull); }); @@ -212,7 +212,7 @@ void main() { binding: () => tester.binding, ); - final event = await enricher.apply(SentryEvent()); + final event = await enricher.apply(SentryEvent(), Hint()); final flutterRuntime = event?.contexts.runtimes .firstWhere((element) => element.name == 'Flutter'); @@ -236,7 +236,7 @@ void main() { checker: pair.key, ); - final event = await enricher.apply(SentryEvent()); + final event = await enricher.apply(SentryEvent(), Hint()); final flutterRuntime = event?.contexts.runtimes .firstWhere((element) => element.name == 'Flutter'); @@ -264,7 +264,7 @@ void main() { ), ); - final event = await enricher.apply(SentryEvent()); + final event = await enricher.apply(SentryEvent(), Hint()); expect(event?.modules, { 'foo_package': 'unknown', @@ -292,7 +292,7 @@ void main() { ), ); - final event = await enricher.apply(SentryEvent()); + final event = await enricher.apply(SentryEvent(), Hint()); expect(event?.modules, null); }); @@ -316,7 +316,7 @@ void main() { ), ); - final event = await enricher.apply(SentryEvent()); + final event = await enricher.apply(SentryEvent(), Hint()); expect(event?.modules, {'foo_package': 'unknown'}); }); @@ -341,7 +341,7 @@ void main() { hasNativeIntegration: false, ); - final event = await enricher.apply(fakeEvent); + final event = await enricher.apply(fakeEvent, Hint()); // contexts.device expect( @@ -401,7 +401,7 @@ void main() { final enricher = fixture.getSut( binding: () => tester.binding, ); - final event = await enricher.apply(eventWithContextsApp); + final event = await enricher.apply(eventWithContextsApp, Hint()); expect(event?.contexts.app?.viewNames, ['fixture-currentRouteName']); }); diff --git a/flutter/test/event_processor/flutter_exception_event_processor_test.dart b/flutter/test/event_processor/flutter_exception_event_processor_test.dart index aaca15e2af..8dc4f5c528 100644 --- a/flutter/test/event_processor/flutter_exception_event_processor_test.dart +++ b/flutter/test/event_processor/flutter_exception_event_processor_test.dart @@ -20,6 +20,7 @@ void main() { uri: Uri.parse('https://example.org/foo/bar?foo=bar'), ), ), + Hint(), ); expect(event?.request, isNotNull); diff --git a/flutter/test/event_processor/platform_exception_event_processor_test.dart b/flutter/test/event_processor/platform_exception_event_processor_test.dart index d4bf2d9c99..ecc3d7130b 100644 --- a/flutter/test/event_processor/platform_exception_event_processor_test.dart +++ b/flutter/test/event_processor/platform_exception_event_processor_test.dart @@ -26,7 +26,7 @@ void main() { var event = SentryEvent(exceptions: [sentryException]); final sut = fixture.getSut(); - event = (sut.apply(event))!; + event = (sut.apply(event, Hint()))!; expect(event.exceptions?.first.mechanism?.data["code"], "fixture-code"); expect(event.exceptions?.first.mechanism?.data["message"], @@ -46,7 +46,7 @@ void main() { var event = SentryEvent(exceptions: [sentryException]); final sut = fixture.getSut(); - event = (sut.apply(event))!; + event = (sut.apply(event, Hint()))!; expect(event.exceptions?.first.mechanism?.type, "platformException"); }); diff --git a/flutter/test/event_processor/screenshot_event_processor_test.dart b/flutter/test/event_processor/screenshot_event_processor_test.dart index 763c0e0ca3..2c1d0a4adc 100644 --- a/flutter/test/event_processor/screenshot_event_processor_test.dart +++ b/flutter/test/event_processor/screenshot_event_processor_test.dart @@ -40,7 +40,7 @@ void main() { final throwable = Exception(); event = SentryEvent(throwable: throwable); hint = Hint(); - await sut.apply(event, hint: hint); + await sut.apply(event, hint); expect(hint.screenshot != null, added); if (expectedMaxWidthOrHeight != null) { diff --git a/flutter/test/event_processor/widget_event_processor_test.dart b/flutter/test/event_processor/widget_event_processor_test.dart index 5e93e288ff..4744b58ad2 100644 --- a/flutter/test/event_processor/widget_event_processor_test.dart +++ b/flutter/test/event_processor/widget_event_processor_test.dart @@ -30,7 +30,7 @@ void main() { app: SentryApp(), ), ); - event = await sut.apply(event); + event = await sut.apply(event, Hint()); expect(event?.contexts.app?.textScale, 1.0); }); diff --git a/flutter/test/integrations/flutter_error_integration_test.dart b/flutter/test/integrations/flutter_error_integration_test.dart index 6c479fdf39..401b606bc4 100644 --- a/flutter/test/integrations/flutter_error_integration_test.dart +++ b/flutter/test/integrations/flutter_error_integration_test.dart @@ -70,7 +70,7 @@ void main() { final throwableMechanism = event.throwableMechanism as ThrowableMechanism; expect(throwableMechanism.mechanism.type, 'FlutterError'); - expect(throwableMechanism.mechanism.handled, true); + expect(throwableMechanism.mechanism.handled, false); expect(throwableMechanism.throwable, exception); expect(event.contexts['flutter_error_details']['library'], 'sentry'); @@ -102,7 +102,7 @@ void main() { final throwableMechanism = event.throwableMechanism as ThrowableMechanism; expect(throwableMechanism.mechanism.type, 'FlutterError'); - expect(throwableMechanism.mechanism.handled, true); + expect(throwableMechanism.mechanism.handled, false); expect(event.contexts['flutter_error_details']['library'], 'sentry'); expect(event.contexts['flutter_error_details']['context'], @@ -126,7 +126,7 @@ void main() { final throwableMechanism = event.throwableMechanism as ThrowableMechanism; expect(throwableMechanism.mechanism.type, 'FlutterError'); - expect(throwableMechanism.mechanism.handled, true); + expect(throwableMechanism.mechanism.handled, false); expect(throwableMechanism.mechanism.data['hint'], isNull); expect(event.contexts['flutter_error_details'], isNull); diff --git a/flutter/test/integrations/load_contexts_integration_test.dart b/flutter/test/integrations/load_contexts_integration_test.dart index 29aed18027..7b57eb572a 100644 --- a/flutter/test/integrations/load_contexts_integration_test.dart +++ b/flutter/test/integrations/load_contexts_integration_test.dart @@ -58,7 +58,8 @@ void main() { final integration = LoadContextsIntegration(fixture.methodChannel); integration.call(fixture.hub, fixture.options); - event = (await fixture.options.eventProcessors.first.apply(event))!; + event = + (await fixture.options.eventProcessors.first.apply(event, Hint()))!; expect(event.breadcrumbs!.length, 1); expect(event.breadcrumbs!.first.message, 'native'); @@ -83,7 +84,8 @@ void main() { final integration = LoadContextsIntegration(fixture.methodChannel); integration.call(fixture.hub, fixture.options); - event = (await fixture.options.eventProcessors.first.apply(event))!; + event = + (await fixture.options.eventProcessors.first.apply(event, Hint()))!; expect(event.breadcrumbs!.length, 1); expect(event.breadcrumbs!.first.message, 'event'); @@ -91,7 +93,7 @@ void main() { test('apply beforeBreadcrumb to native breadcrumbs', () async { fixture.options.enableScopeSync = true; - fixture.options.beforeBreadcrumb = (breadcrumb, {hint}) { + fixture.options.beforeBreadcrumb = (breadcrumb, hint) { if (breadcrumb?.message == 'native-mutated') { return breadcrumb?.copyWith(message: 'native-mutated-applied'); } else { @@ -119,7 +121,8 @@ void main() { final integration = LoadContextsIntegration(fixture.methodChannel); integration.call(fixture.hub, fixture.options); - event = (await fixture.options.eventProcessors.first.apply(event))!; + event = + (await fixture.options.eventProcessors.first.apply(event, Hint()))!; expect(event.breadcrumbs!.length, 1); expect(event.breadcrumbs!.first.message, 'native-mutated-applied'); diff --git a/flutter/test/integrations/load_contexts_integrations_test.dart b/flutter/test/integrations/load_contexts_integrations_test.dart index c6bb98f0b7..6de2d32e8d 100644 --- a/flutter/test/integrations/load_contexts_integrations_test.dart +++ b/flutter/test/integrations/load_contexts_integrations_test.dart @@ -81,7 +81,7 @@ void main() { e.contexts.operatingSystem = SentryOperatingSystem(theme: 'theme1'); e.contexts.app = SentryApp(inForeground: true); - final event = await fixture.options.eventProcessors.first.apply(e); + final event = await fixture.options.eventProcessors.first.apply(e, Hint()); expect(fixture.called, true); expect(event?.contexts.device?.name, 'Device1'); @@ -121,7 +121,7 @@ void main() { final e = SentryEvent(contexts: eventContexts, user: SentryUser(id: 'myId')); - final event = await fixture.options.eventProcessors.first.apply(e); + final event = await fixture.options.eventProcessors.first.apply(e, Hint()); expect(fixture.called, true); expect(event?.contexts.device?.name, 'eDevice'); @@ -145,7 +145,8 @@ void main() { integration(fixture.hub, fixture.options); final e = getEvent(); - final event = await fixture.options.eventProcessors.first.apply(e); + final event = + await fixture.options.eventProcessors.first.apply(e, Hint()); expect( event?.sdk?.packages.any((element) => element.name == 'native-package'), @@ -169,7 +170,8 @@ void main() { integration(fixture.hub, fixture.options); final e = getEvent(); - final event = await fixture.options.eventProcessors.first.apply(e); + final event = + await fixture.options.eventProcessors.first.apply(e, Hint()); expect( event?.sdk?.integrations @@ -189,7 +191,8 @@ void main() { integration(fixture.hub, fixture.options); final e = getEvent(); - final event = await fixture.options.eventProcessors.first.apply(e); + final event = + await fixture.options.eventProcessors.first.apply(e, Hint()); expect( event?.sdk?.packages @@ -210,7 +213,8 @@ void main() { integration(fixture.hub, fixture.options); final e = getEvent(); - final event = await fixture.options.eventProcessors.first.apply(e); + final event = + await fixture.options.eventProcessors.first.apply(e, Hint()); expect( event?.sdk?.packages @@ -239,7 +243,7 @@ void main() { integration(fixture.hub, fixture.options); final e = SentryEvent(); - final event = await fixture.options.eventProcessors.first.apply(e); + final event = await fixture.options.eventProcessors.first.apply(e, Hint()); expect(event, isNotNull); }); @@ -252,7 +256,8 @@ void main() { final eventSdk = getSdkVersion(name: 'sentry.dart.flutter'); final e = getEvent(sdk: eventSdk); - final event = await fixture.options.eventProcessors.first.apply(e); + final event = + await fixture.options.eventProcessors.first.apply(e, Hint()); expect(event?.tags?['event.origin'], 'flutter'); expect(event?.tags?['event.environment'], 'dart'); @@ -270,7 +275,8 @@ void main() { sdk: eventSdk, tags: {'a': 'b'}, ); - final event = await fixture.options.eventProcessors.first.apply(e); + final event = + await fixture.options.eventProcessors.first.apply(e, Hint()); expect(event?.tags?['event.origin'], 'flutter'); expect(event?.tags?['event.environment'], 'dart'); @@ -285,7 +291,8 @@ void main() { integration(fixture.hub, fixture.options); final e = getEvent(tags: {}); - final event = await fixture.options.eventProcessors.first.apply(e); + final event = + await fixture.options.eventProcessors.first.apply(e, Hint()); expect(event?.tags?.containsKey('event.origin'), false); expect(event?.tags?.containsKey('event.environment'), false); @@ -298,7 +305,7 @@ void main() { integration(fixture.hub, fixture.options); final e = getEvent(tags: {'key': 'flutter', 'key-a': 'flutter'}); - final event = await fixture.options.eventProcessors.first.apply(e); + final event = await fixture.options.eventProcessors.first.apply(e, Hint()); expect(event?.tags?['key'], 'flutter'); expect(event?.tags?['key-a'], 'flutter'); @@ -311,7 +318,7 @@ void main() { integration(fixture.hub, fixture.options); final e = getEvent(extra: {'key': 'flutter', 'key-a': 'flutter'}); - final event = await fixture.options.eventProcessors.first.apply(e); + final event = await fixture.options.eventProcessors.first.apply(e, Hint()); // ignore: deprecated_member_use expect(event?.extra?['key'], 'flutter'); @@ -326,7 +333,7 @@ void main() { integration(fixture.hub, fixture.options); final e = getEvent(); - final event = await fixture.options.eventProcessors.first.apply(e); + final event = await fixture.options.eventProcessors.first.apply(e, Hint()); expect(event?.user?.id, '196E065A-AAF7-409A-9A6C-A81F40274CB9'); expect(event?.user?.username, 'fixture-username'); @@ -340,7 +347,7 @@ void main() { integration(fixture.hub, fixture.options); final e = getEvent(user: SentryUser(id: 'abc')); - final event = await fixture.options.eventProcessors.first.apply(e); + final event = await fixture.options.eventProcessors.first.apply(e, Hint()); expect(event?.user?.id, 'abc'); }); @@ -350,7 +357,7 @@ void main() { integration(fixture.hub, fixture.options); final e = getEvent(); - final event = await fixture.options.eventProcessors.first.apply(e); + final event = await fixture.options.eventProcessors.first.apply(e, Hint()); expect(event?.dist, 'fixture-dist'); }); @@ -360,7 +367,7 @@ void main() { integration(fixture.hub, fixture.options); final e = getEvent(dist: 'abc'); - final event = await fixture.options.eventProcessors.first.apply(e); + final event = await fixture.options.eventProcessors.first.apply(e, Hint()); expect(event?.dist, 'abc'); }); @@ -370,7 +377,7 @@ void main() { integration(fixture.hub, fixture.options); final e = getEvent(); - final event = await fixture.options.eventProcessors.first.apply(e); + final event = await fixture.options.eventProcessors.first.apply(e, Hint()); expect(event?.environment, 'fixture-environment'); }); @@ -380,7 +387,7 @@ void main() { integration(fixture.hub, fixture.options); final e = getEvent(environment: 'abc'); - final event = await fixture.options.eventProcessors.first.apply(e); + final event = await fixture.options.eventProcessors.first.apply(e, Hint()); expect(event?.environment, 'abc'); }); @@ -391,7 +398,7 @@ void main() { integration(fixture.hub, fixture.options); final e = getEvent(fingerprint: ['fingerprint-a', 'fingerprint-b']); - final event = await fixture.options.eventProcessors.first.apply(e); + final event = await fixture.options.eventProcessors.first.apply(e, Hint()); expect(event?.fingerprint, ['fingerprint-a', 'fingerprint-b']); }); @@ -401,7 +408,7 @@ void main() { integration(fixture.hub, fixture.options); final e = getEvent(); - final event = await fixture.options.eventProcessors.first.apply(e); + final event = await fixture.options.eventProcessors.first.apply(e, Hint()); expect(event?.level, SentryLevel.error); }); @@ -411,7 +418,7 @@ void main() { integration(fixture.hub, fixture.options); final e = getEvent(level: SentryLevel.fatal); - final event = await fixture.options.eventProcessors.first.apply(e); + final event = await fixture.options.eventProcessors.first.apply(e, Hint()); expect(event?.level, SentryLevel.fatal); }); diff --git a/flutter/test/integrations/load_image_list_test.dart b/flutter/test/integrations/load_image_list_test.dart index 085bbcd3dc..b02acc94f3 100644 --- a/flutter/test/integrations/load_image_list_test.dart +++ b/flutter/test/integrations/load_image_list_test.dart @@ -135,7 +135,7 @@ void main() { final ep = fixture.options.eventProcessors.first; SentryEvent? event = _getEvent(); - event = await ep.apply(event); + event = await ep.apply(event, Hint()); expect(1, event!.debugMeta!.images.length); }); @@ -146,7 +146,7 @@ void main() { sut.call(fixture.hub, fixture.options); final ep = fixture.options.eventProcessors.first; SentryEvent? event = _getEvent(); - event = await ep.apply(event); + event = await ep.apply(event, Hint()); final image = event!.debugMeta!.images.first; diff --git a/flutter/test/integrations/native_app_start_integration_test.dart b/flutter/test/integrations/native_app_start_integration_test.dart index 135d90f34b..70b088cfec 100644 --- a/flutter/test/integrations/native_app_start_integration_test.dart +++ b/flutter/test/integrations/native_app_start_integration_test.dart @@ -31,7 +31,8 @@ void main() { final transaction = SentryTransaction(tracer); final processor = fixture.options.eventProcessors.first; - final enriched = await processor.apply(transaction) as SentryTransaction; + final enriched = + await processor.apply(transaction, Hint()) as SentryTransaction; final measurement = enriched.measurements['app_start_cold']!; expect(measurement.value, 10); @@ -50,8 +51,10 @@ void main() { final processor = fixture.options.eventProcessors.first; - var enriched = await processor.apply(transaction) as SentryTransaction; - var secondEnriched = await processor.apply(enriched) as SentryTransaction; + var enriched = + await processor.apply(transaction, Hint()) as SentryTransaction; + var secondEnriched = + await processor.apply(enriched, Hint()) as SentryTransaction; expect(secondEnriched.measurements.length, 1); }); @@ -69,8 +72,10 @@ void main() { final processor = fixture.options.eventProcessors.first; - var enriched = await processor.apply(transaction) as SentryTransaction; - var secondEnriched = await processor.apply(enriched) as SentryTransaction; + var enriched = + await processor.apply(transaction, Hint()) as SentryTransaction; + var secondEnriched = + await processor.apply(enriched, Hint()) as SentryTransaction; expect(secondEnriched.measurements.length, 2); expect(secondEnriched.measurements.containsKey(measurement.name), true); @@ -86,7 +91,8 @@ void main() { final transaction = SentryTransaction(tracer); final processor = fixture.options.eventProcessors.first; - final enriched = await processor.apply(transaction) as SentryTransaction; + final enriched = + await processor.apply(transaction, Hint()) as SentryTransaction; expect(enriched.measurements.isEmpty, true); }); diff --git a/flutter/test/load_image_list_test.dart b/flutter/test/load_image_list_test.dart index 0afff01b97..345d913887 100644 --- a/flutter/test/load_image_list_test.dart +++ b/flutter/test/load_image_list_test.dart @@ -127,7 +127,7 @@ void main() { final ep = fixture.options.eventProcessors.first; SentryEvent? event = _getEvent(); - event = await ep.apply(event); + event = await ep.apply(event, Hint()); expect(1, event!.debugMeta!.images.length); }); @@ -138,7 +138,7 @@ void main() { sut.call(fixture.hub, fixture.options); final ep = fixture.options.eventProcessors.first; SentryEvent? event = _getEvent(); - event = await ep.apply(event); + event = await ep.apply(event, Hint()); final image = event!.debugMeta!.images.first; diff --git a/flutter/test/sentry_flutter_test.dart b/flutter/test/sentry_flutter_test.dart index f01c9a8d3f..e06938da90 100644 --- a/flutter/test/sentry_flutter_test.dart +++ b/flutter/test/sentry_flutter_test.dart @@ -32,9 +32,10 @@ final nonWebIntegrations = [ OnErrorIntegration, ]; -// These should only be added to Android +// These should be added to Android final androidIntegrations = [ LoadImageListIntegration, + LoadContextsIntegration, ]; // These should be added to iOS and macOS diff --git a/flutter/test/view_hierarchy/view_hierarchy_event_processor_test.dart b/flutter/test/view_hierarchy/view_hierarchy_event_processor_test.dart index 6900ba5589..7743e8ebc6 100644 --- a/flutter/test/view_hierarchy/view_hierarchy_event_processor_test.dart +++ b/flutter/test/view_hierarchy/view_hierarchy_event_processor_test.dart @@ -26,7 +26,7 @@ void main() { exceptions: [SentryException(type: 'type', value: 'value')]); final hint = Hint(); - sut.apply(event, hint: hint); + sut.apply(event, hint); expect(hint.viewHierarchy, isNotNull); }); @@ -42,7 +42,7 @@ void main() { final event = SentryEvent(throwable: StateError('error')); final hint = Hint(); - sut.apply(event, hint: hint); + sut.apply(event, hint); expect(hint.viewHierarchy, isNotNull); }); @@ -58,7 +58,7 @@ void main() { final event = SentryEvent(); final hint = Hint(); - sut.apply(event, hint: hint); + sut.apply(event, hint); expect(hint.viewHierarchy, isNull); }); @@ -74,7 +74,7 @@ void main() { final event = SentryEvent(); final hint = Hint(); - sut.apply(event, hint: hint); + sut.apply(event, hint); expect(hint.viewHierarchy, isNull); }); diff --git a/hive/README.md b/hive/README.md index a5347c31a4..b67e9e4f7b 100644 --- a/hive/README.md +++ b/hive/README.md @@ -78,8 +78,9 @@ class Person { #### Resources -* [![Documentation](https://img.shields.io/badge/documentation-sentry.io-green.svg)](https://docs.sentry.io/platforms/dart/) -* [![Forum](https://img.shields.io/badge/forum-sentry-green.svg)](https://forum.sentry.io/c/sdks) -* [![Discord](https://img.shields.io/discord/621778831602221064)](https://discord.gg/Ww9hbqr) +* [![Flutter docs](https://img.shields.io/badge/documentation-sentry.io-green.svg?label=flutter%20docs)](https://docs.sentry.io/platforms/flutter/) +* [![Dart docs](https://img.shields.io/badge/documentation-sentry.io-green.svg?label=dart%20docs)](https://docs.sentry.io/platforms/dart/) +* [![Discussions](https://img.shields.io/github/discussions/getsentry/sentry-dart.svg)](https://github.com/getsentry/sentry-dart/discussions) +* [![Discord Chat](https://img.shields.io/discord/621778831602221064?logo=discord&logoColor=ffffff&color=7389D8)](https://discord.gg/PXa5Apfe7K) * [![Stack Overflow](https://img.shields.io/badge/stack%20overflow-sentry-green.svg)](https://stackoverflow.com/questions/tagged/sentry) * [![Twitter Follow](https://img.shields.io/twitter/follow/getsentry?label=getsentry&style=social)](https://twitter.com/intent/follow?screen_name=getsentry) diff --git a/hive/lib/src/version.dart b/hive/lib/src/version.dart index d0079c0f70..524aa89e7f 100644 --- a/hive/lib/src/version.dart +++ b/hive/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.20.0'; +const String sdkVersion = '8.0.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_hive'; diff --git a/hive/pubspec.yaml b/hive/pubspec.yaml index 161e7796d9..6aeaed7f68 100644 --- a/hive/pubspec.yaml +++ b/hive/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_hive description: An integration which adds support for performance tracing for the hive package. -version: 7.20.0 +version: 8.0.0 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -17,7 +17,7 @@ platforms: web: dependencies: - sentry: 7.20.0 + sentry: 8.0.0 hive: ^2.2.3 meta: ^1.3.0 diff --git a/isar/README.md b/isar/README.md index 5405c8e43e..011e8e834f 100644 --- a/isar/README.md +++ b/isar/README.md @@ -76,8 +76,9 @@ Future runApp() async { #### Resources -* [![Documentation](https://img.shields.io/badge/documentation-sentry.io-green.svg)](https://docs.sentry.io/platforms/dart/) -* [![Forum](https://img.shields.io/badge/forum-sentry-green.svg)](https://forum.sentry.io/c/sdks) -* [![Discord](https://img.shields.io/discord/621778831602221064)](https://discord.gg/Ww9hbqr) +* [![Flutter docs](https://img.shields.io/badge/documentation-sentry.io-green.svg?label=flutter%20docs)](https://docs.sentry.io/platforms/flutter/) +* [![Dart docs](https://img.shields.io/badge/documentation-sentry.io-green.svg?label=dart%20docs)](https://docs.sentry.io/platforms/dart/) +* [![Discussions](https://img.shields.io/github/discussions/getsentry/sentry-dart.svg)](https://github.com/getsentry/sentry-dart/discussions) +* [![Discord Chat](https://img.shields.io/discord/621778831602221064?logo=discord&logoColor=ffffff&color=7389D8)](https://discord.gg/PXa5Apfe7K) * [![Stack Overflow](https://img.shields.io/badge/stack%20overflow-sentry-green.svg)](https://stackoverflow.com/questions/tagged/sentry) * [![Twitter Follow](https://img.shields.io/twitter/follow/getsentry?label=getsentry&style=social)](https://twitter.com/intent/follow?screen_name=getsentry) diff --git a/isar/lib/src/version.dart b/isar/lib/src/version.dart index a61930b879..7410567886 100644 --- a/isar/lib/src/version.dart +++ b/isar/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.20.0'; +const String sdkVersion = '8.0.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_isar'; diff --git a/isar/pubspec.yaml b/isar/pubspec.yaml index 53aa85a5f8..fb83755493 100644 --- a/isar/pubspec.yaml +++ b/isar/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_isar description: An integration which adds support for performance tracing for the isar package. -version: 7.20.0 +version: 8.0.0 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -20,7 +20,7 @@ platforms: dependencies: isar: ^3.1.0 isar_flutter_libs: ^3.1.0 # contains Isar Core - sentry: 7.20.0 + sentry: 8.0.0 meta: ^1.3.0 path: ^1.8.3 diff --git a/logging/README.md b/logging/README.md index 0b4b4fcfef..488ebb8adf 100644 --- a/logging/README.md +++ b/logging/README.md @@ -43,8 +43,9 @@ void initApp() { #### Resources -* [![Documentation](https://img.shields.io/badge/documentation-sentry.io-green.svg)](https://docs.sentry.io/platforms/dart/) -* [![Forum](https://img.shields.io/badge/forum-sentry-green.svg)](https://forum.sentry.io/c/sdks) -* [![Discord](https://img.shields.io/discord/621778831602221064)](https://discord.gg/Ww9hbqr) +* [![Flutter docs](https://img.shields.io/badge/documentation-sentry.io-green.svg?label=flutter%20docs)](https://docs.sentry.io/platforms/flutter/) +* [![Dart docs](https://img.shields.io/badge/documentation-sentry.io-green.svg?label=dart%20docs)](https://docs.sentry.io/platforms/dart/) +* [![Discussions](https://img.shields.io/github/discussions/getsentry/sentry-dart.svg)](https://github.com/getsentry/sentry-dart/discussions) +* [![Discord Chat](https://img.shields.io/discord/621778831602221064?logo=discord&logoColor=ffffff&color=7389D8)](https://discord.gg/PXa5Apfe7K) * [![Stack Overflow](https://img.shields.io/badge/stack%20overflow-sentry-green.svg)](https://stackoverflow.com/questions/tagged/sentry) -* [![Twitter Follow](https://img.shields.io/twitter/follow/getsentry?label=getsentry&style=social)](https://twitter.com/intent/follow?screen_name=getsentry) +* [![Twitter Follow](https://img.shields.io/twitter/follow/getsentry?label=getsentry&style=social)](https://twitter.com/intent/follow?screen_name=getsentry) \ No newline at end of file diff --git a/logging/lib/src/version.dart b/logging/lib/src/version.dart index fbbea58108..21a66180d1 100644 --- a/logging/lib/src/version.dart +++ b/logging/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.20.0'; +const String sdkVersion = '8.0.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_logging'; diff --git a/logging/pubspec.yaml b/logging/pubspec.yaml index 04d4232f8f..b9855f47de 100644 --- a/logging/pubspec.yaml +++ b/logging/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_logging description: An integration which adds support for recording log from the logging package. -version: 7.20.0 +version: 8.0.0 homepage: https://docs.sentry.io/platforms/dart/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -19,7 +19,7 @@ platforms: dependencies: logging: ^1.0.0 - sentry: 7.20.0 + sentry: 8.0.0 dev_dependencies: lints: ^3.0.0 diff --git a/min_version_test/ios/Podfile b/min_version_test/ios/Podfile index 88359b225f..2c068c404b 100644 --- a/min_version_test/ios/Podfile +++ b/min_version_test/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -# platform :ios, '11.0' +platform :ios, '12.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' diff --git a/sqflite/README.md b/sqflite/README.md index ed2b3c4f9d..ff5774ba74 100644 --- a/sqflite/README.md +++ b/sqflite/README.md @@ -62,8 +62,9 @@ Future insertProducts() async { #### Resources -* [![Documentation](https://img.shields.io/badge/documentation-sentry.io-green.svg)](https://docs.sentry.io/platforms/dart/) -* [![Forum](https://img.shields.io/badge/forum-sentry-green.svg)](https://forum.sentry.io/c/sdks) -* [![Discord](https://img.shields.io/discord/621778831602221064)](https://discord.gg/Ww9hbqr) +* [![Flutter docs](https://img.shields.io/badge/documentation-sentry.io-green.svg?label=flutter%20docs)](https://docs.sentry.io/platforms/flutter/) +* [![Dart docs](https://img.shields.io/badge/documentation-sentry.io-green.svg?label=dart%20docs)](https://docs.sentry.io/platforms/dart/) +* [![Discussions](https://img.shields.io/github/discussions/getsentry/sentry-dart.svg)](https://github.com/getsentry/sentry-dart/discussions) +* [![Discord Chat](https://img.shields.io/discord/621778831602221064?logo=discord&logoColor=ffffff&color=7389D8)](https://discord.gg/PXa5Apfe7K) * [![Stack Overflow](https://img.shields.io/badge/stack%20overflow-sentry-green.svg)](https://stackoverflow.com/questions/tagged/sentry) -* [![Twitter Follow](https://img.shields.io/twitter/follow/getsentry?label=getsentry&style=social)](https://twitter.com/intent/follow?screen_name=getsentry) +* [![Twitter Follow](https://img.shields.io/twitter/follow/getsentry?label=getsentry&style=social)](https://twitter.com/intent/follow?screen_name=getsentry) \ No newline at end of file diff --git a/sqflite/lib/src/version.dart b/sqflite/lib/src/version.dart index 5b98e5939e..d0fae42df4 100644 --- a/sqflite/lib/src/version.dart +++ b/sqflite/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '7.20.0'; +const String sdkVersion = '8.0.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_sqflite'; diff --git a/sqflite/pubspec.yaml b/sqflite/pubspec.yaml index e8d317c214..32d060abef 100644 --- a/sqflite/pubspec.yaml +++ b/sqflite/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_sqflite description: An integration which adds support for performance tracing for the sqflite package. -version: 7.20.0 +version: 8.0.0 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -15,7 +15,7 @@ platforms: macos: dependencies: - sentry: 7.20.0 + sentry: 8.0.0 sqflite: ^2.0.0 sqflite_common: ^2.0.0 meta: ^1.3.0 From 42211351963a46890833cddc00ca89bd88ac760d Mon Sep 17 00:00:00 2001 From: getsentry-bot Date: Fri, 19 Apr 2024 10:46:33 +0000 Subject: [PATCH 143/237] release: 8.0.0 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8acd561d6d..fa0a13035f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## Unreleased +## 8.0.0 This release contains breaking changes, please read the changelog carefully. From a9352cf0b23709facaa8f3eb597ef182d60faf82 Mon Sep 17 00:00:00 2001 From: Stefano Date: Mon, 22 Apr 2024 13:56:06 +0200 Subject: [PATCH 144/237] Timing metric aggregates metrics in the created span (#1994) * timing metric now aggregates metrics in the span --- CHANGELOG.md | 6 ++++++ dart/lib/src/metrics/metrics_aggregator.dart | 14 ++++++++------ dart/lib/src/metrics/metrics_api.dart | 10 ++++++++-- dart/test/metrics/metrics_api_test.dart | 2 ++ 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fa0a13035f..f10f44c738 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## Unreleased + +### Fixes + +- Timing metric aggregates metrics in the created span ([#1994](https://github.com/getsentry/sentry-dart/pull/1994)) + ## 8.0.0 This release contains breaking changes, please read the changelog carefully. diff --git a/dart/lib/src/metrics/metrics_aggregator.dart b/dart/lib/src/metrics/metrics_aggregator.dart index 2dd9cb2c91..ef763eae35 100644 --- a/dart/lib/src/metrics/metrics_aggregator.dart +++ b/dart/lib/src/metrics/metrics_aggregator.dart @@ -5,6 +5,7 @@ import 'dart:math'; import 'package:meta/meta.dart'; import '../../sentry.dart'; +import 'local_metrics_aggregator.dart'; import 'metric.dart'; /// Class that aggregates all metrics into time buckets and sends them. @@ -53,8 +54,9 @@ class MetricsAggregator { String key, num value, SentryMeasurementUnit unit, - Map tags, - ) { + Map tags, { + LocalMetricsAggregator? localMetricsAggregator, + }) { if (_isClosed) { return; } @@ -102,10 +104,10 @@ class MetricsAggregator { // For sets, we only record that a value has been added to the set but not which one. // See develop docs: https://develop.sentry.dev/sdk/metrics/#sets - _hub - .getSpan() - ?.localMetricsAggregator - ?.add(metric, metricType == MetricType.set ? addedWeight : value); + final localAggregator = + localMetricsAggregator ?? (_hub.getSpan()?.localMetricsAggregator); + localAggregator?.add( + metric, metricType == MetricType.set ? addedWeight : value); // Schedule the metrics flushing. _scheduleFlush(); diff --git a/dart/lib/src/metrics/metrics_api.dart b/dart/lib/src/metrics/metrics_api.dart index 1ef8df77c3..9f9e8305f2 100644 --- a/dart/lib/src/metrics/metrics_api.dart +++ b/dart/lib/src/metrics/metrics_api.dart @@ -151,8 +151,14 @@ class MetricsApi { } final value = _convertMicrosTo(unit, duration.inMicroseconds); - _hub.metricsAggregator?.emit(MetricType.distribution, key, value, unit, - _enrichWithDefaultTags(tags)); + _hub.metricsAggregator?.emit( + MetricType.distribution, + key, + value, + unit, + _enrichWithDefaultTags(tags), + localMetricsAggregator: span?.localMetricsAggregator, + ); } } diff --git a/dart/test/metrics/metrics_api_test.dart b/dart/test/metrics/metrics_api_test.dart index 9345720102..8c53e66772 100644 --- a/dart/test/metrics/metrics_api_test.dart +++ b/dart/test/metrics/metrics_api_test.dart @@ -132,6 +132,8 @@ void main() { Iterable sentMetrics = fixture.hub.metricsAggregator!.buckets.values.first.values; + // The emitted metric value should be aggregated in the span + expect(span.localMetricsAggregator?.getSummaries(), isNotEmpty); // The emitted metric value should match the span duration expect(sentMetrics.first.unit, DurationSentryMeasurementUnit.milliSecond); // Duration.inMilliseconds returns an int, so we have to assert it From 4a8fdb4ee93d5eb04902636af00bda23368cfc76 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 17:53:50 +0200 Subject: [PATCH 145/237] chore: update metrics/flutter.properties to 3.19.6 (#1995) Co-authored-by: GitHub --- metrics/flutter.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/metrics/flutter.properties b/metrics/flutter.properties index c570b4b0f2..4bb0b5513e 100644 --- a/metrics/flutter.properties +++ b/metrics/flutter.properties @@ -1,2 +1,2 @@ -version = 3.19.5 +version = 3.19.6 repo = https://github.com/flutter/flutter From 6d27c512dfbb3b1f5c13daae73c9ac6bd35b2df0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 Apr 2024 11:43:07 +0200 Subject: [PATCH 146/237] build(deps): bump actions/checkout from 3 to 4 (#2006) Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/flutter_integration_test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/flutter_integration_test.yml b/.github/workflows/flutter_integration_test.yml index 86bcb2e2dd..308c65b758 100644 --- a/.github/workflows/flutter_integration_test.yml +++ b/.github/workflows/flutter_integration_test.yml @@ -31,7 +31,7 @@ jobs: sdk: [ "stable", "beta" ] steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - uses: actions/setup-java@v3 with: @@ -98,7 +98,7 @@ jobs: sdk: [ "stable" ] steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - uses: subosito/flutter-action@48cafc24713cca54bbe03cdc3a423187d413aafa # pin@v2.10.0 with: From e33e5fac2aa609020f40b38c56c587824ac6424a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 Apr 2024 13:22:20 +0200 Subject: [PATCH 147/237] build(deps): bump actions/setup-java from 3 to 4 (#2005) Bumps [actions/setup-java](https://github.com/actions/setup-java) from 3 to 4. - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/setup-java dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/flutter_integration_test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/flutter_integration_test.yml b/.github/workflows/flutter_integration_test.yml index 308c65b758..845a7f354e 100644 --- a/.github/workflows/flutter_integration_test.yml +++ b/.github/workflows/flutter_integration_test.yml @@ -33,7 +33,7 @@ jobs: - name: checkout uses: actions/checkout@v4 - - uses: actions/setup-java@v3 + - uses: actions/setup-java@v4 with: distribution: "adopt" java-version: "11" From 5b4cd6ff2898361f7051acc5d4d57c2999fdb604 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 Apr 2024 13:22:45 +0200 Subject: [PATCH 148/237] build(deps): bump actions/cache from 3 to 4 (#2004) Bumps [actions/cache](https://github.com/actions/cache) from 3 to 4. - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/cache dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor --- .github/workflows/flutter_integration_test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/flutter_integration_test.yml b/.github/workflows/flutter_integration_test.yml index 845a7f354e..0b12b5ad74 100644 --- a/.github/workflows/flutter_integration_test.yml +++ b/.github/workflows/flutter_integration_test.yml @@ -52,7 +52,7 @@ jobs: uses: gradle/gradle-build-action@982da8e78c05368c70dac0351bb82647a9e9a5d2 # pin@v2.11.1 - name: AVD cache - uses: actions/cache@v3 + uses: actions/cache@v4 id: avd-cache with: path: | From 50bdfad10c3833c388a7a32c883117f3e9b2cbce Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 23 Apr 2024 13:45:19 +0200 Subject: [PATCH 149/237] chore(deps): update Cocoa SDK to v8.24.0 (#1986) * chore: update flutter/scripts/update-cocoa.sh to 8.24.0 * rollback binding.dart * fix generated bindings for swift in cocoa 8.22.0 --------- Co-authored-by: GitHub Co-authored-by: Ivan Dlugos --- CHANGELOG.md | 6 + flutter/ffi-cocoa.yaml | 4 +- flutter/ios/sentry_flutter.podspec | 2 +- flutter/lib/src/native/cocoa/binding.dart | 8170 ++++++++--------- .../src/native/cocoa/sentry_native_cocoa.dart | 2 +- flutter/scripts/generate-cocoa-bindings.sh | 3 +- 6 files changed, 3976 insertions(+), 4211 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f10f44c738..7cf3f707c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,12 @@ - Timing metric aggregates metrics in the created span ([#1994](https://github.com/getsentry/sentry-dart/pull/1994)) +### Dependencies + +- Bump Cocoa SDK from v8.21.0 to v8.24.0 ([#1986](https://github.com/getsentry/sentry-dart/pull/1986)) + - [changelog](https://github.com/getsentry/sentry-cocoa/blob/main/CHANGELOG.md#8240) + - [diff](https://github.com/getsentry/sentry-cocoa/compare/8.21.0...8.24.0) + ## 8.0.0 This release contains breaking changes, please read the changelog carefully. diff --git a/flutter/ffi-cocoa.yaml b/flutter/ffi-cocoa.yaml index d680be1189..c27c5a882a 100644 --- a/flutter/ffi-cocoa.yaml +++ b/flutter/ffi-cocoa.yaml @@ -5,7 +5,7 @@ output: lib/src/native/cocoa/binding.dart headers: entry-points: - ./cocoa_bindings_temp/Sentry.framework/Versions/A/PrivateHeaders/PrivateSentrySDKOnly.h - - ./cocoa_bindings_temp/Sentry.framework/Versions/A/Headers/SentryId.h + - ./cocoa_bindings_temp/Sentry.framework/Versions/A/Headers/Sentry-Swift.h compiler-opts: - -DSENTRY_TARGET_PROFILING_SUPPORTED=1 - -DCOCOAPODS=1 @@ -16,3 +16,5 @@ objc-interfaces: include: - PrivateSentrySDKOnly - SentryId + module: + 'SentryId': 'Sentry' diff --git a/flutter/ios/sentry_flutter.podspec b/flutter/ios/sentry_flutter.podspec index 184a5ae7d2..f67b35e2e4 100644 --- a/flutter/ios/sentry_flutter.podspec +++ b/flutter/ios/sentry_flutter.podspec @@ -16,7 +16,7 @@ Sentry SDK for Flutter with support to native through sentry-cocoa. :tag => s.version.to_s } s.source_files = 'Classes/**/*' s.public_header_files = 'Classes/**/*.h' - s.dependency 'Sentry/HybridSDK', '8.21.0' + s.dependency 'Sentry/HybridSDK', '8.24.0' s.ios.dependency 'Flutter' s.osx.dependency 'FlutterMacOS' s.ios.deployment_target = '12.0' diff --git a/flutter/lib/src/native/cocoa/binding.dart b/flutter/lib/src/native/cocoa/binding.dart index 41350a3a2c..f8c31e95a7 100644 --- a/flutter/lib/src/native/cocoa/binding.dart +++ b/flutter/lib/src/native/cocoa/binding.dart @@ -1012,6 +1012,10 @@ class SentryCocoa { late final _sel_URLWithString_1 = _registerName1("URLWithString:"); late final _sel_URLWithString_relativeToURL_1 = _registerName1("URLWithString:relativeToURL:"); + late final _sel_initWithString_encodingInvalidCharacters_1 = + _registerName1("initWithString:encodingInvalidCharacters:"); + late final _sel_URLWithString_encodingInvalidCharacters_1 = + _registerName1("URLWithString:encodingInvalidCharacters:"); late final _sel_initWithDataRepresentation_relativeToURL_1 = _registerName1("initWithDataRepresentation:relativeToURL:"); instancetype _objc_msgSend_37( @@ -3621,7 +3625,7 @@ class SentryCocoa { ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer predicateFormat, - ffi.Pointer<__va_list_tag> argList, + ffi.Pointer argList, ) { return __objc_msgSend_135( obj, @@ -3637,13 +3641,13 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Pointer, - ffi.Pointer<__va_list_tag>)>>('objc_msgSend'); + ffi.Pointer)>>('objc_msgSend'); late final __objc_msgSend_135 = __objc_msgSend_135Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, - ffi.Pointer<__va_list_tag>)>(); + ffi.Pointer)>(); late final _sel_predicateFromMetadataQueryString_1 = _registerName1("predicateFromMetadataQueryString:"); @@ -4666,9 +4670,11 @@ class SentryCocoa { late final _sel_languageCode1 = _registerName1("languageCode"); late final _sel_localizedStringForLanguageCode_1 = _registerName1("localizedStringForLanguageCode:"); + late final _sel_languageIdentifier1 = _registerName1("languageIdentifier"); late final _sel_countryCode1 = _registerName1("countryCode"); late final _sel_localizedStringForCountryCode_1 = _registerName1("localizedStringForCountryCode:"); + late final _sel_regionCode1 = _registerName1("regionCode"); late final _sel_scriptCode1 = _registerName1("scriptCode"); late final _sel_localizedStringForScriptCode_1 = _registerName1("localizedStringForScriptCode:"); @@ -6032,41 +6038,19 @@ class SentryCocoa { _registerName1("fileSystemRepresentation"); late final _sel_isFileURL1 = _registerName1("isFileURL"); late final _sel_standardizedURL1 = _registerName1("standardizedURL"); - late final _sel_checkResourceIsReachableAndReturnError_1 = - _registerName1("checkResourceIsReachableAndReturnError:"); - bool _objc_msgSend_225( - ffi.Pointer obj, - ffi.Pointer sel, - ffi.Pointer> error, - ) { - return __objc_msgSend_225( - obj, - sel, - error, - ); - } - - late final __objc_msgSend_225Ptr = _lookup< - ffi.NativeFunction< - ffi.Bool Function(ffi.Pointer, ffi.Pointer, - ffi.Pointer>)>>('objc_msgSend'); - late final __objc_msgSend_225 = __objc_msgSend_225Ptr.asFunction< - bool Function(ffi.Pointer, ffi.Pointer, - ffi.Pointer>)>(); - late final _sel_isFileReferenceURL1 = _registerName1("isFileReferenceURL"); late final _sel_fileReferenceURL1 = _registerName1("fileReferenceURL"); late final _sel_filePathURL1 = _registerName1("filePathURL"); late final _sel_getResourceValue_forKey_error_1 = _registerName1("getResourceValue:forKey:error:"); - bool _objc_msgSend_226( + bool _objc_msgSend_225( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer> value, ffi.Pointer key, ffi.Pointer> error, ) { - return __objc_msgSend_226( + return __objc_msgSend_225( obj, sel, value, @@ -6075,7 +6059,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_226Ptr = _lookup< + late final __objc_msgSend_225Ptr = _lookup< ffi.NativeFunction< ffi.Bool Function( ffi.Pointer, @@ -6083,7 +6067,7 @@ class SentryCocoa { ffi.Pointer>, ffi.Pointer, ffi.Pointer>)>>('objc_msgSend'); - late final __objc_msgSend_226 = __objc_msgSend_226Ptr.asFunction< + late final __objc_msgSend_225 = __objc_msgSend_225Ptr.asFunction< bool Function( ffi.Pointer, ffi.Pointer, @@ -6093,13 +6077,13 @@ class SentryCocoa { late final _sel_resourceValuesForKeys_error_1 = _registerName1("resourceValuesForKeys:error:"); - ffi.Pointer _objc_msgSend_227( + ffi.Pointer _objc_msgSend_226( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer keys, ffi.Pointer> error, ) { - return __objc_msgSend_227( + return __objc_msgSend_226( obj, sel, keys, @@ -6107,14 +6091,14 @@ class SentryCocoa { ); } - late final __objc_msgSend_227Ptr = _lookup< + late final __objc_msgSend_226Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer>)>>('objc_msgSend'); - late final __objc_msgSend_227 = __objc_msgSend_227Ptr.asFunction< + late final __objc_msgSend_226 = __objc_msgSend_226Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, @@ -6123,14 +6107,14 @@ class SentryCocoa { late final _sel_setResourceValue_forKey_error_1 = _registerName1("setResourceValue:forKey:error:"); - bool _objc_msgSend_228( + bool _objc_msgSend_227( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer value, ffi.Pointer key, ffi.Pointer> error, ) { - return __objc_msgSend_228( + return __objc_msgSend_227( obj, sel, value, @@ -6139,7 +6123,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_228Ptr = _lookup< + late final __objc_msgSend_227Ptr = _lookup< ffi.NativeFunction< ffi.Bool Function( ffi.Pointer, @@ -6147,7 +6131,7 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Pointer>)>>('objc_msgSend'); - late final __objc_msgSend_228 = __objc_msgSend_228Ptr.asFunction< + late final __objc_msgSend_227 = __objc_msgSend_227Ptr.asFunction< bool Function( ffi.Pointer, ffi.Pointer, @@ -6157,13 +6141,13 @@ class SentryCocoa { late final _sel_setResourceValues_error_1 = _registerName1("setResourceValues:error:"); - bool _objc_msgSend_229( + bool _objc_msgSend_228( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer keyedValues, ffi.Pointer> error, ) { - return __objc_msgSend_229( + return __objc_msgSend_228( obj, sel, keyedValues, @@ -6171,14 +6155,14 @@ class SentryCocoa { ); } - late final __objc_msgSend_229Ptr = _lookup< + late final __objc_msgSend_228Ptr = _lookup< ffi.NativeFunction< ffi.Bool Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer>)>>('objc_msgSend'); - late final __objc_msgSend_229 = __objc_msgSend_229Ptr.asFunction< + late final __objc_msgSend_228 = __objc_msgSend_228Ptr.asFunction< bool Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer>)>(); @@ -6191,7 +6175,7 @@ class SentryCocoa { late final _sel_bookmarkDataWithOptions_includingResourceValuesForKeys_relativeToURL_error_1 = _registerName1( "bookmarkDataWithOptions:includingResourceValuesForKeys:relativeToURL:error:"); - ffi.Pointer _objc_msgSend_230( + ffi.Pointer _objc_msgSend_229( ffi.Pointer obj, ffi.Pointer sel, int options, @@ -6199,7 +6183,7 @@ class SentryCocoa { ffi.Pointer relativeURL, ffi.Pointer> error, ) { - return __objc_msgSend_230( + return __objc_msgSend_229( obj, sel, options, @@ -6209,7 +6193,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_230Ptr = _lookup< + late final __objc_msgSend_229Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, @@ -6218,7 +6202,7 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Pointer>)>>('objc_msgSend'); - late final __objc_msgSend_230 = __objc_msgSend_230Ptr.asFunction< + late final __objc_msgSend_229 = __objc_msgSend_229Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, @@ -6230,7 +6214,7 @@ class SentryCocoa { late final _sel_initByResolvingBookmarkData_options_relativeToURL_bookmarkDataIsStale_error_1 = _registerName1( "initByResolvingBookmarkData:options:relativeToURL:bookmarkDataIsStale:error:"); - instancetype _objc_msgSend_231( + instancetype _objc_msgSend_230( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer bookmarkData, @@ -6239,7 +6223,7 @@ class SentryCocoa { ffi.Pointer isStale, ffi.Pointer> error, ) { - return __objc_msgSend_231( + return __objc_msgSend_230( obj, sel, bookmarkData, @@ -6250,7 +6234,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_231Ptr = _lookup< + late final __objc_msgSend_230Ptr = _lookup< ffi.NativeFunction< instancetype Function( ffi.Pointer, @@ -6260,7 +6244,7 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Pointer>)>>('objc_msgSend'); - late final __objc_msgSend_231 = __objc_msgSend_231Ptr.asFunction< + late final __objc_msgSend_230 = __objc_msgSend_230Ptr.asFunction< instancetype Function( ffi.Pointer, ffi.Pointer, @@ -6275,13 +6259,13 @@ class SentryCocoa { "URLByResolvingBookmarkData:options:relativeToURL:bookmarkDataIsStale:error:"); late final _sel_resourceValuesForKeys_fromBookmarkData_1 = _registerName1("resourceValuesForKeys:fromBookmarkData:"); - ffi.Pointer _objc_msgSend_232( + ffi.Pointer _objc_msgSend_231( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer keys, ffi.Pointer bookmarkData, ) { - return __objc_msgSend_232( + return __objc_msgSend_231( obj, sel, keys, @@ -6289,14 +6273,14 @@ class SentryCocoa { ); } - late final __objc_msgSend_232Ptr = _lookup< + late final __objc_msgSend_231Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_232 = __objc_msgSend_232Ptr.asFunction< + late final __objc_msgSend_231 = __objc_msgSend_231Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, @@ -6305,7 +6289,7 @@ class SentryCocoa { late final _sel_writeBookmarkData_toURL_options_error_1 = _registerName1("writeBookmarkData:toURL:options:error:"); - bool _objc_msgSend_233( + bool _objc_msgSend_232( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer bookmarkData, @@ -6313,7 +6297,7 @@ class SentryCocoa { int options, ffi.Pointer> error, ) { - return __objc_msgSend_233( + return __objc_msgSend_232( obj, sel, bookmarkData, @@ -6323,7 +6307,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_233Ptr = _lookup< + late final __objc_msgSend_232Ptr = _lookup< ffi.NativeFunction< ffi.Bool Function( ffi.Pointer, @@ -6332,7 +6316,7 @@ class SentryCocoa { ffi.Pointer, ffi.UnsignedLong, ffi.Pointer>)>>('objc_msgSend'); - late final __objc_msgSend_233 = __objc_msgSend_233Ptr.asFunction< + late final __objc_msgSend_232 = __objc_msgSend_232Ptr.asFunction< bool Function( ffi.Pointer, ffi.Pointer, @@ -6343,13 +6327,13 @@ class SentryCocoa { late final _sel_bookmarkDataWithContentsOfURL_error_1 = _registerName1("bookmarkDataWithContentsOfURL:error:"); - ffi.Pointer _objc_msgSend_234( + ffi.Pointer _objc_msgSend_233( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer bookmarkFileURL, ffi.Pointer> error, ) { - return __objc_msgSend_234( + return __objc_msgSend_233( obj, sel, bookmarkFileURL, @@ -6357,14 +6341,14 @@ class SentryCocoa { ); } - late final __objc_msgSend_234Ptr = _lookup< + late final __objc_msgSend_233Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer>)>>('objc_msgSend'); - late final __objc_msgSend_234 = __objc_msgSend_234Ptr.asFunction< + late final __objc_msgSend_233 = __objc_msgSend_233Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, @@ -6373,14 +6357,14 @@ class SentryCocoa { late final _sel_URLByResolvingAliasFileAtURL_options_error_1 = _registerName1("URLByResolvingAliasFileAtURL:options:error:"); - instancetype _objc_msgSend_235( + instancetype _objc_msgSend_234( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer url, int options, ffi.Pointer> error, ) { - return __objc_msgSend_235( + return __objc_msgSend_234( obj, sel, url, @@ -6389,7 +6373,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_235Ptr = _lookup< + late final __objc_msgSend_234Ptr = _lookup< ffi.NativeFunction< instancetype Function( ffi.Pointer, @@ -6397,7 +6381,7 @@ class SentryCocoa { ffi.Pointer, ffi.Int32, ffi.Pointer>)>>('objc_msgSend'); - late final __objc_msgSend_235 = __objc_msgSend_235Ptr.asFunction< + late final __objc_msgSend_234 = __objc_msgSend_234Ptr.asFunction< instancetype Function( ffi.Pointer, ffi.Pointer, @@ -6413,13 +6397,13 @@ class SentryCocoa { _registerName1("getPromisedItemResourceValue:forKey:error:"); late final _sel_promisedItemResourceValuesForKeys_error_1 = _registerName1("promisedItemResourceValuesForKeys:error:"); - ffi.Pointer _objc_msgSend_236( + ffi.Pointer _objc_msgSend_235( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer keys, ffi.Pointer> error, ) { - return __objc_msgSend_236( + return __objc_msgSend_235( obj, sel, keys, @@ -6427,14 +6411,14 @@ class SentryCocoa { ); } - late final __objc_msgSend_236Ptr = _lookup< + late final __objc_msgSend_235Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer>)>>('objc_msgSend'); - late final __objc_msgSend_236 = __objc_msgSend_236Ptr.asFunction< + late final __objc_msgSend_235 = __objc_msgSend_235Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, @@ -6443,6 +6427,26 @@ class SentryCocoa { late final _sel_checkPromisedItemIsReachableAndReturnError_1 = _registerName1("checkPromisedItemIsReachableAndReturnError:"); + bool _objc_msgSend_236( + ffi.Pointer obj, + ffi.Pointer sel, + ffi.Pointer> error, + ) { + return __objc_msgSend_236( + obj, + sel, + error, + ); + } + + late final __objc_msgSend_236Ptr = _lookup< + ffi.NativeFunction< + ffi.Bool Function(ffi.Pointer, ffi.Pointer, + ffi.Pointer>)>>('objc_msgSend'); + late final __objc_msgSend_236 = __objc_msgSend_236Ptr.asFunction< + bool Function(ffi.Pointer, ffi.Pointer, + ffi.Pointer>)>(); + late final _sel_fileURLWithPathComponents_1 = _registerName1("fileURLWithPathComponents:"); ffi.Pointer _objc_msgSend_237( @@ -6478,6 +6482,8 @@ class SentryCocoa { _registerName1("URLByAppendingPathExtension:"); late final _sel_URLByDeletingPathExtension1 = _registerName1("URLByDeletingPathExtension"); + late final _sel_checkResourceIsReachableAndReturnError_1 = + _registerName1("checkResourceIsReachableAndReturnError:"); late final _sel_URLByStandardizingPath1 = _registerName1("URLByStandardizingPath"); late final _sel_URLByResolvingSymlinksInPath1 = @@ -9531,7 +9537,7 @@ class SentryCocoa { ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer format, - ffi.Pointer<__va_list_tag> argList, + ffi.Pointer argList, ) { return __objc_msgSend_348( obj, @@ -9543,14 +9549,11 @@ class SentryCocoa { late final __objc_msgSend_348Ptr = _lookup< ffi.NativeFunction< - instancetype Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer<__va_list_tag>)>>('objc_msgSend'); + instancetype Function(ffi.Pointer, ffi.Pointer, + ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); late final __objc_msgSend_348 = __objc_msgSend_348Ptr.asFunction< instancetype Function(ffi.Pointer, ffi.Pointer, - ffi.Pointer, ffi.Pointer<__va_list_tag>)>(); + ffi.Pointer, ffi.Pointer)>(); late final _sel_initWithFormat_locale_1 = _registerName1("initWithFormat:locale:"); @@ -9561,7 +9564,7 @@ class SentryCocoa { ffi.Pointer sel, ffi.Pointer format, ffi.Pointer locale, - ffi.Pointer<__va_list_tag> argList, + ffi.Pointer argList, ) { return __objc_msgSend_349( obj, @@ -9579,14 +9582,14 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Pointer, - ffi.Pointer<__va_list_tag>)>>('objc_msgSend'); + ffi.Pointer)>>('objc_msgSend'); late final __objc_msgSend_349 = __objc_msgSend_349Ptr.asFunction< instancetype Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer, - ffi.Pointer<__va_list_tag>)>(); + ffi.Pointer)>(); late final _sel_initWithValidatedFormat_validFormatSpecifiers_error_1 = _registerName1("initWithValidatedFormat:validFormatSpecifiers:error:"); @@ -9669,7 +9672,7 @@ class SentryCocoa { ffi.Pointer sel, ffi.Pointer format, ffi.Pointer validFormatSpecifiers, - ffi.Pointer<__va_list_tag> argList, + ffi.Pointer argList, ffi.Pointer> error, ) { return __objc_msgSend_352( @@ -9689,7 +9692,7 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Pointer, - ffi.Pointer<__va_list_tag>, + ffi.Pointer, ffi.Pointer>)>>('objc_msgSend'); late final __objc_msgSend_352 = __objc_msgSend_352Ptr.asFunction< instancetype Function( @@ -9697,7 +9700,7 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Pointer, - ffi.Pointer<__va_list_tag>, + ffi.Pointer, ffi.Pointer>)>(); late final _sel_initWithValidatedFormat_validFormatSpecifiers_locale_arguments_error_1 = @@ -9709,7 +9712,7 @@ class SentryCocoa { ffi.Pointer format, ffi.Pointer validFormatSpecifiers, ffi.Pointer locale, - ffi.Pointer<__va_list_tag> argList, + ffi.Pointer argList, ffi.Pointer> error, ) { return __objc_msgSend_353( @@ -9731,7 +9734,7 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Pointer, - ffi.Pointer<__va_list_tag>, + ffi.Pointer, ffi.Pointer>)>>('objc_msgSend'); late final __objc_msgSend_353 = __objc_msgSend_353Ptr.asFunction< instancetype Function( @@ -9740,7 +9743,7 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Pointer, - ffi.Pointer<__va_list_tag>, + ffi.Pointer, ffi.Pointer>)>(); late final _sel_initWithData_encoding_1 = @@ -19014,7 +19017,7 @@ class SentryCocoa { ffi.Pointer format, int options, ffi.Pointer locale, - ffi.Pointer<__va_list_tag> arguments, + ffi.Pointer arguments, ) { return __objc_msgSend_673( obj, @@ -19034,7 +19037,7 @@ class SentryCocoa { ffi.Pointer, ffi.Int32, ffi.Pointer, - ffi.Pointer<__va_list_tag>)>>('objc_msgSend'); + ffi.Pointer)>>('objc_msgSend'); late final __objc_msgSend_673 = __objc_msgSend_673Ptr.asFunction< instancetype Function( ffi.Pointer, @@ -19042,7 +19045,7 @@ class SentryCocoa { ffi.Pointer, int, ffi.Pointer, - ffi.Pointer<__va_list_tag>)>(); + ffi.Pointer)>(); late final _sel_localizedAttributedStringWithFormat_1 = _registerName1("localizedAttributedStringWithFormat:"); @@ -19070,36 +19073,173 @@ class SentryCocoa { instancetype Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, int)>(); - late final _sel_attributedStringByInflectingString1 = - _registerName1("attributedStringByInflectingString"); - ffi.Pointer _objc_msgSend_675( + late final _sel_initWithFormat_options_locale_context_1 = + _registerName1("initWithFormat:options:locale:context:"); + instancetype _objc_msgSend_675( ffi.Pointer obj, ffi.Pointer sel, + ffi.Pointer format, + int options, + ffi.Pointer locale, + ffi.Pointer context, ) { return __objc_msgSend_675( obj, sel, + format, + options, + locale, + context, ); } late final __objc_msgSend_675Ptr = _lookup< + ffi.NativeFunction< + instancetype Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Int32, + ffi.Pointer, + ffi.Pointer)>>('objc_msgSend'); + late final __objc_msgSend_675 = __objc_msgSend_675Ptr.asFunction< + instancetype Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + int, + ffi.Pointer, + ffi.Pointer)>(); + + late final _sel_initWithFormat_options_locale_context_arguments_1 = + _registerName1("initWithFormat:options:locale:context:arguments:"); + instancetype _objc_msgSend_676( + ffi.Pointer obj, + ffi.Pointer sel, + ffi.Pointer format, + int options, + ffi.Pointer locale, + ffi.Pointer context, + ffi.Pointer arguments, + ) { + return __objc_msgSend_676( + obj, + sel, + format, + options, + locale, + context, + arguments, + ); + } + + late final __objc_msgSend_676Ptr = _lookup< + ffi.NativeFunction< + instancetype Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Int32, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer)>>('objc_msgSend'); + late final __objc_msgSend_676 = __objc_msgSend_676Ptr.asFunction< + instancetype Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + int, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer)>(); + + late final _sel_localizedAttributedStringWithFormat_context_1 = + _registerName1("localizedAttributedStringWithFormat:context:"); + instancetype _objc_msgSend_677( + ffi.Pointer obj, + ffi.Pointer sel, + ffi.Pointer format, + ffi.Pointer context, + ) { + return __objc_msgSend_677( + obj, + sel, + format, + context, + ); + } + + late final __objc_msgSend_677Ptr = _lookup< + ffi.NativeFunction< + instancetype Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer)>>('objc_msgSend'); + late final __objc_msgSend_677 = __objc_msgSend_677Ptr.asFunction< + instancetype Function(ffi.Pointer, ffi.Pointer, + ffi.Pointer, ffi.Pointer)>(); + + late final _sel_localizedAttributedStringWithFormat_options_context_1 = + _registerName1("localizedAttributedStringWithFormat:options:context:"); + instancetype _objc_msgSend_678( + ffi.Pointer obj, + ffi.Pointer sel, + ffi.Pointer format, + int options, + ffi.Pointer context, + ) { + return __objc_msgSend_678( + obj, + sel, + format, + options, + context, + ); + } + + late final __objc_msgSend_678Ptr = _lookup< + ffi.NativeFunction< + instancetype Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Int32, + ffi.Pointer)>>('objc_msgSend'); + late final __objc_msgSend_678 = __objc_msgSend_678Ptr.asFunction< + instancetype Function(ffi.Pointer, ffi.Pointer, + ffi.Pointer, int, ffi.Pointer)>(); + + late final _sel_attributedStringByInflectingString1 = + _registerName1("attributedStringByInflectingString"); + ffi.Pointer _objc_msgSend_679( + ffi.Pointer obj, + ffi.Pointer sel, + ) { + return __objc_msgSend_679( + obj, + sel, + ); + } + + late final __objc_msgSend_679Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_675 = __objc_msgSend_675Ptr.asFunction< + late final __objc_msgSend_679 = __objc_msgSend_679Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>(); late final _sel_localizedAttributedStringForKey_value_table_1 = _registerName1("localizedAttributedStringForKey:value:table:"); - ffi.Pointer _objc_msgSend_676( + ffi.Pointer _objc_msgSend_680( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer key, ffi.Pointer value, ffi.Pointer tableName, ) { - return __objc_msgSend_676( + return __objc_msgSend_680( obj, sel, key, @@ -19108,7 +19248,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_676Ptr = _lookup< + late final __objc_msgSend_680Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, @@ -19116,7 +19256,7 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_676 = __objc_msgSend_676Ptr.asFunction< + late final __objc_msgSend_680 = __objc_msgSend_680Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, @@ -19141,13 +19281,13 @@ class SentryCocoa { _registerName1("preferredLocalizationsFromArray:"); late final _sel_preferredLocalizationsFromArray_forPreferences_1 = _registerName1("preferredLocalizationsFromArray:forPreferences:"); - ffi.Pointer _objc_msgSend_677( + ffi.Pointer _objc_msgSend_681( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer localizationsArray, ffi.Pointer preferencesArray, ) { - return __objc_msgSend_677( + return __objc_msgSend_681( obj, sel, localizationsArray, @@ -19155,14 +19295,14 @@ class SentryCocoa { ); } - late final __objc_msgSend_677Ptr = _lookup< + late final __objc_msgSend_681Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_677 = __objc_msgSend_677Ptr.asFunction< + late final __objc_msgSend_681 = __objc_msgSend_681Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, @@ -19173,13 +19313,13 @@ class SentryCocoa { _registerName1("executableArchitectures"); late final _sel_setPreservationPriority_forTags_1 = _registerName1("setPreservationPriority:forTags:"); - void _objc_msgSend_678( + void _objc_msgSend_682( ffi.Pointer obj, ffi.Pointer sel, double priority, ffi.Pointer tags, ) { - return __objc_msgSend_678( + return __objc_msgSend_682( obj, sel, priority, @@ -19187,11 +19327,11 @@ class SentryCocoa { ); } - late final __objc_msgSend_678Ptr = _lookup< + late final __objc_msgSend_682Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Double, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_678 = __objc_msgSend_678Ptr.asFunction< + late final __objc_msgSend_682 = __objc_msgSend_682Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, double, ffi.Pointer)>(); @@ -19201,13 +19341,13 @@ class SentryCocoa { _getClass1("NSMutableAttributedString"); late final _sel_setAttributes_range_1 = _registerName1("setAttributes:range:"); - void _objc_msgSend_679( + void _objc_msgSend_683( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer attrs, _NSRange range, ) { - return __objc_msgSend_679( + return __objc_msgSend_683( obj, sel, attrs, @@ -19215,43 +19355,43 @@ class SentryCocoa { ); } - late final __objc_msgSend_679Ptr = _lookup< + late final __objc_msgSend_683Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, _NSRange)>>('objc_msgSend'); - late final __objc_msgSend_679 = __objc_msgSend_679Ptr.asFunction< + late final __objc_msgSend_683 = __objc_msgSend_683Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, _NSRange)>(); late final _sel_mutableString1 = _registerName1("mutableString"); - ffi.Pointer _objc_msgSend_680( + ffi.Pointer _objc_msgSend_684( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_680( + return __objc_msgSend_684( obj, sel, ); } - late final __objc_msgSend_680Ptr = _lookup< + late final __objc_msgSend_684Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_680 = __objc_msgSend_680Ptr.asFunction< + late final __objc_msgSend_684 = __objc_msgSend_684Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>(); late final _sel_addAttribute_value_range_1 = _registerName1("addAttribute:value:range:"); - void _objc_msgSend_681( + void _objc_msgSend_685( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer name, ffi.Pointer value, _NSRange range, ) { - return __objc_msgSend_681( + return __objc_msgSend_685( obj, sel, name, @@ -19260,7 +19400,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_681Ptr = _lookup< + late final __objc_msgSend_685Ptr = _lookup< ffi.NativeFunction< ffi.Void Function( ffi.Pointer, @@ -19268,7 +19408,7 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, _NSRange)>>('objc_msgSend'); - late final __objc_msgSend_681 = __objc_msgSend_681Ptr.asFunction< + late final __objc_msgSend_685 = __objc_msgSend_685Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer, _NSRange)>(); @@ -19276,13 +19416,13 @@ class SentryCocoa { _registerName1("addAttributes:range:"); late final _sel_removeAttribute_range_1 = _registerName1("removeAttribute:range:"); - void _objc_msgSend_682( + void _objc_msgSend_686( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer name, _NSRange range, ) { - return __objc_msgSend_682( + return __objc_msgSend_686( obj, sel, name, @@ -19290,23 +19430,23 @@ class SentryCocoa { ); } - late final __objc_msgSend_682Ptr = _lookup< + late final __objc_msgSend_686Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, _NSRange)>>('objc_msgSend'); - late final __objc_msgSend_682 = __objc_msgSend_682Ptr.asFunction< + late final __objc_msgSend_686 = __objc_msgSend_686Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, _NSRange)>(); late final _sel_replaceCharactersInRange_withAttributedString_1 = _registerName1("replaceCharactersInRange:withAttributedString:"); - void _objc_msgSend_683( + void _objc_msgSend_687( ffi.Pointer obj, ffi.Pointer sel, _NSRange range, ffi.Pointer attrString, ) { - return __objc_msgSend_683( + return __objc_msgSend_687( obj, sel, range, @@ -19314,23 +19454,23 @@ class SentryCocoa { ); } - late final __objc_msgSend_683Ptr = _lookup< + late final __objc_msgSend_687Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, _NSRange, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_683 = __objc_msgSend_683Ptr.asFunction< + late final __objc_msgSend_687 = __objc_msgSend_687Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, _NSRange, ffi.Pointer)>(); late final _sel_insertAttributedString_atIndex_1 = _registerName1("insertAttributedString:atIndex:"); - void _objc_msgSend_684( + void _objc_msgSend_688( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer attrString, int loc, ) { - return __objc_msgSend_684( + return __objc_msgSend_688( obj, sel, attrString, @@ -19338,33 +19478,33 @@ class SentryCocoa { ); } - late final __objc_msgSend_684Ptr = _lookup< + late final __objc_msgSend_688Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.UnsignedLong)>>('objc_msgSend'); - late final __objc_msgSend_684 = __objc_msgSend_684Ptr.asFunction< + late final __objc_msgSend_688 = __objc_msgSend_688Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, int)>(); late final _sel_appendAttributedString_1 = _registerName1("appendAttributedString:"); - void _objc_msgSend_685( + void _objc_msgSend_689( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer attrString, ) { - return __objc_msgSend_685( + return __objc_msgSend_689( obj, sel, attrString, ); } - late final __objc_msgSend_685Ptr = _lookup< + late final __objc_msgSend_689Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_685 = __objc_msgSend_685Ptr.asFunction< + late final __objc_msgSend_689 = __objc_msgSend_689Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); @@ -19380,13 +19520,13 @@ class SentryCocoa { _registerName1("stringForObjectValue:"); late final _sel_attributedStringForObjectValue_withDefaultAttributes_1 = _registerName1("attributedStringForObjectValue:withDefaultAttributes:"); - ffi.Pointer _objc_msgSend_686( + ffi.Pointer _objc_msgSend_690( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer obj1, ffi.Pointer attrs, ) { - return __objc_msgSend_686( + return __objc_msgSend_690( obj, sel, obj1, @@ -19394,14 +19534,14 @@ class SentryCocoa { ); } - late final __objc_msgSend_686Ptr = _lookup< + late final __objc_msgSend_690Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_686 = __objc_msgSend_686Ptr.asFunction< + late final __objc_msgSend_690 = __objc_msgSend_690Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, @@ -19412,14 +19552,14 @@ class SentryCocoa { _registerName1("editingStringForObjectValue:"); late final _sel_getObjectValue_forString_errorDescription_1 = _registerName1("getObjectValue:forString:errorDescription:"); - bool _objc_msgSend_687( + bool _objc_msgSend_691( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer> obj1, ffi.Pointer string, ffi.Pointer> error, ) { - return __objc_msgSend_687( + return __objc_msgSend_691( obj, sel, obj1, @@ -19428,7 +19568,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_687Ptr = _lookup< + late final __objc_msgSend_691Ptr = _lookup< ffi.NativeFunction< ffi.Bool Function( ffi.Pointer, @@ -19436,7 +19576,7 @@ class SentryCocoa { ffi.Pointer>, ffi.Pointer, ffi.Pointer>)>>('objc_msgSend'); - late final __objc_msgSend_687 = __objc_msgSend_687Ptr.asFunction< + late final __objc_msgSend_691 = __objc_msgSend_691Ptr.asFunction< bool Function( ffi.Pointer, ffi.Pointer, @@ -19446,14 +19586,14 @@ class SentryCocoa { late final _sel_isPartialStringValid_newEditingString_errorDescription_1 = _registerName1("isPartialStringValid:newEditingString:errorDescription:"); - bool _objc_msgSend_688( + bool _objc_msgSend_692( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer partialString, ffi.Pointer> newString, ffi.Pointer> error, ) { - return __objc_msgSend_688( + return __objc_msgSend_692( obj, sel, partialString, @@ -19462,7 +19602,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_688Ptr = _lookup< + late final __objc_msgSend_692Ptr = _lookup< ffi.NativeFunction< ffi.Bool Function( ffi.Pointer, @@ -19470,7 +19610,7 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer>, ffi.Pointer>)>>('objc_msgSend'); - late final __objc_msgSend_688 = __objc_msgSend_688Ptr.asFunction< + late final __objc_msgSend_692 = __objc_msgSend_692Ptr.asFunction< bool Function( ffi.Pointer, ffi.Pointer, @@ -19481,7 +19621,7 @@ class SentryCocoa { late final _sel_isPartialStringValid_proposedSelectedRange_originalString_originalSelectedRange_errorDescription_1 = _registerName1( "isPartialStringValid:proposedSelectedRange:originalString:originalSelectedRange:errorDescription:"); - bool _objc_msgSend_689( + bool _objc_msgSend_693( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer> partialStringPtr, @@ -19490,7 +19630,7 @@ class SentryCocoa { _NSRange origSelRange, ffi.Pointer> error, ) { - return __objc_msgSend_689( + return __objc_msgSend_693( obj, sel, partialStringPtr, @@ -19501,7 +19641,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_689Ptr = _lookup< + late final __objc_msgSend_693Ptr = _lookup< ffi.NativeFunction< ffi.Bool Function( ffi.Pointer, @@ -19511,7 +19651,7 @@ class SentryCocoa { ffi.Pointer, _NSRange, ffi.Pointer>)>>('objc_msgSend'); - late final __objc_msgSend_689 = __objc_msgSend_689Ptr.asFunction< + late final __objc_msgSend_693 = __objc_msgSend_693Ptr.asFunction< bool Function( ffi.Pointer, ffi.Pointer, @@ -19522,47 +19662,47 @@ class SentryCocoa { ffi.Pointer>)>(); late final _sel_formattingContext1 = _registerName1("formattingContext"); - int _objc_msgSend_690( + int _objc_msgSend_694( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_690( + return __objc_msgSend_694( obj, sel, ); } - late final __objc_msgSend_690Ptr = _lookup< + late final __objc_msgSend_694Ptr = _lookup< ffi.NativeFunction< ffi.Int32 Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_690 = __objc_msgSend_690Ptr.asFunction< + late final __objc_msgSend_694 = __objc_msgSend_694Ptr.asFunction< int Function(ffi.Pointer, ffi.Pointer)>(); late final _sel_setFormattingContext_1 = _registerName1("setFormattingContext:"); - void _objc_msgSend_691( + void _objc_msgSend_695( ffi.Pointer obj, ffi.Pointer sel, int value, ) { - return __objc_msgSend_691( + return __objc_msgSend_695( obj, sel, value, ); } - late final __objc_msgSend_691Ptr = _lookup< + late final __objc_msgSend_695Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Int32)>>('objc_msgSend'); - late final __objc_msgSend_691 = __objc_msgSend_691Ptr.asFunction< + late final __objc_msgSend_695 = __objc_msgSend_695Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, int)>(); late final _sel_getObjectValue_forString_range_error_1 = _registerName1("getObjectValue:forString:range:error:"); - bool _objc_msgSend_692( + bool _objc_msgSend_696( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer> obj1, @@ -19570,7 +19710,7 @@ class SentryCocoa { ffi.Pointer<_NSRange> rangep, ffi.Pointer> error, ) { - return __objc_msgSend_692( + return __objc_msgSend_696( obj, sel, obj1, @@ -19580,7 +19720,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_692Ptr = _lookup< + late final __objc_msgSend_696Ptr = _lookup< ffi.NativeFunction< ffi.Bool Function( ffi.Pointer, @@ -19589,7 +19729,7 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer<_NSRange>, ffi.Pointer>)>>('objc_msgSend'); - late final __objc_msgSend_692 = __objc_msgSend_692Ptr.asFunction< + late final __objc_msgSend_696 = __objc_msgSend_696Ptr.asFunction< bool Function( ffi.Pointer, ffi.Pointer, @@ -19602,14 +19742,14 @@ class SentryCocoa { late final _sel_dateFromString_1 = _registerName1("dateFromString:"); late final _sel_localizedStringFromDate_dateStyle_timeStyle_1 = _registerName1("localizedStringFromDate:dateStyle:timeStyle:"); - ffi.Pointer _objc_msgSend_693( + ffi.Pointer _objc_msgSend_697( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer date, int dstyle, int tstyle, ) { - return __objc_msgSend_693( + return __objc_msgSend_697( obj, sel, date, @@ -19618,7 +19758,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_693Ptr = _lookup< + late final __objc_msgSend_697Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, @@ -19626,20 +19766,20 @@ class SentryCocoa { ffi.Pointer, ffi.Int32, ffi.Int32)>>('objc_msgSend'); - late final __objc_msgSend_693 = __objc_msgSend_693Ptr.asFunction< + late final __objc_msgSend_697 = __objc_msgSend_697Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, int, int)>(); late final _sel_dateFormatFromTemplate_options_locale_1 = _registerName1("dateFormatFromTemplate:options:locale:"); - ffi.Pointer _objc_msgSend_694( + ffi.Pointer _objc_msgSend_698( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer tmplate, int opts, ffi.Pointer locale, ) { - return __objc_msgSend_694( + return __objc_msgSend_698( obj, sel, tmplate, @@ -19648,7 +19788,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_694Ptr = _lookup< + late final __objc_msgSend_698Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, @@ -19656,7 +19796,7 @@ class SentryCocoa { ffi.Pointer, ffi.UnsignedLong, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_694 = __objc_msgSend_694Ptr.asFunction< + late final __objc_msgSend_698 = __objc_msgSend_698Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, @@ -19666,42 +19806,42 @@ class SentryCocoa { late final _sel_defaultFormatterBehavior1 = _registerName1("defaultFormatterBehavior"); - int _objc_msgSend_695( + int _objc_msgSend_699( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_695( + return __objc_msgSend_699( obj, sel, ); } - late final __objc_msgSend_695Ptr = _lookup< + late final __objc_msgSend_699Ptr = _lookup< ffi.NativeFunction< ffi.Int32 Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_695 = __objc_msgSend_695Ptr.asFunction< + late final __objc_msgSend_699 = __objc_msgSend_699Ptr.asFunction< int Function(ffi.Pointer, ffi.Pointer)>(); late final _sel_setDefaultFormatterBehavior_1 = _registerName1("setDefaultFormatterBehavior:"); - void _objc_msgSend_696( + void _objc_msgSend_700( ffi.Pointer obj, ffi.Pointer sel, int value, ) { - return __objc_msgSend_696( + return __objc_msgSend_700( obj, sel, value, ); } - late final __objc_msgSend_696Ptr = _lookup< + late final __objc_msgSend_700Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Int32)>>('objc_msgSend'); - late final __objc_msgSend_696 = __objc_msgSend_696Ptr.asFunction< + late final __objc_msgSend_700 = __objc_msgSend_700Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, int)>(); late final _sel_setLocalizedDateFormatFromTemplate_1 = @@ -19709,64 +19849,64 @@ class SentryCocoa { late final _sel_dateFormat1 = _registerName1("dateFormat"); late final _sel_setDateFormat_1 = _registerName1("setDateFormat:"); late final _sel_dateStyle1 = _registerName1("dateStyle"); - int _objc_msgSend_697( + int _objc_msgSend_701( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_697( + return __objc_msgSend_701( obj, sel, ); } - late final __objc_msgSend_697Ptr = _lookup< + late final __objc_msgSend_701Ptr = _lookup< ffi.NativeFunction< ffi.Int32 Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_697 = __objc_msgSend_697Ptr.asFunction< + late final __objc_msgSend_701 = __objc_msgSend_701Ptr.asFunction< int Function(ffi.Pointer, ffi.Pointer)>(); late final _sel_setDateStyle_1 = _registerName1("setDateStyle:"); - void _objc_msgSend_698( + void _objc_msgSend_702( ffi.Pointer obj, ffi.Pointer sel, int value, ) { - return __objc_msgSend_698( + return __objc_msgSend_702( obj, sel, value, ); } - late final __objc_msgSend_698Ptr = _lookup< + late final __objc_msgSend_702Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Int32)>>('objc_msgSend'); - late final __objc_msgSend_698 = __objc_msgSend_698Ptr.asFunction< + late final __objc_msgSend_702 = __objc_msgSend_702Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, int)>(); late final _sel_timeStyle1 = _registerName1("timeStyle"); late final _sel_setTimeStyle_1 = _registerName1("setTimeStyle:"); late final _sel_locale1 = _registerName1("locale"); late final _sel_setLocale_1 = _registerName1("setLocale:"); - void _objc_msgSend_699( + void _objc_msgSend_703( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer value, ) { - return __objc_msgSend_699( + return __objc_msgSend_703( obj, sel, value, ); } - late final __objc_msgSend_699Ptr = _lookup< + late final __objc_msgSend_703Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_699 = __objc_msgSend_699Ptr.asFunction< + late final __objc_msgSend_703 = __objc_msgSend_703Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); @@ -19779,21 +19919,21 @@ class SentryCocoa { _registerName1("setFormatterBehavior:"); late final _class_NSCalendar1 = _getClass1("NSCalendar"); late final _sel_currentCalendar1 = _registerName1("currentCalendar"); - ffi.Pointer _objc_msgSend_700( + ffi.Pointer _objc_msgSend_704( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_700( + return __objc_msgSend_704( obj, sel, ); } - late final __objc_msgSend_700Ptr = _lookup< + late final __objc_msgSend_704Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_700 = __objc_msgSend_700Ptr.asFunction< + late final __objc_msgSend_704 = __objc_msgSend_704Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>(); @@ -19801,23 +19941,23 @@ class SentryCocoa { _registerName1("autoupdatingCurrentCalendar"); late final _sel_calendarWithIdentifier_1 = _registerName1("calendarWithIdentifier:"); - ffi.Pointer _objc_msgSend_701( + ffi.Pointer _objc_msgSend_705( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer calendarIdentifierConstant, ) { - return __objc_msgSend_701( + return __objc_msgSend_705( obj, sel, calendarIdentifierConstant, ); } - late final __objc_msgSend_701Ptr = _lookup< + late final __objc_msgSend_705Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_701 = __objc_msgSend_701Ptr.asFunction< + late final __objc_msgSend_705 = __objc_msgSend_705Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); @@ -19860,13 +20000,13 @@ class SentryCocoa { late final _sel_AMSymbol1 = _registerName1("AMSymbol"); late final _sel_PMSymbol1 = _registerName1("PMSymbol"); late final _sel_minimumRangeOfUnit_1 = _registerName1("minimumRangeOfUnit:"); - void _objc_msgSend_702( + void _objc_msgSend_706( ffi.Pointer<_NSRange> stret, ffi.Pointer obj, ffi.Pointer sel, int unit, ) { - return __objc_msgSend_702( + return __objc_msgSend_706( stret, obj, sel, @@ -19874,18 +20014,18 @@ class SentryCocoa { ); } - late final __objc_msgSend_702Ptr = _lookup< + late final __objc_msgSend_706Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer<_NSRange>, ffi.Pointer, ffi.Pointer, ffi.Int32)>>('objc_msgSend_stret'); - late final __objc_msgSend_702 = __objc_msgSend_702Ptr.asFunction< + late final __objc_msgSend_706 = __objc_msgSend_706Ptr.asFunction< void Function(ffi.Pointer<_NSRange>, ffi.Pointer, ffi.Pointer, int)>(); late final _sel_maximumRangeOfUnit_1 = _registerName1("maximumRangeOfUnit:"); late final _sel_rangeOfUnit_inUnit_forDate_1 = _registerName1("rangeOfUnit:inUnit:forDate:"); - void _objc_msgSend_703( + void _objc_msgSend_707( ffi.Pointer<_NSRange> stret, ffi.Pointer obj, ffi.Pointer sel, @@ -19893,7 +20033,7 @@ class SentryCocoa { int larger, ffi.Pointer date, ) { - return __objc_msgSend_703( + return __objc_msgSend_707( stret, obj, sel, @@ -19903,7 +20043,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_703Ptr = _lookup< + late final __objc_msgSend_707Ptr = _lookup< ffi.NativeFunction< ffi.Void Function( ffi.Pointer<_NSRange>, @@ -19912,20 +20052,20 @@ class SentryCocoa { ffi.Int32, ffi.Int32, ffi.Pointer)>>('objc_msgSend_stret'); - late final __objc_msgSend_703 = __objc_msgSend_703Ptr.asFunction< + late final __objc_msgSend_707 = __objc_msgSend_707Ptr.asFunction< void Function(ffi.Pointer<_NSRange>, ffi.Pointer, ffi.Pointer, int, int, ffi.Pointer)>(); late final _sel_ordinalityOfUnit_inUnit_forDate_1 = _registerName1("ordinalityOfUnit:inUnit:forDate:"); - int _objc_msgSend_704( + int _objc_msgSend_708( ffi.Pointer obj, ffi.Pointer sel, int smaller, int larger, ffi.Pointer date, ) { - return __objc_msgSend_704( + return __objc_msgSend_708( obj, sel, smaller, @@ -19934,7 +20074,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_704Ptr = _lookup< + late final __objc_msgSend_708Ptr = _lookup< ffi.NativeFunction< ffi.UnsignedLong Function( ffi.Pointer, @@ -19942,13 +20082,13 @@ class SentryCocoa { ffi.Int32, ffi.Int32, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_704 = __objc_msgSend_704Ptr.asFunction< + late final __objc_msgSend_708 = __objc_msgSend_708Ptr.asFunction< int Function(ffi.Pointer, ffi.Pointer, int, int, ffi.Pointer)>(); late final _sel_rangeOfUnit_startDate_interval_forDate_1 = _registerName1("rangeOfUnit:startDate:interval:forDate:"); - bool _objc_msgSend_705( + bool _objc_msgSend_709( ffi.Pointer obj, ffi.Pointer sel, int unit, @@ -19956,7 +20096,7 @@ class SentryCocoa { ffi.Pointer tip, ffi.Pointer date, ) { - return __objc_msgSend_705( + return __objc_msgSend_709( obj, sel, unit, @@ -19966,7 +20106,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_705Ptr = _lookup< + late final __objc_msgSend_709Ptr = _lookup< ffi.NativeFunction< ffi.Bool Function( ffi.Pointer, @@ -19975,7 +20115,7 @@ class SentryCocoa { ffi.Pointer>, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_705 = __objc_msgSend_705Ptr.asFunction< + late final __objc_msgSend_709 = __objc_msgSend_709Ptr.asFunction< bool Function( ffi.Pointer, ffi.Pointer, @@ -19987,23 +20127,23 @@ class SentryCocoa { late final _class_NSDateComponents1 = _getClass1("NSDateComponents"); late final _sel_calendar1 = _registerName1("calendar"); late final _sel_setCalendar_1 = _registerName1("setCalendar:"); - void _objc_msgSend_706( + void _objc_msgSend_710( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer value, ) { - return __objc_msgSend_706( + return __objc_msgSend_710( obj, sel, value, ); } - late final __objc_msgSend_706Ptr = _lookup< + late final __objc_msgSend_710Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_706 = __objc_msgSend_706Ptr.asFunction< + late final __objc_msgSend_710 = __objc_msgSend_710Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); @@ -20042,13 +20182,13 @@ class SentryCocoa { late final _sel_setWeek_1 = _registerName1("setWeek:"); late final _sel_setValue_forComponent_1 = _registerName1("setValue:forComponent:"); - void _objc_msgSend_707( + void _objc_msgSend_711( ffi.Pointer obj, ffi.Pointer sel, int value, int unit, ) { - return __objc_msgSend_707( + return __objc_msgSend_711( obj, sel, value, @@ -20056,86 +20196,86 @@ class SentryCocoa { ); } - late final __objc_msgSend_707Ptr = _lookup< + late final __objc_msgSend_711Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Long, ffi.Int32)>>('objc_msgSend'); - late final __objc_msgSend_707 = __objc_msgSend_707Ptr.asFunction< + late final __objc_msgSend_711 = __objc_msgSend_711Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, int, int)>(); late final _sel_valueForComponent_1 = _registerName1("valueForComponent:"); - int _objc_msgSend_708( + int _objc_msgSend_712( ffi.Pointer obj, ffi.Pointer sel, int unit, ) { - return __objc_msgSend_708( + return __objc_msgSend_712( obj, sel, unit, ); } - late final __objc_msgSend_708Ptr = _lookup< + late final __objc_msgSend_712Ptr = _lookup< ffi.NativeFunction< ffi.Long Function(ffi.Pointer, ffi.Pointer, ffi.Int32)>>('objc_msgSend'); - late final __objc_msgSend_708 = __objc_msgSend_708Ptr.asFunction< + late final __objc_msgSend_712 = __objc_msgSend_712Ptr.asFunction< int Function(ffi.Pointer, ffi.Pointer, int)>(); late final _sel_isValidDate1 = _registerName1("isValidDate"); late final _sel_isValidDateInCalendar_1 = _registerName1("isValidDateInCalendar:"); - bool _objc_msgSend_709( + bool _objc_msgSend_713( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer calendar, ) { - return __objc_msgSend_709( + return __objc_msgSend_713( obj, sel, calendar, ); } - late final __objc_msgSend_709Ptr = _lookup< + late final __objc_msgSend_713Ptr = _lookup< ffi.NativeFunction< ffi.Bool Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_709 = __objc_msgSend_709Ptr.asFunction< + late final __objc_msgSend_713 = __objc_msgSend_713Ptr.asFunction< bool Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); late final _sel_dateFromComponents_1 = _registerName1("dateFromComponents:"); - ffi.Pointer _objc_msgSend_710( + ffi.Pointer _objc_msgSend_714( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer comps, ) { - return __objc_msgSend_710( + return __objc_msgSend_714( obj, sel, comps, ); } - late final __objc_msgSend_710Ptr = _lookup< + late final __objc_msgSend_714Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_710 = __objc_msgSend_710Ptr.asFunction< + late final __objc_msgSend_714 = __objc_msgSend_714Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); late final _sel_components_fromDate_1 = _registerName1("components:fromDate:"); - ffi.Pointer _objc_msgSend_711( + ffi.Pointer _objc_msgSend_715( ffi.Pointer obj, ffi.Pointer sel, int unitFlags, ffi.Pointer date, ) { - return __objc_msgSend_711( + return __objc_msgSend_715( obj, sel, unitFlags, @@ -20143,27 +20283,27 @@ class SentryCocoa { ); } - late final __objc_msgSend_711Ptr = _lookup< + late final __objc_msgSend_715Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, ffi.Int32, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_711 = __objc_msgSend_711Ptr.asFunction< + late final __objc_msgSend_715 = __objc_msgSend_715Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, int, ffi.Pointer)>(); late final _sel_dateByAddingComponents_toDate_options_1 = _registerName1("dateByAddingComponents:toDate:options:"); - ffi.Pointer _objc_msgSend_712( + ffi.Pointer _objc_msgSend_716( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer comps, ffi.Pointer date, int opts, ) { - return __objc_msgSend_712( + return __objc_msgSend_716( obj, sel, comps, @@ -20172,7 +20312,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_712Ptr = _lookup< + late final __objc_msgSend_716Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, @@ -20180,7 +20320,7 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Int32)>>('objc_msgSend'); - late final __objc_msgSend_712 = __objc_msgSend_712Ptr.asFunction< + late final __objc_msgSend_716 = __objc_msgSend_716Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, @@ -20190,7 +20330,7 @@ class SentryCocoa { late final _sel_components_fromDate_toDate_options_1 = _registerName1("components:fromDate:toDate:options:"); - ffi.Pointer _objc_msgSend_713( + ffi.Pointer _objc_msgSend_717( ffi.Pointer obj, ffi.Pointer sel, int unitFlags, @@ -20198,7 +20338,7 @@ class SentryCocoa { ffi.Pointer resultDate, int opts, ) { - return __objc_msgSend_713( + return __objc_msgSend_717( obj, sel, unitFlags, @@ -20208,7 +20348,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_713Ptr = _lookup< + late final __objc_msgSend_717Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, @@ -20217,7 +20357,7 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Int32)>>('objc_msgSend'); - late final __objc_msgSend_713 = __objc_msgSend_713Ptr.asFunction< + late final __objc_msgSend_717 = __objc_msgSend_717Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, @@ -20228,7 +20368,7 @@ class SentryCocoa { late final _sel_getEra_year_month_day_fromDate_1 = _registerName1("getEra:year:month:day:fromDate:"); - void _objc_msgSend_714( + void _objc_msgSend_718( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer eraValuePointer, @@ -20237,7 +20377,7 @@ class SentryCocoa { ffi.Pointer dayValuePointer, ffi.Pointer date, ) { - return __objc_msgSend_714( + return __objc_msgSend_718( obj, sel, eraValuePointer, @@ -20248,7 +20388,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_714Ptr = _lookup< + late final __objc_msgSend_718Ptr = _lookup< ffi.NativeFunction< ffi.Void Function( ffi.Pointer, @@ -20258,7 +20398,7 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_714 = __objc_msgSend_714Ptr.asFunction< + late final __objc_msgSend_718 = __objc_msgSend_718Ptr.asFunction< void Function( ffi.Pointer, ffi.Pointer, @@ -20273,13 +20413,13 @@ class SentryCocoa { late final _sel_getHour_minute_second_nanosecond_fromDate_1 = _registerName1("getHour:minute:second:nanosecond:fromDate:"); late final _sel_component_fromDate_1 = _registerName1("component:fromDate:"); - int _objc_msgSend_715( + int _objc_msgSend_719( ffi.Pointer obj, ffi.Pointer sel, int unit, ffi.Pointer date, ) { - return __objc_msgSend_715( + return __objc_msgSend_719( obj, sel, unit, @@ -20287,18 +20427,18 @@ class SentryCocoa { ); } - late final __objc_msgSend_715Ptr = _lookup< + late final __objc_msgSend_719Ptr = _lookup< ffi.NativeFunction< ffi.Long Function(ffi.Pointer, ffi.Pointer, ffi.Int32, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_715 = __objc_msgSend_715Ptr.asFunction< + late final __objc_msgSend_719 = __objc_msgSend_719Ptr.asFunction< int Function(ffi.Pointer, ffi.Pointer, int, ffi.Pointer)>(); late final _sel_dateWithEra_year_month_day_hour_minute_second_nanosecond_1 = _registerName1( "dateWithEra:year:month:day:hour:minute:second:nanosecond:"); - ffi.Pointer _objc_msgSend_716( + ffi.Pointer _objc_msgSend_720( ffi.Pointer obj, ffi.Pointer sel, int eraValue, @@ -20310,7 +20450,7 @@ class SentryCocoa { int secondValue, int nanosecondValue, ) { - return __objc_msgSend_716( + return __objc_msgSend_720( obj, sel, eraValue, @@ -20324,7 +20464,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_716Ptr = _lookup< + late final __objc_msgSend_720Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, @@ -20337,7 +20477,7 @@ class SentryCocoa { ffi.Long, ffi.Long, ffi.Long)>>('objc_msgSend'); - late final __objc_msgSend_716 = __objc_msgSend_716Ptr.asFunction< + late final __objc_msgSend_720 = __objc_msgSend_720Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, int, int, int, int, int, int, int, int)>(); @@ -20347,13 +20487,13 @@ class SentryCocoa { late final _sel_startOfDayForDate_1 = _registerName1("startOfDayForDate:"); late final _sel_componentsInTimeZone_fromDate_1 = _registerName1("componentsInTimeZone:fromDate:"); - ffi.Pointer _objc_msgSend_717( + ffi.Pointer _objc_msgSend_721( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer timezone, ffi.Pointer date, ) { - return __objc_msgSend_717( + return __objc_msgSend_721( obj, sel, timezone, @@ -20361,14 +20501,14 @@ class SentryCocoa { ); } - late final __objc_msgSend_717Ptr = _lookup< + late final __objc_msgSend_721Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_717 = __objc_msgSend_717Ptr.asFunction< + late final __objc_msgSend_721 = __objc_msgSend_721Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, @@ -20377,14 +20517,14 @@ class SentryCocoa { late final _sel_compareDate_toDate_toUnitGranularity_1 = _registerName1("compareDate:toDate:toUnitGranularity:"); - int _objc_msgSend_718( + int _objc_msgSend_722( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer date1, ffi.Pointer date2, int unit, ) { - return __objc_msgSend_718( + return __objc_msgSend_722( obj, sel, date1, @@ -20393,7 +20533,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_718Ptr = _lookup< + late final __objc_msgSend_722Ptr = _lookup< ffi.NativeFunction< ffi.Int32 Function( ffi.Pointer, @@ -20401,20 +20541,20 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Int32)>>('objc_msgSend'); - late final __objc_msgSend_718 = __objc_msgSend_718Ptr.asFunction< + late final __objc_msgSend_722 = __objc_msgSend_722Ptr.asFunction< int Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer, int)>(); late final _sel_isDate_equalToDate_toUnitGranularity_1 = _registerName1("isDate:equalToDate:toUnitGranularity:"); - bool _objc_msgSend_719( + bool _objc_msgSend_723( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer date1, ffi.Pointer date2, int unit, ) { - return __objc_msgSend_719( + return __objc_msgSend_723( obj, sel, date1, @@ -20423,7 +20563,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_719Ptr = _lookup< + late final __objc_msgSend_723Ptr = _lookup< ffi.NativeFunction< ffi.Bool Function( ffi.Pointer, @@ -20431,19 +20571,19 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Int32)>>('objc_msgSend'); - late final __objc_msgSend_719 = __objc_msgSend_719Ptr.asFunction< + late final __objc_msgSend_723 = __objc_msgSend_723Ptr.asFunction< bool Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer, int)>(); late final _sel_isDate_inSameDayAsDate_1 = _registerName1("isDate:inSameDayAsDate:"); - bool _objc_msgSend_720( + bool _objc_msgSend_724( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer date1, ffi.Pointer date2, ) { - return __objc_msgSend_720( + return __objc_msgSend_724( obj, sel, date1, @@ -20451,14 +20591,14 @@ class SentryCocoa { ); } - late final __objc_msgSend_720Ptr = _lookup< + late final __objc_msgSend_724Ptr = _lookup< ffi.NativeFunction< ffi.Bool Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_720 = __objc_msgSend_720Ptr.asFunction< + late final __objc_msgSend_724 = __objc_msgSend_724Ptr.asFunction< bool Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); @@ -20468,14 +20608,14 @@ class SentryCocoa { late final _sel_isDateInWeekend_1 = _registerName1("isDateInWeekend:"); late final _sel_rangeOfWeekendStartDate_interval_containingDate_1 = _registerName1("rangeOfWeekendStartDate:interval:containingDate:"); - bool _objc_msgSend_721( + bool _objc_msgSend_725( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer> datep, ffi.Pointer tip, ffi.Pointer date, ) { - return __objc_msgSend_721( + return __objc_msgSend_725( obj, sel, datep, @@ -20484,7 +20624,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_721Ptr = _lookup< + late final __objc_msgSend_725Ptr = _lookup< ffi.NativeFunction< ffi.Bool Function( ffi.Pointer, @@ -20492,7 +20632,7 @@ class SentryCocoa { ffi.Pointer>, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_721 = __objc_msgSend_721Ptr.asFunction< + late final __objc_msgSend_725 = __objc_msgSend_725Ptr.asFunction< bool Function( ffi.Pointer, ffi.Pointer, @@ -20502,7 +20642,7 @@ class SentryCocoa { late final _sel_nextWeekendStartDate_interval_options_afterDate_1 = _registerName1("nextWeekendStartDate:interval:options:afterDate:"); - bool _objc_msgSend_722( + bool _objc_msgSend_726( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer> datep, @@ -20510,7 +20650,7 @@ class SentryCocoa { int options, ffi.Pointer date, ) { - return __objc_msgSend_722( + return __objc_msgSend_726( obj, sel, datep, @@ -20520,7 +20660,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_722Ptr = _lookup< + late final __objc_msgSend_726Ptr = _lookup< ffi.NativeFunction< ffi.Bool Function( ffi.Pointer, @@ -20529,7 +20669,7 @@ class SentryCocoa { ffi.Pointer, ffi.Int32, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_722 = __objc_msgSend_722Ptr.asFunction< + late final __objc_msgSend_726 = __objc_msgSend_726Ptr.asFunction< bool Function( ffi.Pointer, ffi.Pointer, @@ -20540,7 +20680,7 @@ class SentryCocoa { late final _sel_components_fromDateComponents_toDateComponents_options_1 = _registerName1("components:fromDateComponents:toDateComponents:options:"); - ffi.Pointer _objc_msgSend_723( + ffi.Pointer _objc_msgSend_727( ffi.Pointer obj, ffi.Pointer sel, int unitFlags, @@ -20548,7 +20688,7 @@ class SentryCocoa { ffi.Pointer resultDateComp, int options, ) { - return __objc_msgSend_723( + return __objc_msgSend_727( obj, sel, unitFlags, @@ -20558,7 +20698,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_723Ptr = _lookup< + late final __objc_msgSend_727Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, @@ -20567,7 +20707,7 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Int32)>>('objc_msgSend'); - late final __objc_msgSend_723 = __objc_msgSend_723Ptr.asFunction< + late final __objc_msgSend_727 = __objc_msgSend_727Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, @@ -20578,7 +20718,7 @@ class SentryCocoa { late final _sel_dateByAddingUnit_value_toDate_options_1 = _registerName1("dateByAddingUnit:value:toDate:options:"); - ffi.Pointer _objc_msgSend_724( + ffi.Pointer _objc_msgSend_728( ffi.Pointer obj, ffi.Pointer sel, int unit, @@ -20586,7 +20726,7 @@ class SentryCocoa { ffi.Pointer date, int options, ) { - return __objc_msgSend_724( + return __objc_msgSend_728( obj, sel, unit, @@ -20596,7 +20736,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_724Ptr = _lookup< + late final __objc_msgSend_728Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, @@ -20605,14 +20745,14 @@ class SentryCocoa { ffi.Long, ffi.Pointer, ffi.Int32)>>('objc_msgSend'); - late final __objc_msgSend_724 = __objc_msgSend_724Ptr.asFunction< + late final __objc_msgSend_728 = __objc_msgSend_728Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, int, int, ffi.Pointer, int)>(); late final _sel_enumerateDatesStartingAfterDate_matchingComponents_options_usingBlock_1 = _registerName1( "enumerateDatesStartingAfterDate:matchingComponents:options:usingBlock:"); - void _objc_msgSend_725( + void _objc_msgSend_729( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer start, @@ -20620,7 +20760,7 @@ class SentryCocoa { int opts, ffi.Pointer<_ObjCBlock> block, ) { - return __objc_msgSend_725( + return __objc_msgSend_729( obj, sel, start, @@ -20630,7 +20770,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_725Ptr = _lookup< + late final __objc_msgSend_729Ptr = _lookup< ffi.NativeFunction< ffi.Void Function( ffi.Pointer, @@ -20639,7 +20779,7 @@ class SentryCocoa { ffi.Pointer, ffi.Int32, ffi.Pointer<_ObjCBlock>)>>('objc_msgSend'); - late final __objc_msgSend_725 = __objc_msgSend_725Ptr.asFunction< + late final __objc_msgSend_729 = __objc_msgSend_729Ptr.asFunction< void Function( ffi.Pointer, ffi.Pointer, @@ -20650,14 +20790,14 @@ class SentryCocoa { late final _sel_nextDateAfterDate_matchingComponents_options_1 = _registerName1("nextDateAfterDate:matchingComponents:options:"); - ffi.Pointer _objc_msgSend_726( + ffi.Pointer _objc_msgSend_730( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer date, ffi.Pointer comps, int options, ) { - return __objc_msgSend_726( + return __objc_msgSend_730( obj, sel, date, @@ -20666,7 +20806,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_726Ptr = _lookup< + late final __objc_msgSend_730Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, @@ -20674,7 +20814,7 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Int32)>>('objc_msgSend'); - late final __objc_msgSend_726 = __objc_msgSend_726Ptr.asFunction< + late final __objc_msgSend_730 = __objc_msgSend_730Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, @@ -20684,7 +20824,7 @@ class SentryCocoa { late final _sel_nextDateAfterDate_matchingUnit_value_options_1 = _registerName1("nextDateAfterDate:matchingUnit:value:options:"); - ffi.Pointer _objc_msgSend_727( + ffi.Pointer _objc_msgSend_731( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer date, @@ -20692,7 +20832,7 @@ class SentryCocoa { int value, int options, ) { - return __objc_msgSend_727( + return __objc_msgSend_731( obj, sel, date, @@ -20702,7 +20842,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_727Ptr = _lookup< + late final __objc_msgSend_731Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, @@ -20711,13 +20851,13 @@ class SentryCocoa { ffi.Int32, ffi.Long, ffi.Int32)>>('objc_msgSend'); - late final __objc_msgSend_727 = __objc_msgSend_727Ptr.asFunction< + late final __objc_msgSend_731 = __objc_msgSend_731Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, int, int, int)>(); late final _sel_nextDateAfterDate_matchingHour_minute_second_options_1 = _registerName1("nextDateAfterDate:matchingHour:minute:second:options:"); - ffi.Pointer _objc_msgSend_728( + ffi.Pointer _objc_msgSend_732( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer date, @@ -20726,7 +20866,7 @@ class SentryCocoa { int secondValue, int options, ) { - return __objc_msgSend_728( + return __objc_msgSend_732( obj, sel, date, @@ -20737,7 +20877,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_728Ptr = _lookup< + late final __objc_msgSend_732Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, @@ -20747,7 +20887,7 @@ class SentryCocoa { ffi.Long, ffi.Long, ffi.Int32)>>('objc_msgSend'); - late final __objc_msgSend_728 = __objc_msgSend_728Ptr.asFunction< + late final __objc_msgSend_732 = __objc_msgSend_732Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, int, int, int, int)>(); @@ -20755,7 +20895,7 @@ class SentryCocoa { _registerName1("dateBySettingUnit:value:ofDate:options:"); late final _sel_dateBySettingHour_minute_second_ofDate_options_1 = _registerName1("dateBySettingHour:minute:second:ofDate:options:"); - ffi.Pointer _objc_msgSend_729( + ffi.Pointer _objc_msgSend_733( ffi.Pointer obj, ffi.Pointer sel, int h, @@ -20764,7 +20904,7 @@ class SentryCocoa { ffi.Pointer date, int opts, ) { - return __objc_msgSend_729( + return __objc_msgSend_733( obj, sel, h, @@ -20775,7 +20915,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_729Ptr = _lookup< + late final __objc_msgSend_733Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, @@ -20785,19 +20925,19 @@ class SentryCocoa { ffi.Long, ffi.Pointer, ffi.Int32)>>('objc_msgSend'); - late final __objc_msgSend_729 = __objc_msgSend_729Ptr.asFunction< + late final __objc_msgSend_733 = __objc_msgSend_733Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, int, int, int, ffi.Pointer, int)>(); late final _sel_date_matchesComponents_1 = _registerName1("date:matchesComponents:"); - bool _objc_msgSend_730( + bool _objc_msgSend_734( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer date, ffi.Pointer components, ) { - return __objc_msgSend_730( + return __objc_msgSend_734( obj, sel, date, @@ -20805,14 +20945,14 @@ class SentryCocoa { ); } - late final __objc_msgSend_730Ptr = _lookup< + late final __objc_msgSend_734Ptr = _lookup< ffi.NativeFunction< ffi.Bool Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_730 = __objc_msgSend_730Ptr.asFunction< + late final __objc_msgSend_734 = __objc_msgSend_734Ptr.asFunction< bool Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); @@ -20824,23 +20964,23 @@ class SentryCocoa { late final _sel_defaultDate1 = _registerName1("defaultDate"); late final _sel_setDefaultDate_1 = _registerName1("setDefaultDate:"); late final _sel_setEraSymbols_1 = _registerName1("setEraSymbols:"); - void _objc_msgSend_731( + void _objc_msgSend_735( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer value, ) { - return __objc_msgSend_731( + return __objc_msgSend_735( obj, sel, value, ); } - late final __objc_msgSend_731Ptr = _lookup< + late final __objc_msgSend_735Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_731 = __objc_msgSend_731Ptr.asFunction< + late final __objc_msgSend_735 = __objc_msgSend_735Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); @@ -20889,56 +21029,56 @@ class SentryCocoa { _registerName1("allowsNaturalLanguage"); late final _class_NSNumberFormatter1 = _getClass1("NSNumberFormatter"); late final _sel_stringFromNumber_1 = _registerName1("stringFromNumber:"); - ffi.Pointer _objc_msgSend_732( + ffi.Pointer _objc_msgSend_736( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer number, ) { - return __objc_msgSend_732( + return __objc_msgSend_736( obj, sel, number, ); } - late final __objc_msgSend_732Ptr = _lookup< + late final __objc_msgSend_736Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_732 = __objc_msgSend_732Ptr.asFunction< + late final __objc_msgSend_736 = __objc_msgSend_736Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); late final _sel_numberFromString_1 = _registerName1("numberFromString:"); - ffi.Pointer _objc_msgSend_733( + ffi.Pointer _objc_msgSend_737( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer string, ) { - return __objc_msgSend_733( + return __objc_msgSend_737( obj, sel, string, ); } - late final __objc_msgSend_733Ptr = _lookup< + late final __objc_msgSend_737Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_733 = __objc_msgSend_733Ptr.asFunction< + late final __objc_msgSend_737 = __objc_msgSend_737Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); late final _sel_localizedStringFromNumber_numberStyle_1 = _registerName1("localizedStringFromNumber:numberStyle:"); - ffi.Pointer _objc_msgSend_734( + ffi.Pointer _objc_msgSend_738( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer num, int nstyle, ) { - return __objc_msgSend_734( + return __objc_msgSend_738( obj, sel, num, @@ -20946,112 +21086,112 @@ class SentryCocoa { ); } - late final __objc_msgSend_734Ptr = _lookup< + late final __objc_msgSend_738Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Int32)>>('objc_msgSend'); - late final __objc_msgSend_734 = __objc_msgSend_734Ptr.asFunction< + late final __objc_msgSend_738 = __objc_msgSend_738Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, int)>(); - int _objc_msgSend_735( + int _objc_msgSend_739( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_735( + return __objc_msgSend_739( obj, sel, ); } - late final __objc_msgSend_735Ptr = _lookup< + late final __objc_msgSend_739Ptr = _lookup< ffi.NativeFunction< ffi.Int32 Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_735 = __objc_msgSend_735Ptr.asFunction< + late final __objc_msgSend_739 = __objc_msgSend_739Ptr.asFunction< int Function(ffi.Pointer, ffi.Pointer)>(); - void _objc_msgSend_736( + void _objc_msgSend_740( ffi.Pointer obj, ffi.Pointer sel, int behavior, ) { - return __objc_msgSend_736( + return __objc_msgSend_740( obj, sel, behavior, ); } - late final __objc_msgSend_736Ptr = _lookup< + late final __objc_msgSend_740Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Int32)>>('objc_msgSend'); - late final __objc_msgSend_736 = __objc_msgSend_736Ptr.asFunction< + late final __objc_msgSend_740 = __objc_msgSend_740Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, int)>(); late final _sel_numberStyle1 = _registerName1("numberStyle"); - int _objc_msgSend_737( + int _objc_msgSend_741( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_737( + return __objc_msgSend_741( obj, sel, ); } - late final __objc_msgSend_737Ptr = _lookup< + late final __objc_msgSend_741Ptr = _lookup< ffi.NativeFunction< ffi.Int32 Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_737 = __objc_msgSend_737Ptr.asFunction< + late final __objc_msgSend_741 = __objc_msgSend_741Ptr.asFunction< int Function(ffi.Pointer, ffi.Pointer)>(); late final _sel_setNumberStyle_1 = _registerName1("setNumberStyle:"); - void _objc_msgSend_738( + void _objc_msgSend_742( ffi.Pointer obj, ffi.Pointer sel, int value, ) { - return __objc_msgSend_738( + return __objc_msgSend_742( obj, sel, value, ); } - late final __objc_msgSend_738Ptr = _lookup< + late final __objc_msgSend_742Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Int32)>>('objc_msgSend'); - late final __objc_msgSend_738 = __objc_msgSend_738Ptr.asFunction< + late final __objc_msgSend_742 = __objc_msgSend_742Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, int)>(); late final _sel_generatesDecimalNumbers1 = _registerName1("generatesDecimalNumbers"); late final _sel_setGeneratesDecimalNumbers_1 = _registerName1("setGeneratesDecimalNumbers:"); - void _objc_msgSend_739( + void _objc_msgSend_743( ffi.Pointer obj, ffi.Pointer sel, int value, ) { - return __objc_msgSend_739( + return __objc_msgSend_743( obj, sel, value, ); } - late final __objc_msgSend_739Ptr = _lookup< + late final __objc_msgSend_743Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Int32)>>('objc_msgSend'); - late final __objc_msgSend_739 = __objc_msgSend_739Ptr.asFunction< + late final __objc_msgSend_743 = __objc_msgSend_743Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, int)>(); late final _sel_negativeFormat1 = _registerName1("negativeFormat"); @@ -21157,79 +21297,79 @@ class SentryCocoa { late final _sel_setPaddingCharacter_1 = _registerName1("setPaddingCharacter:"); late final _sel_paddingPosition1 = _registerName1("paddingPosition"); - int _objc_msgSend_740( + int _objc_msgSend_744( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_740( + return __objc_msgSend_744( obj, sel, ); } - late final __objc_msgSend_740Ptr = _lookup< + late final __objc_msgSend_744Ptr = _lookup< ffi.NativeFunction< ffi.Int32 Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_740 = __objc_msgSend_740Ptr.asFunction< + late final __objc_msgSend_744 = __objc_msgSend_744Ptr.asFunction< int Function(ffi.Pointer, ffi.Pointer)>(); late final _sel_setPaddingPosition_1 = _registerName1("setPaddingPosition:"); - void _objc_msgSend_741( + void _objc_msgSend_745( ffi.Pointer obj, ffi.Pointer sel, int value, ) { - return __objc_msgSend_741( + return __objc_msgSend_745( obj, sel, value, ); } - late final __objc_msgSend_741Ptr = _lookup< + late final __objc_msgSend_745Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Int32)>>('objc_msgSend'); - late final __objc_msgSend_741 = __objc_msgSend_741Ptr.asFunction< + late final __objc_msgSend_745 = __objc_msgSend_745Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, int)>(); late final _sel_roundingMode1 = _registerName1("roundingMode"); - int _objc_msgSend_742( + int _objc_msgSend_746( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_742( + return __objc_msgSend_746( obj, sel, ); } - late final __objc_msgSend_742Ptr = _lookup< + late final __objc_msgSend_746Ptr = _lookup< ffi.NativeFunction< ffi.Int32 Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_742 = __objc_msgSend_742Ptr.asFunction< + late final __objc_msgSend_746 = __objc_msgSend_746Ptr.asFunction< int Function(ffi.Pointer, ffi.Pointer)>(); late final _sel_setRoundingMode_1 = _registerName1("setRoundingMode:"); - void _objc_msgSend_743( + void _objc_msgSend_747( ffi.Pointer obj, ffi.Pointer sel, int value, ) { - return __objc_msgSend_743( + return __objc_msgSend_747( obj, sel, value, ); } - late final __objc_msgSend_743Ptr = _lookup< + late final __objc_msgSend_747Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Int32)>>('objc_msgSend'); - late final __objc_msgSend_743 = __objc_msgSend_743Ptr.asFunction< + late final __objc_msgSend_747 = __objc_msgSend_747Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, int)>(); late final _sel_roundingIncrement1 = _registerName1("roundingIncrement"); @@ -21290,23 +21430,23 @@ class SentryCocoa { _registerName1("attributedStringForZero"); late final _sel_setAttributedStringForZero_1 = _registerName1("setAttributedStringForZero:"); - void _objc_msgSend_744( + void _objc_msgSend_748( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer value, ) { - return __objc_msgSend_744( + return __objc_msgSend_748( obj, sel, value, ); } - late final __objc_msgSend_744Ptr = _lookup< + late final __objc_msgSend_748Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_744 = __objc_msgSend_744Ptr.asFunction< + late final __objc_msgSend_748 = __objc_msgSend_748Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); @@ -21322,28 +21462,28 @@ class SentryCocoa { _getClass1("NSDecimalNumberHandler"); late final _sel_defaultDecimalNumberHandler1 = _registerName1("defaultDecimalNumberHandler"); - ffi.Pointer _objc_msgSend_745( + ffi.Pointer _objc_msgSend_749( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_745( + return __objc_msgSend_749( obj, sel, ); } - late final __objc_msgSend_745Ptr = _lookup< + late final __objc_msgSend_749Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_745 = __objc_msgSend_745Ptr.asFunction< + late final __objc_msgSend_749 = __objc_msgSend_749Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>(); late final _sel_initWithRoundingMode_scale_raiseOnExactness_raiseOnOverflow_raiseOnUnderflow_raiseOnDivideByZero_1 = _registerName1( "initWithRoundingMode:scale:raiseOnExactness:raiseOnOverflow:raiseOnUnderflow:raiseOnDivideByZero:"); - instancetype _objc_msgSend_746( + instancetype _objc_msgSend_750( ffi.Pointer obj, ffi.Pointer sel, int roundingMode, @@ -21353,7 +21493,7 @@ class SentryCocoa { bool underflow, bool divideByZero, ) { - return __objc_msgSend_746( + return __objc_msgSend_750( obj, sel, roundingMode, @@ -21365,7 +21505,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_746Ptr = _lookup< + late final __objc_msgSend_750Ptr = _lookup< ffi.NativeFunction< instancetype Function( ffi.Pointer, @@ -21376,7 +21516,7 @@ class SentryCocoa { ffi.Bool, ffi.Bool, ffi.Bool)>>('objc_msgSend'); - late final __objc_msgSend_746 = __objc_msgSend_746Ptr.asFunction< + late final __objc_msgSend_750 = __objc_msgSend_750Ptr.asFunction< instancetype Function(ffi.Pointer, ffi.Pointer, int, int, bool, bool, bool, bool)>(); @@ -21386,23 +21526,23 @@ class SentryCocoa { late final _sel_roundingBehavior1 = _registerName1("roundingBehavior"); late final _sel_setRoundingBehavior_1 = _registerName1("setRoundingBehavior:"); - void _objc_msgSend_747( + void _objc_msgSend_751( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer value, ) { - return __objc_msgSend_747( + return __objc_msgSend_751( obj, sel, value, ); } - late final __objc_msgSend_747Ptr = _lookup< + late final __objc_msgSend_751Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_747 = __objc_msgSend_747Ptr.asFunction< + late final __objc_msgSend_751 = __objc_msgSend_751Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); @@ -21413,173 +21553,173 @@ class SentryCocoa { _registerName1("charactersToBeSkipped"); late final _sel_setCharactersToBeSkipped_1 = _registerName1("setCharactersToBeSkipped:"); - void _objc_msgSend_748( + void _objc_msgSend_752( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer value, ) { - return __objc_msgSend_748( + return __objc_msgSend_752( obj, sel, value, ); } - late final __objc_msgSend_748Ptr = _lookup< + late final __objc_msgSend_752Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_748 = __objc_msgSend_748Ptr.asFunction< + late final __objc_msgSend_752 = __objc_msgSend_752Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); late final _sel_caseSensitive1 = _registerName1("caseSensitive"); late final _sel_setCaseSensitive_1 = _registerName1("setCaseSensitive:"); late final _sel_scanInt_1 = _registerName1("scanInt:"); - bool _objc_msgSend_749( + bool _objc_msgSend_753( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer result, ) { - return __objc_msgSend_749( + return __objc_msgSend_753( obj, sel, result, ); } - late final __objc_msgSend_749Ptr = _lookup< + late final __objc_msgSend_753Ptr = _lookup< ffi.NativeFunction< ffi.Bool Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_749 = __objc_msgSend_749Ptr.asFunction< + late final __objc_msgSend_753 = __objc_msgSend_753Ptr.asFunction< bool Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); late final _sel_scanInteger_1 = _registerName1("scanInteger:"); - bool _objc_msgSend_750( + bool _objc_msgSend_754( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer result, ) { - return __objc_msgSend_750( + return __objc_msgSend_754( obj, sel, result, ); } - late final __objc_msgSend_750Ptr = _lookup< + late final __objc_msgSend_754Ptr = _lookup< ffi.NativeFunction< ffi.Bool Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_750 = __objc_msgSend_750Ptr.asFunction< + late final __objc_msgSend_754 = __objc_msgSend_754Ptr.asFunction< bool Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); late final _sel_scanLongLong_1 = _registerName1("scanLongLong:"); - bool _objc_msgSend_751( + bool _objc_msgSend_755( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer result, ) { - return __objc_msgSend_751( + return __objc_msgSend_755( obj, sel, result, ); } - late final __objc_msgSend_751Ptr = _lookup< + late final __objc_msgSend_755Ptr = _lookup< ffi.NativeFunction< ffi.Bool Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_751 = __objc_msgSend_751Ptr.asFunction< + late final __objc_msgSend_755 = __objc_msgSend_755Ptr.asFunction< bool Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); late final _sel_scanUnsignedLongLong_1 = _registerName1("scanUnsignedLongLong:"); - bool _objc_msgSend_752( + bool _objc_msgSend_756( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer result, ) { - return __objc_msgSend_752( + return __objc_msgSend_756( obj, sel, result, ); } - late final __objc_msgSend_752Ptr = _lookup< + late final __objc_msgSend_756Ptr = _lookup< ffi.NativeFunction< ffi.Bool Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_752 = __objc_msgSend_752Ptr.asFunction< + late final __objc_msgSend_756 = __objc_msgSend_756Ptr.asFunction< bool Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); late final _sel_scanFloat_1 = _registerName1("scanFloat:"); - bool _objc_msgSend_753( + bool _objc_msgSend_757( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer result, ) { - return __objc_msgSend_753( + return __objc_msgSend_757( obj, sel, result, ); } - late final __objc_msgSend_753Ptr = _lookup< + late final __objc_msgSend_757Ptr = _lookup< ffi.NativeFunction< ffi.Bool Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_753 = __objc_msgSend_753Ptr.asFunction< + late final __objc_msgSend_757 = __objc_msgSend_757Ptr.asFunction< bool Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); late final _sel_scanDouble_1 = _registerName1("scanDouble:"); - bool _objc_msgSend_754( + bool _objc_msgSend_758( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer result, ) { - return __objc_msgSend_754( + return __objc_msgSend_758( obj, sel, result, ); } - late final __objc_msgSend_754Ptr = _lookup< + late final __objc_msgSend_758Ptr = _lookup< ffi.NativeFunction< ffi.Bool Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_754 = __objc_msgSend_754Ptr.asFunction< + late final __objc_msgSend_758 = __objc_msgSend_758Ptr.asFunction< bool Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); late final _sel_scanHexInt_1 = _registerName1("scanHexInt:"); - bool _objc_msgSend_755( + bool _objc_msgSend_759( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer result, ) { - return __objc_msgSend_755( + return __objc_msgSend_759( obj, sel, result, ); } - late final __objc_msgSend_755Ptr = _lookup< + late final __objc_msgSend_759Ptr = _lookup< ffi.NativeFunction< ffi.Bool Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_755 = __objc_msgSend_755Ptr.asFunction< + late final __objc_msgSend_759 = __objc_msgSend_759Ptr.asFunction< bool Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); @@ -21588,13 +21728,13 @@ class SentryCocoa { late final _sel_scanHexDouble_1 = _registerName1("scanHexDouble:"); late final _sel_scanString_intoString_1 = _registerName1("scanString:intoString:"); - bool _objc_msgSend_756( + bool _objc_msgSend_760( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer string, ffi.Pointer> result, ) { - return __objc_msgSend_756( + return __objc_msgSend_760( obj, sel, string, @@ -21602,26 +21742,26 @@ class SentryCocoa { ); } - late final __objc_msgSend_756Ptr = _lookup< + late final __objc_msgSend_760Ptr = _lookup< ffi.NativeFunction< ffi.Bool Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer>)>>('objc_msgSend'); - late final __objc_msgSend_756 = __objc_msgSend_756Ptr.asFunction< + late final __objc_msgSend_760 = __objc_msgSend_760Ptr.asFunction< bool Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer>)>(); late final _sel_scanCharactersFromSet_intoString_1 = _registerName1("scanCharactersFromSet:intoString:"); - bool _objc_msgSend_757( + bool _objc_msgSend_761( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer set1, ffi.Pointer> result, ) { - return __objc_msgSend_757( + return __objc_msgSend_761( obj, sel, set1, @@ -21629,14 +21769,14 @@ class SentryCocoa { ); } - late final __objc_msgSend_757Ptr = _lookup< + late final __objc_msgSend_761Ptr = _lookup< ffi.NativeFunction< ffi.Bool Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer>)>>('objc_msgSend'); - late final __objc_msgSend_757 = __objc_msgSend_757Ptr.asFunction< + late final __objc_msgSend_761 = __objc_msgSend_761Ptr.asFunction< bool Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer>)>(); @@ -21649,37 +21789,37 @@ class SentryCocoa { late final _sel_localizedScannerWithString_1 = _registerName1("localizedScannerWithString:"); late final _sel_scanDecimal_1 = _registerName1("scanDecimal:"); - bool _objc_msgSend_758( + bool _objc_msgSend_762( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer dcm, ) { - return __objc_msgSend_758( + return __objc_msgSend_762( obj, sel, dcm, ); } - late final __objc_msgSend_758Ptr = _lookup< + late final __objc_msgSend_762Ptr = _lookup< ffi.NativeFunction< ffi.Bool Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_758 = __objc_msgSend_758Ptr.asFunction< + late final __objc_msgSend_762 = __objc_msgSend_762Ptr.asFunction< bool Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); late final _class_NSException1 = _getClass1("NSException"); late final _sel_exceptionWithName_reason_userInfo_1 = _registerName1("exceptionWithName:reason:userInfo:"); - ffi.Pointer _objc_msgSend_759( + ffi.Pointer _objc_msgSend_763( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer name, ffi.Pointer reason, ffi.Pointer userInfo, ) { - return __objc_msgSend_759( + return __objc_msgSend_763( obj, sel, name, @@ -21688,7 +21828,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_759Ptr = _lookup< + late final __objc_msgSend_763Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, @@ -21696,7 +21836,7 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_759 = __objc_msgSend_759Ptr.asFunction< + late final __objc_msgSend_763 = __objc_msgSend_763Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, @@ -21711,14 +21851,14 @@ class SentryCocoa { late final _sel_raise_format_1 = _registerName1("raise:format:"); late final _sel_raise_format_arguments_1 = _registerName1("raise:format:arguments:"); - void _objc_msgSend_760( + void _objc_msgSend_764( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer name, ffi.Pointer format, - ffi.Pointer<__va_list_tag> argList, + ffi.Pointer argList, ) { - return __objc_msgSend_760( + return __objc_msgSend_764( obj, sel, name, @@ -21727,33 +21867,33 @@ class SentryCocoa { ); } - late final __objc_msgSend_760Ptr = _lookup< + late final __objc_msgSend_764Ptr = _lookup< ffi.NativeFunction< ffi.Void Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer, - ffi.Pointer<__va_list_tag>)>>('objc_msgSend'); - late final __objc_msgSend_760 = __objc_msgSend_760Ptr.asFunction< + ffi.Pointer)>>('objc_msgSend'); + late final __objc_msgSend_764 = __objc_msgSend_764Ptr.asFunction< void Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer, - ffi.Pointer<__va_list_tag>)>(); + ffi.Pointer)>(); late final _class_NSFileHandle1 = _getClass1("NSFileHandle"); late final _sel_availableData1 = _registerName1("availableData"); late final _sel_initWithFileDescriptor_closeOnDealloc_1 = _registerName1("initWithFileDescriptor:closeOnDealloc:"); - instancetype _objc_msgSend_761( + instancetype _objc_msgSend_765( ffi.Pointer obj, ffi.Pointer sel, int fd, bool closeopt, ) { - return __objc_msgSend_761( + return __objc_msgSend_765( obj, sel, fd, @@ -21761,47 +21901,47 @@ class SentryCocoa { ); } - late final __objc_msgSend_761Ptr = _lookup< + late final __objc_msgSend_765Ptr = _lookup< ffi.NativeFunction< instancetype Function(ffi.Pointer, ffi.Pointer, ffi.Int, ffi.Bool)>>('objc_msgSend'); - late final __objc_msgSend_761 = __objc_msgSend_761Ptr.asFunction< + late final __objc_msgSend_765 = __objc_msgSend_765Ptr.asFunction< instancetype Function( ffi.Pointer, ffi.Pointer, int, bool)>(); late final _sel_readDataToEndOfFileAndReturnError_1 = _registerName1("readDataToEndOfFileAndReturnError:"); - ffi.Pointer _objc_msgSend_762( + ffi.Pointer _objc_msgSend_766( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer> error, ) { - return __objc_msgSend_762( + return __objc_msgSend_766( obj, sel, error, ); } - late final __objc_msgSend_762Ptr = _lookup< + late final __objc_msgSend_766Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, ffi.Pointer>)>>('objc_msgSend'); - late final __objc_msgSend_762 = __objc_msgSend_762Ptr.asFunction< + late final __objc_msgSend_766 = __objc_msgSend_766Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer>)>(); late final _sel_readDataUpToLength_error_1 = _registerName1("readDataUpToLength:error:"); - ffi.Pointer _objc_msgSend_763( + ffi.Pointer _objc_msgSend_767( ffi.Pointer obj, ffi.Pointer sel, int length, ffi.Pointer> error, ) { - return __objc_msgSend_763( + return __objc_msgSend_767( obj, sel, length, @@ -21809,25 +21949,25 @@ class SentryCocoa { ); } - late final __objc_msgSend_763Ptr = _lookup< + late final __objc_msgSend_767Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, ffi.UnsignedLong, ffi.Pointer>)>>('objc_msgSend'); - late final __objc_msgSend_763 = __objc_msgSend_763Ptr.asFunction< + late final __objc_msgSend_767 = __objc_msgSend_767Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, int, ffi.Pointer>)>(); late final _sel_writeData_error_1 = _registerName1("writeData:error:"); - bool _objc_msgSend_764( + bool _objc_msgSend_768( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer data, ffi.Pointer> error, ) { - return __objc_msgSend_764( + return __objc_msgSend_768( obj, sel, data, @@ -21835,25 +21975,25 @@ class SentryCocoa { ); } - late final __objc_msgSend_764Ptr = _lookup< + late final __objc_msgSend_768Ptr = _lookup< ffi.NativeFunction< ffi.Bool Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer>)>>('objc_msgSend'); - late final __objc_msgSend_764 = __objc_msgSend_764Ptr.asFunction< + late final __objc_msgSend_768 = __objc_msgSend_768Ptr.asFunction< bool Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer>)>(); late final _sel_getOffset_error_1 = _registerName1("getOffset:error:"); - bool _objc_msgSend_765( + bool _objc_msgSend_769( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer offsetInFile, ffi.Pointer> error, ) { - return __objc_msgSend_765( + return __objc_msgSend_769( obj, sel, offsetInFile, @@ -21861,14 +22001,14 @@ class SentryCocoa { ); } - late final __objc_msgSend_765Ptr = _lookup< + late final __objc_msgSend_769Ptr = _lookup< ffi.NativeFunction< ffi.Bool Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer>)>>('objc_msgSend'); - late final __objc_msgSend_765 = __objc_msgSend_765Ptr.asFunction< + late final __objc_msgSend_769 = __objc_msgSend_769Ptr.asFunction< bool Function( ffi.Pointer, ffi.Pointer, @@ -21878,13 +22018,13 @@ class SentryCocoa { late final _sel_seekToEndReturningOffset_error_1 = _registerName1("seekToEndReturningOffset:error:"); late final _sel_seekToOffset_error_1 = _registerName1("seekToOffset:error:"); - bool _objc_msgSend_766( + bool _objc_msgSend_770( ffi.Pointer obj, ffi.Pointer sel, int offset, ffi.Pointer> error, ) { - return __objc_msgSend_766( + return __objc_msgSend_770( obj, sel, offset, @@ -21892,14 +22032,14 @@ class SentryCocoa { ); } - late final __objc_msgSend_766Ptr = _lookup< + late final __objc_msgSend_770Ptr = _lookup< ffi.NativeFunction< ffi.Bool Function( ffi.Pointer, ffi.Pointer, ffi.UnsignedLongLong, ffi.Pointer>)>>('objc_msgSend'); - late final __objc_msgSend_766 = __objc_msgSend_766Ptr.asFunction< + late final __objc_msgSend_770 = __objc_msgSend_770Ptr.asFunction< bool Function(ffi.Pointer, ffi.Pointer, int, ffi.Pointer>)>(); @@ -21911,21 +22051,21 @@ class SentryCocoa { _registerName1("closeAndReturnError:"); late final _sel_fileHandleWithStandardInput1 = _registerName1("fileHandleWithStandardInput"); - ffi.Pointer _objc_msgSend_767( + ffi.Pointer _objc_msgSend_771( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_767( + return __objc_msgSend_771( obj, sel, ); } - late final __objc_msgSend_767Ptr = _lookup< + late final __objc_msgSend_771Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_767 = __objc_msgSend_767Ptr.asFunction< + late final __objc_msgSend_771 = __objc_msgSend_771Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>(); @@ -21943,13 +22083,13 @@ class SentryCocoa { _registerName1("fileHandleForUpdatingAtPath:"); late final _sel_fileHandleForReadingFromURL_error_1 = _registerName1("fileHandleForReadingFromURL:error:"); - instancetype _objc_msgSend_768( + instancetype _objc_msgSend_772( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer url, ffi.Pointer> error, ) { - return __objc_msgSend_768( + return __objc_msgSend_772( obj, sel, url, @@ -21957,14 +22097,14 @@ class SentryCocoa { ); } - late final __objc_msgSend_768Ptr = _lookup< + late final __objc_msgSend_772Ptr = _lookup< ffi.NativeFunction< instancetype Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer>)>>('objc_msgSend'); - late final __objc_msgSend_768 = __objc_msgSend_768Ptr.asFunction< + late final __objc_msgSend_772 = __objc_msgSend_772Ptr.asFunction< instancetype Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer>)>(); @@ -21989,43 +22129,43 @@ class SentryCocoa { late final _sel_waitForDataInBackgroundAndNotify1 = _registerName1("waitForDataInBackgroundAndNotify"); late final _sel_readabilityHandler1 = _registerName1("readabilityHandler"); - ffi.Pointer<_ObjCBlock> _objc_msgSend_769( + ffi.Pointer<_ObjCBlock> _objc_msgSend_773( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_769( + return __objc_msgSend_773( obj, sel, ); } - late final __objc_msgSend_769Ptr = _lookup< + late final __objc_msgSend_773Ptr = _lookup< ffi.NativeFunction< ffi.Pointer<_ObjCBlock> Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_769 = __objc_msgSend_769Ptr.asFunction< + late final __objc_msgSend_773 = __objc_msgSend_773Ptr.asFunction< ffi.Pointer<_ObjCBlock> Function( ffi.Pointer, ffi.Pointer)>(); late final _sel_setReadabilityHandler_1 = _registerName1("setReadabilityHandler:"); - void _objc_msgSend_770( + void _objc_msgSend_774( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer<_ObjCBlock> value, ) { - return __objc_msgSend_770( + return __objc_msgSend_774( obj, sel, value, ); } - late final __objc_msgSend_770Ptr = _lookup< + late final __objc_msgSend_774Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer<_ObjCBlock>)>>('objc_msgSend'); - late final __objc_msgSend_770 = __objc_msgSend_770Ptr.asFunction< + late final __objc_msgSend_774 = __objc_msgSend_774Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer<_ObjCBlock>)>(); @@ -22034,23 +22174,23 @@ class SentryCocoa { _registerName1("setWriteabilityHandler:"); late final _sel_initWithFileDescriptor_1 = _registerName1("initWithFileDescriptor:"); - instancetype _objc_msgSend_771( + instancetype _objc_msgSend_775( ffi.Pointer obj, ffi.Pointer sel, int fd, ) { - return __objc_msgSend_771( + return __objc_msgSend_775( obj, sel, fd, ); } - late final __objc_msgSend_771Ptr = _lookup< + late final __objc_msgSend_775Ptr = _lookup< ffi.NativeFunction< instancetype Function(ffi.Pointer, ffi.Pointer, ffi.Int)>>('objc_msgSend'); - late final __objc_msgSend_771 = __objc_msgSend_771Ptr.asFunction< + late final __objc_msgSend_775 = __objc_msgSend_775Ptr.asFunction< instancetype Function( ffi.Pointer, ffi.Pointer, int)>(); @@ -22060,23 +22200,23 @@ class SentryCocoa { late final _sel_offsetInFile1 = _registerName1("offsetInFile"); late final _sel_seekToEndOfFile1 = _registerName1("seekToEndOfFile"); late final _sel_seekToFileOffset_1 = _registerName1("seekToFileOffset:"); - void _objc_msgSend_772( + void _objc_msgSend_776( ffi.Pointer obj, ffi.Pointer sel, int offset, ) { - return __objc_msgSend_772( + return __objc_msgSend_776( obj, sel, offset, ); } - late final __objc_msgSend_772Ptr = _lookup< + late final __objc_msgSend_776Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.UnsignedLongLong)>>('objc_msgSend'); - late final __objc_msgSend_772 = __objc_msgSend_772Ptr.asFunction< + late final __objc_msgSend_776 = __objc_msgSend_776Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, int)>(); late final _sel_truncateFileAtOffset_1 = @@ -22086,43 +22226,43 @@ class SentryCocoa { late final _class_NSHTTPCookieStorage1 = _getClass1("NSHTTPCookieStorage"); late final _sel_sharedHTTPCookieStorage1 = _registerName1("sharedHTTPCookieStorage"); - ffi.Pointer _objc_msgSend_773( + ffi.Pointer _objc_msgSend_777( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_773( + return __objc_msgSend_777( obj, sel, ); } - late final __objc_msgSend_773Ptr = _lookup< + late final __objc_msgSend_777Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_773 = __objc_msgSend_773Ptr.asFunction< + late final __objc_msgSend_777 = __objc_msgSend_777Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>(); late final _sel_sharedCookieStorageForGroupContainerIdentifier_1 = _registerName1("sharedCookieStorageForGroupContainerIdentifier:"); - ffi.Pointer _objc_msgSend_774( + ffi.Pointer _objc_msgSend_778( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer identifier, ) { - return __objc_msgSend_774( + return __objc_msgSend_778( obj, sel, identifier, ); } - late final __objc_msgSend_774Ptr = _lookup< + late final __objc_msgSend_778Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_774 = __objc_msgSend_774Ptr.asFunction< + late final __objc_msgSend_778 = __objc_msgSend_778Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); @@ -22131,23 +22271,23 @@ class SentryCocoa { late final _sel_initWithProperties_1 = _registerName1("initWithProperties:"); late final _sel_cookieWithProperties_1 = _registerName1("cookieWithProperties:"); - ffi.Pointer _objc_msgSend_775( + ffi.Pointer _objc_msgSend_779( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer properties, ) { - return __objc_msgSend_775( + return __objc_msgSend_779( obj, sel, properties, ); } - late final __objc_msgSend_775Ptr = _lookup< + late final __objc_msgSend_779Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_775 = __objc_msgSend_775Ptr.asFunction< + late final __objc_msgSend_779 = __objc_msgSend_779Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); @@ -22155,13 +22295,13 @@ class SentryCocoa { _registerName1("requestHeaderFieldsWithCookies:"); late final _sel_cookiesWithResponseHeaderFields_forURL_1 = _registerName1("cookiesWithResponseHeaderFields:forURL:"); - ffi.Pointer _objc_msgSend_776( + ffi.Pointer _objc_msgSend_780( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer headerFields, ffi.Pointer URL, ) { - return __objc_msgSend_776( + return __objc_msgSend_780( obj, sel, headerFields, @@ -22169,14 +22309,14 @@ class SentryCocoa { ); } - late final __objc_msgSend_776Ptr = _lookup< + late final __objc_msgSend_780Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_776 = __objc_msgSend_776Ptr.asFunction< + late final __objc_msgSend_780 = __objc_msgSend_780Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, @@ -22194,23 +22334,23 @@ class SentryCocoa { late final _sel_portList1 = _registerName1("portList"); late final _sel_sameSitePolicy1 = _registerName1("sameSitePolicy"); late final _sel_setCookie_1 = _registerName1("setCookie:"); - void _objc_msgSend_777( + void _objc_msgSend_781( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer cookie, ) { - return __objc_msgSend_777( + return __objc_msgSend_781( obj, sel, cookie, ); } - late final __objc_msgSend_777Ptr = _lookup< + late final __objc_msgSend_781Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_777 = __objc_msgSend_777Ptr.asFunction< + late final __objc_msgSend_781 = __objc_msgSend_781Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); @@ -22220,14 +22360,14 @@ class SentryCocoa { late final _sel_cookiesForURL_1 = _registerName1("cookiesForURL:"); late final _sel_setCookies_forURL_mainDocumentURL_1 = _registerName1("setCookies:forURL:mainDocumentURL:"); - void _objc_msgSend_778( + void _objc_msgSend_782( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer cookies, ffi.Pointer URL, ffi.Pointer mainDocumentURL, ) { - return __objc_msgSend_778( + return __objc_msgSend_782( obj, sel, cookies, @@ -22236,7 +22376,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_778Ptr = _lookup< + late final __objc_msgSend_782Ptr = _lookup< ffi.NativeFunction< ffi.Void Function( ffi.Pointer, @@ -22244,7 +22384,7 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_778 = __objc_msgSend_778Ptr.asFunction< + late final __objc_msgSend_782 = __objc_msgSend_782Ptr.asFunction< void Function( ffi.Pointer, ffi.Pointer, @@ -22253,42 +22393,42 @@ class SentryCocoa { ffi.Pointer)>(); late final _sel_cookieAcceptPolicy1 = _registerName1("cookieAcceptPolicy"); - int _objc_msgSend_779( + int _objc_msgSend_783( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_779( + return __objc_msgSend_783( obj, sel, ); } - late final __objc_msgSend_779Ptr = _lookup< + late final __objc_msgSend_783Ptr = _lookup< ffi.NativeFunction< ffi.Int32 Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_779 = __objc_msgSend_779Ptr.asFunction< + late final __objc_msgSend_783 = __objc_msgSend_783Ptr.asFunction< int Function(ffi.Pointer, ffi.Pointer)>(); late final _sel_setCookieAcceptPolicy_1 = _registerName1("setCookieAcceptPolicy:"); - void _objc_msgSend_780( + void _objc_msgSend_784( ffi.Pointer obj, ffi.Pointer sel, int value, ) { - return __objc_msgSend_780( + return __objc_msgSend_784( obj, sel, value, ); } - late final __objc_msgSend_780Ptr = _lookup< + late final __objc_msgSend_784Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Int32)>>('objc_msgSend'); - late final __objc_msgSend_780 = __objc_msgSend_780Ptr.asFunction< + late final __objc_msgSend_784 = __objc_msgSend_784Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, int)>(); late final _sel_sortedCookiesUsingDescriptors_1 = @@ -22301,14 +22441,14 @@ class SentryCocoa { _registerName1("supportsSecureCoding"); late final _sel_requestWithURL_cachePolicy_timeoutInterval_1 = _registerName1("requestWithURL:cachePolicy:timeoutInterval:"); - instancetype _objc_msgSend_781( + instancetype _objc_msgSend_785( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer URL, int cachePolicy, double timeoutInterval, ) { - return __objc_msgSend_781( + return __objc_msgSend_785( obj, sel, URL, @@ -22317,11 +22457,11 @@ class SentryCocoa { ); } - late final __objc_msgSend_781Ptr = _lookup< + late final __objc_msgSend_785Ptr = _lookup< ffi.NativeFunction< instancetype Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Int32, ffi.Double)>>('objc_msgSend'); - late final __objc_msgSend_781 = __objc_msgSend_781Ptr.asFunction< + late final __objc_msgSend_785 = __objc_msgSend_785Ptr.asFunction< instancetype Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, int, double)>(); @@ -22329,41 +22469,41 @@ class SentryCocoa { _registerName1("initWithURL:cachePolicy:timeoutInterval:"); late final _sel_URL1 = _registerName1("URL"); late final _sel_cachePolicy1 = _registerName1("cachePolicy"); - int _objc_msgSend_782( + int _objc_msgSend_786( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_782( + return __objc_msgSend_786( obj, sel, ); } - late final __objc_msgSend_782Ptr = _lookup< + late final __objc_msgSend_786Ptr = _lookup< ffi.NativeFunction< ffi.Int32 Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_782 = __objc_msgSend_782Ptr.asFunction< + late final __objc_msgSend_786 = __objc_msgSend_786Ptr.asFunction< int Function(ffi.Pointer, ffi.Pointer)>(); late final _sel_timeoutInterval1 = _registerName1("timeoutInterval"); late final _sel_mainDocumentURL1 = _registerName1("mainDocumentURL"); late final _sel_networkServiceType1 = _registerName1("networkServiceType"); - int _objc_msgSend_783( + int _objc_msgSend_787( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_783( + return __objc_msgSend_787( obj, sel, ); } - late final __objc_msgSend_783Ptr = _lookup< + late final __objc_msgSend_787Ptr = _lookup< ffi.NativeFunction< ffi.Int32 Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_783 = __objc_msgSend_783Ptr.asFunction< + late final __objc_msgSend_787 = __objc_msgSend_787Ptr.asFunction< int Function(ffi.Pointer, ffi.Pointer)>(); late final _sel_allowsCellularAccess1 = @@ -22374,21 +22514,21 @@ class SentryCocoa { _registerName1("allowsConstrainedNetworkAccess"); late final _sel_assumesHTTP3Capable1 = _registerName1("assumesHTTP3Capable"); late final _sel_attribution1 = _registerName1("attribution"); - int _objc_msgSend_784( + int _objc_msgSend_788( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_784( + return __objc_msgSend_788( obj, sel, ); } - late final __objc_msgSend_784Ptr = _lookup< + late final __objc_msgSend_788Ptr = _lookup< ffi.NativeFunction< ffi.Int32 Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_784 = __objc_msgSend_784Ptr.asFunction< + late final __objc_msgSend_788 = __objc_msgSend_788Ptr.asFunction< int Function(ffi.Pointer, ffi.Pointer)>(); late final _sel_requiresDNSSECValidation1 = @@ -22403,33 +22543,33 @@ class SentryCocoa { late final _sel_open1 = _registerName1("open"); late final _sel_close1 = _registerName1("close"); late final _sel_streamStatus1 = _registerName1("streamStatus"); - int _objc_msgSend_785( + int _objc_msgSend_789( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_785( + return __objc_msgSend_789( obj, sel, ); } - late final __objc_msgSend_785Ptr = _lookup< + late final __objc_msgSend_789Ptr = _lookup< ffi.NativeFunction< ffi.Int32 Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_785 = __objc_msgSend_785Ptr.asFunction< + late final __objc_msgSend_789 = __objc_msgSend_789Ptr.asFunction< int Function(ffi.Pointer, ffi.Pointer)>(); late final _sel_streamError1 = _registerName1("streamError"); late final _class_NSOutputStream1 = _getClass1("NSOutputStream"); late final _sel_write_maxLength_1 = _registerName1("write:maxLength:"); - int _objc_msgSend_786( + int _objc_msgSend_790( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer buffer, int len, ) { - return __objc_msgSend_786( + return __objc_msgSend_790( obj, sel, buffer, @@ -22437,11 +22577,11 @@ class SentryCocoa { ); } - late final __objc_msgSend_786Ptr = _lookup< + late final __objc_msgSend_790Ptr = _lookup< ffi.NativeFunction< ffi.Long Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.UnsignedLong)>>('objc_msgSend'); - late final __objc_msgSend_786 = __objc_msgSend_786Ptr.asFunction< + late final __objc_msgSend_790 = __objc_msgSend_790Ptr.asFunction< int Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, int)>(); @@ -22449,13 +22589,13 @@ class SentryCocoa { late final _sel_initToMemory1 = _registerName1("initToMemory"); late final _sel_initToBuffer_capacity_1 = _registerName1("initToBuffer:capacity:"); - instancetype _objc_msgSend_787( + instancetype _objc_msgSend_791( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer buffer, int capacity, ) { - return __objc_msgSend_787( + return __objc_msgSend_791( obj, sel, buffer, @@ -22463,11 +22603,11 @@ class SentryCocoa { ); } - late final __objc_msgSend_787Ptr = _lookup< + late final __objc_msgSend_791Ptr = _lookup< ffi.NativeFunction< instancetype Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.UnsignedLong)>>('objc_msgSend'); - late final __objc_msgSend_787 = __objc_msgSend_787Ptr.asFunction< + late final __objc_msgSend_791 = __objc_msgSend_791Ptr.asFunction< instancetype Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, int)>(); @@ -22484,7 +22624,7 @@ class SentryCocoa { _registerName1("outputStreamWithURL:append:"); late final _sel_getStreamsToHostWithName_port_inputStream_outputStream_1 = _registerName1("getStreamsToHostWithName:port:inputStream:outputStream:"); - void _objc_msgSend_788( + void _objc_msgSend_792( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer hostname, @@ -22492,7 +22632,7 @@ class SentryCocoa { ffi.Pointer> inputStream, ffi.Pointer> outputStream, ) { - return __objc_msgSend_788( + return __objc_msgSend_792( obj, sel, hostname, @@ -22502,7 +22642,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_788Ptr = _lookup< + late final __objc_msgSend_792Ptr = _lookup< ffi.NativeFunction< ffi.Void Function( ffi.Pointer, @@ -22511,7 +22651,7 @@ class SentryCocoa { ffi.Long, ffi.Pointer>, ffi.Pointer>)>>('objc_msgSend'); - late final __objc_msgSend_788 = __objc_msgSend_788Ptr.asFunction< + late final __objc_msgSend_792 = __objc_msgSend_792Ptr.asFunction< void Function( ffi.Pointer, ffi.Pointer, @@ -22525,23 +22665,23 @@ class SentryCocoa { late final _sel_hostWithName_1 = _registerName1("hostWithName:"); late final _sel_hostWithAddress_1 = _registerName1("hostWithAddress:"); late final _sel_isEqualToHost_1 = _registerName1("isEqualToHost:"); - bool _objc_msgSend_789( + bool _objc_msgSend_793( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer aHost, ) { - return __objc_msgSend_789( + return __objc_msgSend_793( obj, sel, aHost, ); } - late final __objc_msgSend_789Ptr = _lookup< + late final __objc_msgSend_793Ptr = _lookup< ffi.NativeFunction< ffi.Bool Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_789 = __objc_msgSend_789Ptr.asFunction< + late final __objc_msgSend_793 = __objc_msgSend_793Ptr.asFunction< bool Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); @@ -22551,30 +22691,30 @@ class SentryCocoa { late final _sel_localizedName1 = _registerName1("localizedName"); late final _sel_setHostCacheEnabled_1 = _registerName1("setHostCacheEnabled:"); - void _objc_msgSend_790( + void _objc_msgSend_794( ffi.Pointer obj, ffi.Pointer sel, bool flag, ) { - return __objc_msgSend_790( + return __objc_msgSend_794( obj, sel, flag, ); } - late final __objc_msgSend_790Ptr = _lookup< + late final __objc_msgSend_794Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Bool)>>('objc_msgSend'); - late final __objc_msgSend_790 = __objc_msgSend_790Ptr.asFunction< + late final __objc_msgSend_794 = __objc_msgSend_794Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, bool)>(); late final _sel_isHostCacheEnabled1 = _registerName1("isHostCacheEnabled"); late final _sel_flushHostCache1 = _registerName1("flushHostCache"); late final _sel_getStreamsToHost_port_inputStream_outputStream_1 = _registerName1("getStreamsToHost:port:inputStream:outputStream:"); - void _objc_msgSend_791( + void _objc_msgSend_795( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer host, @@ -22582,7 +22722,7 @@ class SentryCocoa { ffi.Pointer> inputStream, ffi.Pointer> outputStream, ) { - return __objc_msgSend_791( + return __objc_msgSend_795( obj, sel, host, @@ -22592,7 +22732,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_791Ptr = _lookup< + late final __objc_msgSend_795Ptr = _lookup< ffi.NativeFunction< ffi.Void Function( ffi.Pointer, @@ -22601,7 +22741,7 @@ class SentryCocoa { ffi.Long, ffi.Pointer>, ffi.Pointer>)>>('objc_msgSend'); - late final __objc_msgSend_791 = __objc_msgSend_791Ptr.asFunction< + late final __objc_msgSend_795 = __objc_msgSend_795Ptr.asFunction< void Function( ffi.Pointer, ffi.Pointer, @@ -22612,14 +22752,14 @@ class SentryCocoa { late final _sel_getBoundStreamsWithBufferSize_inputStream_outputStream_1 = _registerName1("getBoundStreamsWithBufferSize:inputStream:outputStream:"); - void _objc_msgSend_792( + void _objc_msgSend_796( ffi.Pointer obj, ffi.Pointer sel, int bufferSize, ffi.Pointer> inputStream, ffi.Pointer> outputStream, ) { - return __objc_msgSend_792( + return __objc_msgSend_796( obj, sel, bufferSize, @@ -22628,7 +22768,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_792Ptr = _lookup< + late final __objc_msgSend_796Ptr = _lookup< ffi.NativeFunction< ffi.Void Function( ffi.Pointer, @@ -22636,7 +22776,7 @@ class SentryCocoa { ffi.UnsignedLong, ffi.Pointer>, ffi.Pointer>)>>('objc_msgSend'); - late final __objc_msgSend_792 = __objc_msgSend_792Ptr.asFunction< + late final __objc_msgSend_796 = __objc_msgSend_796Ptr.asFunction< void Function( ffi.Pointer, ffi.Pointer, @@ -22646,13 +22786,13 @@ class SentryCocoa { late final _sel_read_maxLength_1 = _registerName1("read:maxLength:"); late final _sel_getBuffer_length_1 = _registerName1("getBuffer:length:"); - bool _objc_msgSend_793( + bool _objc_msgSend_797( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer> buffer, ffi.Pointer len, ) { - return __objc_msgSend_793( + return __objc_msgSend_797( obj, sel, buffer, @@ -22660,14 +22800,14 @@ class SentryCocoa { ); } - late final __objc_msgSend_793Ptr = _lookup< + late final __objc_msgSend_797Ptr = _lookup< ffi.NativeFunction< ffi.Bool Function( ffi.Pointer, ffi.Pointer, ffi.Pointer>, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_793 = __objc_msgSend_793Ptr.asFunction< + late final __objc_msgSend_797 = __objc_msgSend_797Ptr.asFunction< bool Function( ffi.Pointer, ffi.Pointer, @@ -22682,21 +22822,21 @@ class SentryCocoa { _registerName1("inputStreamWithFileAtPath:"); late final _sel_inputStreamWithURL_1 = _registerName1("inputStreamWithURL:"); late final _sel_HTTPBodyStream1 = _registerName1("HTTPBodyStream"); - ffi.Pointer _objc_msgSend_794( + ffi.Pointer _objc_msgSend_798( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_794( + return __objc_msgSend_798( obj, sel, ); } - late final __objc_msgSend_794Ptr = _lookup< + late final __objc_msgSend_798Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_794 = __objc_msgSend_794Ptr.asFunction< + late final __objc_msgSend_798 = __objc_msgSend_798Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>(); @@ -22705,21 +22845,21 @@ class SentryCocoa { late final _sel_HTTPShouldUsePipelining1 = _registerName1("HTTPShouldUsePipelining"); late final _sel_originalRequest1 = _registerName1("originalRequest"); - ffi.Pointer _objc_msgSend_795( + ffi.Pointer _objc_msgSend_799( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_795( + return __objc_msgSend_799( obj, sel, ); } - late final __objc_msgSend_795Ptr = _lookup< + late final __objc_msgSend_799Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_795 = __objc_msgSend_795Ptr.asFunction< + late final __objc_msgSend_799 = __objc_msgSend_799Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>(); @@ -22728,7 +22868,7 @@ class SentryCocoa { late final _sel_initWithURL_MIMEType_expectedContentLength_textEncodingName_1 = _registerName1( "initWithURL:MIMEType:expectedContentLength:textEncodingName:"); - instancetype _objc_msgSend_796( + instancetype _objc_msgSend_800( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer URL, @@ -22736,7 +22876,7 @@ class SentryCocoa { int length, ffi.Pointer name, ) { - return __objc_msgSend_796( + return __objc_msgSend_800( obj, sel, URL, @@ -22746,7 +22886,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_796Ptr = _lookup< + late final __objc_msgSend_800Ptr = _lookup< ffi.NativeFunction< instancetype Function( ffi.Pointer, @@ -22755,7 +22895,7 @@ class SentryCocoa { ffi.Pointer, ffi.Long, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_796 = __objc_msgSend_796Ptr.asFunction< + late final __objc_msgSend_800 = __objc_msgSend_800Ptr.asFunction< instancetype Function( ffi.Pointer, ffi.Pointer, @@ -22770,21 +22910,21 @@ class SentryCocoa { late final _sel_textEncodingName1 = _registerName1("textEncodingName"); late final _sel_suggestedFilename1 = _registerName1("suggestedFilename"); late final _sel_response1 = _registerName1("response"); - ffi.Pointer _objc_msgSend_797( + ffi.Pointer _objc_msgSend_801( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_797( + return __objc_msgSend_801( obj, sel, ); } - late final __objc_msgSend_797Ptr = _lookup< + late final __objc_msgSend_801Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_797 = __objc_msgSend_797Ptr.asFunction< + late final __objc_msgSend_801 = __objc_msgSend_801Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>(); @@ -22810,43 +22950,43 @@ class SentryCocoa { late final _sel_taskDescription1 = _registerName1("taskDescription"); late final _sel_setTaskDescription_1 = _registerName1("setTaskDescription:"); late final _sel_state1 = _registerName1("state"); - int _objc_msgSend_798( + int _objc_msgSend_802( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_798( + return __objc_msgSend_802( obj, sel, ); } - late final __objc_msgSend_798Ptr = _lookup< + late final __objc_msgSend_802Ptr = _lookup< ffi.NativeFunction< ffi.Int32 Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_798 = __objc_msgSend_798Ptr.asFunction< + late final __objc_msgSend_802 = __objc_msgSend_802Ptr.asFunction< int Function(ffi.Pointer, ffi.Pointer)>(); late final _sel_suspend1 = _registerName1("suspend"); late final _sel_priority1 = _registerName1("priority"); late final _sel_setPriority_1 = _registerName1("setPriority:"); - void _objc_msgSend_799( + void _objc_msgSend_803( ffi.Pointer obj, ffi.Pointer sel, double value, ) { - return __objc_msgSend_799( + return __objc_msgSend_803( obj, sel, value, ); } - late final __objc_msgSend_799Ptr = _lookup< + late final __objc_msgSend_803Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Float)>>('objc_msgSend'); - late final __objc_msgSend_799 = __objc_msgSend_799Ptr.asFunction< + late final __objc_msgSend_803 = __objc_msgSend_803Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, double)>(); late final _sel_prefersIncrementalDelivery1 = @@ -22855,13 +22995,13 @@ class SentryCocoa { _registerName1("setPrefersIncrementalDelivery:"); late final _sel_storeCookies_forTask_1 = _registerName1("storeCookies:forTask:"); - void _objc_msgSend_800( + void _objc_msgSend_804( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer cookies, ffi.Pointer task, ) { - return __objc_msgSend_800( + return __objc_msgSend_804( obj, sel, cookies, @@ -22869,26 +23009,26 @@ class SentryCocoa { ); } - late final __objc_msgSend_800Ptr = _lookup< + late final __objc_msgSend_804Ptr = _lookup< ffi.NativeFunction< ffi.Void Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_800 = __objc_msgSend_800Ptr.asFunction< + late final __objc_msgSend_804 = __objc_msgSend_804Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); late final _sel_getCookiesForTask_completionHandler_1 = _registerName1("getCookiesForTask:completionHandler:"); - void _objc_msgSend_801( + void _objc_msgSend_805( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer task, ffi.Pointer<_ObjCBlock> completionHandler, ) { - return __objc_msgSend_801( + return __objc_msgSend_805( obj, sel, task, @@ -22896,14 +23036,14 @@ class SentryCocoa { ); } - late final __objc_msgSend_801Ptr = _lookup< + late final __objc_msgSend_805Ptr = _lookup< ffi.NativeFunction< ffi.Void Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer<_ObjCBlock>)>>('objc_msgSend'); - late final __objc_msgSend_801 = __objc_msgSend_801Ptr.asFunction< + late final __objc_msgSend_805 = __objc_msgSend_805Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer<_ObjCBlock>)>(); @@ -22911,13 +23051,13 @@ class SentryCocoa { late final _sel_indexPathWithIndex_1 = _registerName1("indexPathWithIndex:"); late final _sel_indexPathWithIndexes_length_1 = _registerName1("indexPathWithIndexes:length:"); - instancetype _objc_msgSend_802( + instancetype _objc_msgSend_806( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer indexes, int length, ) { - return __objc_msgSend_802( + return __objc_msgSend_806( obj, sel, indexes, @@ -22925,14 +23065,14 @@ class SentryCocoa { ); } - late final __objc_msgSend_802Ptr = _lookup< + late final __objc_msgSend_806Ptr = _lookup< ffi.NativeFunction< instancetype Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.UnsignedLong)>>('objc_msgSend'); - late final __objc_msgSend_802 = __objc_msgSend_802Ptr.asFunction< + late final __objc_msgSend_806 = __objc_msgSend_806Ptr.asFunction< instancetype Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, int)>(); @@ -22940,55 +23080,55 @@ class SentryCocoa { _registerName1("initWithIndexes:length:"); late final _sel_indexPathByAddingIndex_1 = _registerName1("indexPathByAddingIndex:"); - ffi.Pointer _objc_msgSend_803( + ffi.Pointer _objc_msgSend_807( ffi.Pointer obj, ffi.Pointer sel, int index, ) { - return __objc_msgSend_803( + return __objc_msgSend_807( obj, sel, index, ); } - late final __objc_msgSend_803Ptr = _lookup< + late final __objc_msgSend_807Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.UnsignedLong)>>('objc_msgSend'); - late final __objc_msgSend_803 = __objc_msgSend_803Ptr.asFunction< + late final __objc_msgSend_807 = __objc_msgSend_807Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, int)>(); late final _sel_indexPathByRemovingLastIndex1 = _registerName1("indexPathByRemovingLastIndex"); - ffi.Pointer _objc_msgSend_804( + ffi.Pointer _objc_msgSend_808( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_804( + return __objc_msgSend_808( obj, sel, ); } - late final __objc_msgSend_804Ptr = _lookup< + late final __objc_msgSend_808Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_804 = __objc_msgSend_804Ptr.asFunction< + late final __objc_msgSend_808 = __objc_msgSend_808Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>(); late final _sel_indexAtPosition_1 = _registerName1("indexAtPosition:"); late final _sel_getIndexes_range_1 = _registerName1("getIndexes:range:"); - void _objc_msgSend_805( + void _objc_msgSend_809( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer indexes, _NSRange positionRange, ) { - return __objc_msgSend_805( + return __objc_msgSend_809( obj, sel, indexes, @@ -22996,72 +23136,72 @@ class SentryCocoa { ); } - late final __objc_msgSend_805Ptr = _lookup< + late final __objc_msgSend_809Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, _NSRange)>>('objc_msgSend'); - late final __objc_msgSend_805 = __objc_msgSend_805Ptr.asFunction< + late final __objc_msgSend_809 = __objc_msgSend_809Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, _NSRange)>(); - int _objc_msgSend_806( + int _objc_msgSend_810( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer otherObject, ) { - return __objc_msgSend_806( + return __objc_msgSend_810( obj, sel, otherObject, ); } - late final __objc_msgSend_806Ptr = _lookup< + late final __objc_msgSend_810Ptr = _lookup< ffi.NativeFunction< ffi.Int32 Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_806 = __objc_msgSend_806Ptr.asFunction< + late final __objc_msgSend_810 = __objc_msgSend_810Ptr.asFunction< int Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); late final _sel_getIndexes_1 = _registerName1("getIndexes:"); - void _objc_msgSend_807( + void _objc_msgSend_811( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer indexes, ) { - return __objc_msgSend_807( + return __objc_msgSend_811( obj, sel, indexes, ); } - late final __objc_msgSend_807Ptr = _lookup< + late final __objc_msgSend_811Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_807 = __objc_msgSend_807Ptr.asFunction< + late final __objc_msgSend_811 = __objc_msgSend_811Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); late final _class_NSInflectionRule1 = _getClass1("NSInflectionRule"); late final _sel_automaticRule1 = _registerName1("automaticRule"); - ffi.Pointer _objc_msgSend_808( + ffi.Pointer _objc_msgSend_812( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_808( + return __objc_msgSend_812( obj, sel, ); } - late final __objc_msgSend_808Ptr = _lookup< + late final __objc_msgSend_812Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_808 = __objc_msgSend_808Ptr.asFunction< + late final __objc_msgSend_812 = __objc_msgSend_812Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>(); @@ -23070,118 +23210,309 @@ class SentryCocoa { _registerName1("canInflectPreferredLocalization"); late final _class_NSMorphology1 = _getClass1("NSMorphology"); late final _sel_grammaticalGender1 = _registerName1("grammaticalGender"); - int _objc_msgSend_809( + int _objc_msgSend_813( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_809( + return __objc_msgSend_813( obj, sel, ); } - late final __objc_msgSend_809Ptr = _lookup< + late final __objc_msgSend_813Ptr = _lookup< ffi.NativeFunction< ffi.Int32 Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_809 = __objc_msgSend_809Ptr.asFunction< + late final __objc_msgSend_813 = __objc_msgSend_813Ptr.asFunction< int Function(ffi.Pointer, ffi.Pointer)>(); late final _sel_setGrammaticalGender_1 = _registerName1("setGrammaticalGender:"); - void _objc_msgSend_810( + void _objc_msgSend_814( ffi.Pointer obj, ffi.Pointer sel, int value, ) { - return __objc_msgSend_810( + return __objc_msgSend_814( obj, sel, value, ); } - late final __objc_msgSend_810Ptr = _lookup< + late final __objc_msgSend_814Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Int32)>>('objc_msgSend'); - late final __objc_msgSend_810 = __objc_msgSend_810Ptr.asFunction< + late final __objc_msgSend_814 = __objc_msgSend_814Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, int)>(); late final _sel_partOfSpeech1 = _registerName1("partOfSpeech"); - int _objc_msgSend_811( + int _objc_msgSend_815( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_811( + return __objc_msgSend_815( obj, sel, ); } - late final __objc_msgSend_811Ptr = _lookup< + late final __objc_msgSend_815Ptr = _lookup< ffi.NativeFunction< ffi.Int32 Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_811 = __objc_msgSend_811Ptr.asFunction< + late final __objc_msgSend_815 = __objc_msgSend_815Ptr.asFunction< int Function(ffi.Pointer, ffi.Pointer)>(); late final _sel_setPartOfSpeech_1 = _registerName1("setPartOfSpeech:"); - void _objc_msgSend_812( + void _objc_msgSend_816( ffi.Pointer obj, ffi.Pointer sel, int value, ) { - return __objc_msgSend_812( + return __objc_msgSend_816( obj, sel, value, ); } - late final __objc_msgSend_812Ptr = _lookup< + late final __objc_msgSend_816Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Int32)>>('objc_msgSend'); - late final __objc_msgSend_812 = __objc_msgSend_812Ptr.asFunction< + late final __objc_msgSend_816 = __objc_msgSend_816Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, int)>(); late final _sel_number1 = _registerName1("number"); - int _objc_msgSend_813( + int _objc_msgSend_817( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_813( + return __objc_msgSend_817( obj, sel, ); } - late final __objc_msgSend_813Ptr = _lookup< + late final __objc_msgSend_817Ptr = _lookup< ffi.NativeFunction< ffi.Int32 Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_813 = __objc_msgSend_813Ptr.asFunction< + late final __objc_msgSend_817 = __objc_msgSend_817Ptr.asFunction< int Function(ffi.Pointer, ffi.Pointer)>(); late final _sel_setNumber_1 = _registerName1("setNumber:"); - void _objc_msgSend_814( + void _objc_msgSend_818( ffi.Pointer obj, ffi.Pointer sel, int value, ) { - return __objc_msgSend_814( + return __objc_msgSend_818( obj, sel, value, ); } - late final __objc_msgSend_814Ptr = _lookup< + late final __objc_msgSend_818Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Int32)>>('objc_msgSend'); - late final __objc_msgSend_814 = __objc_msgSend_814Ptr.asFunction< + late final __objc_msgSend_818 = __objc_msgSend_818Ptr.asFunction< + void Function(ffi.Pointer, ffi.Pointer, int)>(); + + late final _sel_grammaticalCase1 = _registerName1("grammaticalCase"); + int _objc_msgSend_819( + ffi.Pointer obj, + ffi.Pointer sel, + ) { + return __objc_msgSend_819( + obj, + sel, + ); + } + + late final __objc_msgSend_819Ptr = _lookup< + ffi.NativeFunction< + ffi.Int32 Function( + ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); + late final __objc_msgSend_819 = __objc_msgSend_819Ptr.asFunction< + int Function(ffi.Pointer, ffi.Pointer)>(); + + late final _sel_setGrammaticalCase_1 = _registerName1("setGrammaticalCase:"); + void _objc_msgSend_820( + ffi.Pointer obj, + ffi.Pointer sel, + int value, + ) { + return __objc_msgSend_820( + obj, + sel, + value, + ); + } + + late final __objc_msgSend_820Ptr = _lookup< + ffi.NativeFunction< + ffi.Void Function(ffi.Pointer, ffi.Pointer, + ffi.Int32)>>('objc_msgSend'); + late final __objc_msgSend_820 = __objc_msgSend_820Ptr.asFunction< + void Function(ffi.Pointer, ffi.Pointer, int)>(); + + late final _sel_determination1 = _registerName1("determination"); + int _objc_msgSend_821( + ffi.Pointer obj, + ffi.Pointer sel, + ) { + return __objc_msgSend_821( + obj, + sel, + ); + } + + late final __objc_msgSend_821Ptr = _lookup< + ffi.NativeFunction< + ffi.Int32 Function( + ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); + late final __objc_msgSend_821 = __objc_msgSend_821Ptr.asFunction< + int Function(ffi.Pointer, ffi.Pointer)>(); + + late final _sel_setDetermination_1 = _registerName1("setDetermination:"); + void _objc_msgSend_822( + ffi.Pointer obj, + ffi.Pointer sel, + int value, + ) { + return __objc_msgSend_822( + obj, + sel, + value, + ); + } + + late final __objc_msgSend_822Ptr = _lookup< + ffi.NativeFunction< + ffi.Void Function(ffi.Pointer, ffi.Pointer, + ffi.Int32)>>('objc_msgSend'); + late final __objc_msgSend_822 = __objc_msgSend_822Ptr.asFunction< + void Function(ffi.Pointer, ffi.Pointer, int)>(); + + late final _sel_grammaticalPerson1 = _registerName1("grammaticalPerson"); + int _objc_msgSend_823( + ffi.Pointer obj, + ffi.Pointer sel, + ) { + return __objc_msgSend_823( + obj, + sel, + ); + } + + late final __objc_msgSend_823Ptr = _lookup< + ffi.NativeFunction< + ffi.Int32 Function( + ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); + late final __objc_msgSend_823 = __objc_msgSend_823Ptr.asFunction< + int Function(ffi.Pointer, ffi.Pointer)>(); + + late final _sel_setGrammaticalPerson_1 = + _registerName1("setGrammaticalPerson:"); + void _objc_msgSend_824( + ffi.Pointer obj, + ffi.Pointer sel, + int value, + ) { + return __objc_msgSend_824( + obj, + sel, + value, + ); + } + + late final __objc_msgSend_824Ptr = _lookup< + ffi.NativeFunction< + ffi.Void Function(ffi.Pointer, ffi.Pointer, + ffi.Int32)>>('objc_msgSend'); + late final __objc_msgSend_824 = __objc_msgSend_824Ptr.asFunction< + void Function(ffi.Pointer, ffi.Pointer, int)>(); + + late final _sel_pronounType1 = _registerName1("pronounType"); + int _objc_msgSend_825( + ffi.Pointer obj, + ffi.Pointer sel, + ) { + return __objc_msgSend_825( + obj, + sel, + ); + } + + late final __objc_msgSend_825Ptr = _lookup< + ffi.NativeFunction< + ffi.Int32 Function( + ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); + late final __objc_msgSend_825 = __objc_msgSend_825Ptr.asFunction< + int Function(ffi.Pointer, ffi.Pointer)>(); + + late final _sel_setPronounType_1 = _registerName1("setPronounType:"); + void _objc_msgSend_826( + ffi.Pointer obj, + ffi.Pointer sel, + int value, + ) { + return __objc_msgSend_826( + obj, + sel, + value, + ); + } + + late final __objc_msgSend_826Ptr = _lookup< + ffi.NativeFunction< + ffi.Void Function(ffi.Pointer, ffi.Pointer, + ffi.Int32)>>('objc_msgSend'); + late final __objc_msgSend_826 = __objc_msgSend_826Ptr.asFunction< + void Function(ffi.Pointer, ffi.Pointer, int)>(); + + late final _sel_definiteness1 = _registerName1("definiteness"); + int _objc_msgSend_827( + ffi.Pointer obj, + ffi.Pointer sel, + ) { + return __objc_msgSend_827( + obj, + sel, + ); + } + + late final __objc_msgSend_827Ptr = _lookup< + ffi.NativeFunction< + ffi.Int32 Function( + ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); + late final __objc_msgSend_827 = __objc_msgSend_827Ptr.asFunction< + int Function(ffi.Pointer, ffi.Pointer)>(); + + late final _sel_setDefiniteness_1 = _registerName1("setDefiniteness:"); + void _objc_msgSend_828( + ffi.Pointer obj, + ffi.Pointer sel, + int value, + ) { + return __objc_msgSend_828( + obj, + sel, + value, + ); + } + + late final __objc_msgSend_828Ptr = _lookup< + ffi.NativeFunction< + ffi.Void Function(ffi.Pointer, ffi.Pointer, + ffi.Int32)>>('objc_msgSend'); + late final __objc_msgSend_828 = __objc_msgSend_828Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, int)>(); late final _class_NSMorphologyCustomPronoun1 = @@ -23204,36 +23535,36 @@ class SentryCocoa { late final _sel_setReflexiveForm_1 = _registerName1("setReflexiveForm:"); late final _sel_customPronounForLanguage_1 = _registerName1("customPronounForLanguage:"); - ffi.Pointer _objc_msgSend_815( + ffi.Pointer _objc_msgSend_829( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer language, ) { - return __objc_msgSend_815( + return __objc_msgSend_829( obj, sel, language, ); } - late final __objc_msgSend_815Ptr = _lookup< + late final __objc_msgSend_829Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_815 = __objc_msgSend_815Ptr.asFunction< + late final __objc_msgSend_829 = __objc_msgSend_829Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); late final _sel_setCustomPronoun_forLanguage_error_1 = _registerName1("setCustomPronoun:forLanguage:error:"); - bool _objc_msgSend_816( + bool _objc_msgSend_830( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer features, ffi.Pointer language, ffi.Pointer> error, ) { - return __objc_msgSend_816( + return __objc_msgSend_830( obj, sel, features, @@ -23242,7 +23573,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_816Ptr = _lookup< + late final __objc_msgSend_830Ptr = _lookup< ffi.NativeFunction< ffi.Bool Function( ffi.Pointer, @@ -23250,7 +23581,7 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Pointer>)>>('objc_msgSend'); - late final __objc_msgSend_816 = __objc_msgSend_816Ptr.asFunction< + late final __objc_msgSend_830 = __objc_msgSend_830Ptr.asFunction< bool Function( ffi.Pointer, ffi.Pointer, @@ -23260,21 +23591,21 @@ class SentryCocoa { late final _sel_isUnspecified1 = _registerName1("isUnspecified"); late final _sel_userMorphology1 = _registerName1("userMorphology"); - ffi.Pointer _objc_msgSend_817( + ffi.Pointer _objc_msgSend_831( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_817( + return __objc_msgSend_831( obj, sel, ); } - late final __objc_msgSend_817Ptr = _lookup< + late final __objc_msgSend_831Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_817 = __objc_msgSend_817Ptr.asFunction< + late final __objc_msgSend_831 = __objc_msgSend_831Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>(); @@ -23284,64 +23615,64 @@ class SentryCocoa { late final _sel_isAsynchronous1 = _registerName1("isAsynchronous"); late final _sel_isReady1 = _registerName1("isReady"); late final _sel_addDependency_1 = _registerName1("addDependency:"); - void _objc_msgSend_818( + void _objc_msgSend_832( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer op, ) { - return __objc_msgSend_818( + return __objc_msgSend_832( obj, sel, op, ); } - late final __objc_msgSend_818Ptr = _lookup< + late final __objc_msgSend_832Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_818 = __objc_msgSend_818Ptr.asFunction< + late final __objc_msgSend_832 = __objc_msgSend_832Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); late final _sel_removeDependency_1 = _registerName1("removeDependency:"); late final _sel_dependencies1 = _registerName1("dependencies"); late final _sel_queuePriority1 = _registerName1("queuePriority"); - int _objc_msgSend_819( + int _objc_msgSend_833( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_819( + return __objc_msgSend_833( obj, sel, ); } - late final __objc_msgSend_819Ptr = _lookup< + late final __objc_msgSend_833Ptr = _lookup< ffi.NativeFunction< ffi.Int32 Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_819 = __objc_msgSend_819Ptr.asFunction< + late final __objc_msgSend_833 = __objc_msgSend_833Ptr.asFunction< int Function(ffi.Pointer, ffi.Pointer)>(); late final _sel_setQueuePriority_1 = _registerName1("setQueuePriority:"); - void _objc_msgSend_820( + void _objc_msgSend_834( ffi.Pointer obj, ffi.Pointer sel, int value, ) { - return __objc_msgSend_820( + return __objc_msgSend_834( obj, sel, value, ); } - late final __objc_msgSend_820Ptr = _lookup< + late final __objc_msgSend_834Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Int32)>>('objc_msgSend'); - late final __objc_msgSend_820 = __objc_msgSend_820Ptr.asFunction< + late final __objc_msgSend_834 = __objc_msgSend_834Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, int)>(); late final _sel_completionBlock1 = _registerName1("completionBlock"); @@ -23350,13 +23681,13 @@ class SentryCocoa { late final _sel_addOperation_1 = _registerName1("addOperation:"); late final _sel_addOperations_waitUntilFinished_1 = _registerName1("addOperations:waitUntilFinished:"); - void _objc_msgSend_821( + void _objc_msgSend_835( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer ops, bool wait, ) { - return __objc_msgSend_821( + return __objc_msgSend_835( obj, sel, ops, @@ -23364,11 +23695,11 @@ class SentryCocoa { ); } - late final __objc_msgSend_821Ptr = _lookup< + late final __objc_msgSend_835Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Bool)>>('objc_msgSend'); - late final __objc_msgSend_821 = __objc_msgSend_821Ptr.asFunction< + late final __objc_msgSend_835 = __objc_msgSend_835Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, bool)>(); @@ -23382,42 +23713,42 @@ class SentryCocoa { late final _sel_isSuspended1 = _registerName1("isSuspended"); late final _sel_setSuspended_1 = _registerName1("setSuspended:"); late final _sel_underlyingQueue1 = _registerName1("underlyingQueue"); - ffi.Pointer _objc_msgSend_822( + ffi.Pointer _objc_msgSend_836( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_822( + return __objc_msgSend_836( obj, sel, ); } - late final __objc_msgSend_822Ptr = _lookup< + late final __objc_msgSend_836Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_822 = __objc_msgSend_822Ptr.asFunction< + late final __objc_msgSend_836 = __objc_msgSend_836Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>(); late final _sel_setUnderlyingQueue_1 = _registerName1("setUnderlyingQueue:"); - void _objc_msgSend_823( + void _objc_msgSend_837( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer value, ) { - return __objc_msgSend_823( + return __objc_msgSend_837( obj, sel, value, ); } - late final __objc_msgSend_823Ptr = _lookup< + late final __objc_msgSend_837Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_823 = __objc_msgSend_823Ptr.asFunction< + late final __objc_msgSend_837 = __objc_msgSend_837Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); @@ -23425,21 +23756,21 @@ class SentryCocoa { late final _sel_waitUntilAllOperationsAreFinished1 = _registerName1("waitUntilAllOperationsAreFinished"); late final _sel_currentQueue1 = _registerName1("currentQueue"); - ffi.Pointer _objc_msgSend_824( + ffi.Pointer _objc_msgSend_838( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_824( + return __objc_msgSend_838( obj, sel, ); } - late final __objc_msgSend_824Ptr = _lookup< + late final __objc_msgSend_838Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_824 = __objc_msgSend_824Ptr.asFunction< + late final __objc_msgSend_838 = __objc_msgSend_838Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>(); @@ -23448,46 +23779,46 @@ class SentryCocoa { late final _sel_operationCount1 = _registerName1("operationCount"); late final _class_NSPointerArray1 = _getClass1("NSPointerArray"); late final _sel_initWithOptions_1 = _registerName1("initWithOptions:"); - instancetype _objc_msgSend_825( + instancetype _objc_msgSend_839( ffi.Pointer obj, ffi.Pointer sel, int options, ) { - return __objc_msgSend_825( + return __objc_msgSend_839( obj, sel, options, ); } - late final __objc_msgSend_825Ptr = _lookup< + late final __objc_msgSend_839Ptr = _lookup< ffi.NativeFunction< instancetype Function(ffi.Pointer, ffi.Pointer, ffi.Int32)>>('objc_msgSend'); - late final __objc_msgSend_825 = __objc_msgSend_825Ptr.asFunction< + late final __objc_msgSend_839 = __objc_msgSend_839Ptr.asFunction< instancetype Function( ffi.Pointer, ffi.Pointer, int)>(); late final _class_NSPointerFunctions1 = _getClass1("NSPointerFunctions"); late final _sel_pointerFunctionsWithOptions_1 = _registerName1("pointerFunctionsWithOptions:"); - ffi.Pointer _objc_msgSend_826( + ffi.Pointer _objc_msgSend_840( ffi.Pointer obj, ffi.Pointer sel, int options, ) { - return __objc_msgSend_826( + return __objc_msgSend_840( obj, sel, options, ); } - late final __objc_msgSend_826Ptr = _lookup< + late final __objc_msgSend_840Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Int32)>>('objc_msgSend'); - late final __objc_msgSend_826 = __objc_msgSend_826Ptr.asFunction< + late final __objc_msgSend_840 = __objc_msgSend_840Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, int)>(); @@ -23499,17 +23830,17 @@ class SentryCocoa { ffi.Pointer< ffi.NativeFunction< ffi.UnsignedLong Function(ffi.Pointer)>>)>> - _objc_msgSend_827( + _objc_msgSend_841( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_827( + return __objc_msgSend_841( obj, sel, ); } - late final __objc_msgSend_827Ptr = _lookup< + late final __objc_msgSend_841Ptr = _lookup< ffi.NativeFunction< ffi.Pointer< ffi.NativeFunction< @@ -23521,7 +23852,7 @@ class SentryCocoa { ffi.Pointer)>>)>> Function(ffi.Pointer, ffi.Pointer)>>( 'objc_msgSend'); - late final __objc_msgSend_827 = __objc_msgSend_827Ptr.asFunction< + late final __objc_msgSend_841 = __objc_msgSend_841Ptr.asFunction< ffi.Pointer< ffi.NativeFunction< ffi.UnsignedLong Function( @@ -23533,7 +23864,7 @@ class SentryCocoa { Function(ffi.Pointer, ffi.Pointer)>(); late final _sel_setHashFunction_1 = _registerName1("setHashFunction:"); - void _objc_msgSend_828( + void _objc_msgSend_842( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer< @@ -23546,14 +23877,14 @@ class SentryCocoa { ffi.Pointer)>>)>> value, ) { - return __objc_msgSend_828( + return __objc_msgSend_842( obj, sel, value, ); } - late final __objc_msgSend_828Ptr = _lookup< + late final __objc_msgSend_842Ptr = _lookup< ffi.NativeFunction< ffi.Void Function( ffi.Pointer, @@ -23567,7 +23898,7 @@ class SentryCocoa { ffi.UnsignedLong Function( ffi.Pointer)>>)>>)>>( 'objc_msgSend'); - late final __objc_msgSend_828 = __objc_msgSend_828Ptr.asFunction< + late final __objc_msgSend_842 = __objc_msgSend_842Ptr.asFunction< void Function( ffi.Pointer, ffi.Pointer, @@ -23589,17 +23920,17 @@ class SentryCocoa { ffi.Pointer< ffi.NativeFunction< ffi.UnsignedLong Function(ffi.Pointer)>>)>> - _objc_msgSend_829( + _objc_msgSend_843( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_829( + return __objc_msgSend_843( obj, sel, ); } - late final __objc_msgSend_829Ptr = _lookup< + late final __objc_msgSend_843Ptr = _lookup< ffi.NativeFunction< ffi.Pointer< ffi.NativeFunction< @@ -23612,7 +23943,7 @@ class SentryCocoa { ffi.Pointer)>>)>> Function(ffi.Pointer, ffi.Pointer)>>( 'objc_msgSend'); - late final __objc_msgSend_829 = __objc_msgSend_829Ptr.asFunction< + late final __objc_msgSend_843 = __objc_msgSend_843Ptr.asFunction< ffi.Pointer< ffi.NativeFunction< ffi.Bool Function( @@ -23625,7 +23956,7 @@ class SentryCocoa { Function(ffi.Pointer, ffi.Pointer)>(); late final _sel_setIsEqualFunction_1 = _registerName1("setIsEqualFunction:"); - void _objc_msgSend_830( + void _objc_msgSend_844( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer< @@ -23639,14 +23970,14 @@ class SentryCocoa { ffi.Pointer)>>)>> value, ) { - return __objc_msgSend_830( + return __objc_msgSend_844( obj, sel, value, ); } - late final __objc_msgSend_830Ptr = _lookup< + late final __objc_msgSend_844Ptr = _lookup< ffi.NativeFunction< ffi.Void Function( ffi.Pointer, @@ -23661,7 +23992,7 @@ class SentryCocoa { ffi.UnsignedLong Function( ffi.Pointer)>>)>>)>>( 'objc_msgSend'); - late final __objc_msgSend_830 = __objc_msgSend_830Ptr.asFunction< + late final __objc_msgSend_844 = __objc_msgSend_844Ptr.asFunction< void Function( ffi.Pointer, ffi.Pointer, @@ -23678,31 +24009,31 @@ class SentryCocoa { late final _sel_sizeFunction1 = _registerName1("sizeFunction"); ffi.Pointer< ffi.NativeFunction)>> - _objc_msgSend_831( + _objc_msgSend_845( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_831( + return __objc_msgSend_845( obj, sel, ); } - late final __objc_msgSend_831Ptr = _lookup< + late final __objc_msgSend_845Ptr = _lookup< ffi.NativeFunction< ffi.Pointer< ffi.NativeFunction< ffi.UnsignedLong Function(ffi.Pointer)>> Function(ffi.Pointer, ffi.Pointer)>>( 'objc_msgSend'); - late final __objc_msgSend_831 = __objc_msgSend_831Ptr.asFunction< + late final __objc_msgSend_845 = __objc_msgSend_845Ptr.asFunction< ffi.Pointer< ffi .NativeFunction)>> Function(ffi.Pointer, ffi.Pointer)>(); late final _sel_setSizeFunction_1 = _registerName1("setSizeFunction:"); - void _objc_msgSend_832( + void _objc_msgSend_846( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer< @@ -23710,14 +24041,14 @@ class SentryCocoa { .NativeFunction)>> value, ) { - return __objc_msgSend_832( + return __objc_msgSend_846( obj, sel, value, ); } - late final __objc_msgSend_832Ptr = _lookup< + late final __objc_msgSend_846Ptr = _lookup< ffi.NativeFunction< ffi.Void Function( ffi.Pointer, @@ -23726,7 +24057,7 @@ class SentryCocoa { ffi.NativeFunction< ffi.UnsignedLong Function( ffi.Pointer)>>)>>('objc_msgSend'); - late final __objc_msgSend_832 = __objc_msgSend_832Ptr.asFunction< + late final __objc_msgSend_846 = __objc_msgSend_846Ptr.asFunction< void Function( ffi.Pointer, ffi.Pointer, @@ -23738,17 +24069,17 @@ class SentryCocoa { ffi.Pointer< ffi.NativeFunction< ffi.Pointer Function(ffi.Pointer)>> - _objc_msgSend_833( + _objc_msgSend_847( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_833( + return __objc_msgSend_847( obj, sel, ); } - late final __objc_msgSend_833Ptr = + late final __objc_msgSend_847Ptr = _lookup< ffi.NativeFunction< ffi.Pointer< @@ -23757,7 +24088,7 @@ class SentryCocoa { ffi.Pointer)>> Function(ffi.Pointer, ffi.Pointer)>>( 'objc_msgSend'); - late final __objc_msgSend_833 = __objc_msgSend_833Ptr.asFunction< + late final __objc_msgSend_847 = __objc_msgSend_847Ptr.asFunction< ffi.Pointer< ffi.NativeFunction< ffi.Pointer Function(ffi.Pointer)>> @@ -23765,7 +24096,7 @@ class SentryCocoa { late final _sel_setDescriptionFunction_1 = _registerName1("setDescriptionFunction:"); - void _objc_msgSend_834( + void _objc_msgSend_848( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer< @@ -23773,14 +24104,14 @@ class SentryCocoa { ffi.Pointer Function(ffi.Pointer)>> value, ) { - return __objc_msgSend_834( + return __objc_msgSend_848( obj, sel, value, ); } - late final __objc_msgSend_834Ptr = _lookup< + late final __objc_msgSend_848Ptr = _lookup< ffi.NativeFunction< ffi.Void Function( ffi.Pointer, @@ -23789,7 +24120,7 @@ class SentryCocoa { ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer)>>)>>('objc_msgSend'); - late final __objc_msgSend_834 = __objc_msgSend_834Ptr.asFunction< + late final __objc_msgSend_848 = __objc_msgSend_848Ptr.asFunction< void Function( ffi.Pointer, ffi.Pointer, @@ -23805,17 +24136,17 @@ class SentryCocoa { ffi.Pointer< ffi.NativeFunction< ffi.UnsignedLong Function(ffi.Pointer)>>)>> - _objc_msgSend_835( + _objc_msgSend_849( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_835( + return __objc_msgSend_849( obj, sel, ); } - late final __objc_msgSend_835Ptr = _lookup< + late final __objc_msgSend_849Ptr = _lookup< ffi.NativeFunction< ffi.Pointer< ffi.NativeFunction< @@ -23827,7 +24158,7 @@ class SentryCocoa { ffi.Pointer)>>)>> Function(ffi.Pointer, ffi.Pointer)>>( 'objc_msgSend'); - late final __objc_msgSend_835 = __objc_msgSend_835Ptr.asFunction< + late final __objc_msgSend_849 = __objc_msgSend_849Ptr.asFunction< ffi.Pointer< ffi.NativeFunction< ffi.Void Function( @@ -23840,7 +24171,7 @@ class SentryCocoa { late final _sel_setRelinquishFunction_1 = _registerName1("setRelinquishFunction:"); - void _objc_msgSend_836( + void _objc_msgSend_850( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer< @@ -23853,14 +24184,14 @@ class SentryCocoa { ffi.Pointer)>>)>> value, ) { - return __objc_msgSend_836( + return __objc_msgSend_850( obj, sel, value, ); } - late final __objc_msgSend_836Ptr = _lookup< + late final __objc_msgSend_850Ptr = _lookup< ffi.NativeFunction< ffi.Void Function( ffi.Pointer, @@ -23874,7 +24205,7 @@ class SentryCocoa { ffi.UnsignedLong Function( ffi.Pointer)>>)>>)>>( 'objc_msgSend'); - late final __objc_msgSend_836 = __objc_msgSend_836Ptr.asFunction< + late final __objc_msgSend_850 = __objc_msgSend_850Ptr.asFunction< void Function( ffi.Pointer, ffi.Pointer, @@ -23895,17 +24226,17 @@ class SentryCocoa { ffi.Pointer< ffi.NativeFunction< ffi.UnsignedLong Function(ffi.Pointer)>>, - ffi.Bool)>> _objc_msgSend_837( + ffi.Bool)>> _objc_msgSend_851( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_837( + return __objc_msgSend_851( obj, sel, ); } - late final __objc_msgSend_837Ptr = _lookup< + late final __objc_msgSend_851Ptr = _lookup< ffi.NativeFunction< ffi.Pointer< ffi.NativeFunction< @@ -23918,7 +24249,7 @@ class SentryCocoa { ffi.Bool)>> Function(ffi.Pointer, ffi.Pointer)>>( 'objc_msgSend'); - late final __objc_msgSend_837 = __objc_msgSend_837Ptr.asFunction< + late final __objc_msgSend_851 = __objc_msgSend_851Ptr.asFunction< ffi.Pointer< ffi.NativeFunction< ffi.Pointer Function( @@ -23931,7 +24262,7 @@ class SentryCocoa { Function(ffi.Pointer, ffi.Pointer)>(); late final _sel_setAcquireFunction_1 = _registerName1("setAcquireFunction:"); - void _objc_msgSend_838( + void _objc_msgSend_852( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer< @@ -23944,14 +24275,14 @@ class SentryCocoa { ffi.Bool)>> value, ) { - return __objc_msgSend_838( + return __objc_msgSend_852( obj, sel, value, ); } - late final __objc_msgSend_838Ptr = _lookup< + late final __objc_msgSend_852Ptr = _lookup< ffi.NativeFunction< ffi.Void Function( ffi.Pointer, @@ -23965,7 +24296,7 @@ class SentryCocoa { ffi.UnsignedLong Function( ffi.Pointer)>>, ffi.Bool)>>)>>('objc_msgSend'); - late final __objc_msgSend_838 = __objc_msgSend_838Ptr.asFunction< + late final __objc_msgSend_852 = __objc_msgSend_852Ptr.asFunction< void Function( ffi.Pointer, ffi.Pointer, @@ -23989,107 +24320,107 @@ class SentryCocoa { _registerName1("setUsesWeakReadAndWriteBarriers:"); late final _sel_initWithPointerFunctions_1 = _registerName1("initWithPointerFunctions:"); - instancetype _objc_msgSend_839( + instancetype _objc_msgSend_853( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer functions, ) { - return __objc_msgSend_839( + return __objc_msgSend_853( obj, sel, functions, ); } - late final __objc_msgSend_839Ptr = _lookup< + late final __objc_msgSend_853Ptr = _lookup< ffi.NativeFunction< instancetype Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_839 = __objc_msgSend_839Ptr.asFunction< + late final __objc_msgSend_853 = __objc_msgSend_853Ptr.asFunction< instancetype Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); late final _sel_pointerArrayWithOptions_1 = _registerName1("pointerArrayWithOptions:"); - ffi.Pointer _objc_msgSend_840( + ffi.Pointer _objc_msgSend_854( ffi.Pointer obj, ffi.Pointer sel, int options, ) { - return __objc_msgSend_840( + return __objc_msgSend_854( obj, sel, options, ); } - late final __objc_msgSend_840Ptr = _lookup< + late final __objc_msgSend_854Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Int32)>>('objc_msgSend'); - late final __objc_msgSend_840 = __objc_msgSend_840Ptr.asFunction< + late final __objc_msgSend_854 = __objc_msgSend_854Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, int)>(); late final _sel_pointerArrayWithPointerFunctions_1 = _registerName1("pointerArrayWithPointerFunctions:"); - ffi.Pointer _objc_msgSend_841( + ffi.Pointer _objc_msgSend_855( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer functions, ) { - return __objc_msgSend_841( + return __objc_msgSend_855( obj, sel, functions, ); } - late final __objc_msgSend_841Ptr = _lookup< + late final __objc_msgSend_855Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_841 = __objc_msgSend_841Ptr.asFunction< + late final __objc_msgSend_855 = __objc_msgSend_855Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); late final _sel_pointerFunctions1 = _registerName1("pointerFunctions"); - ffi.Pointer _objc_msgSend_842( + ffi.Pointer _objc_msgSend_856( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_842( + return __objc_msgSend_856( obj, sel, ); } - late final __objc_msgSend_842Ptr = _lookup< + late final __objc_msgSend_856Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_842 = __objc_msgSend_842Ptr.asFunction< + late final __objc_msgSend_856 = __objc_msgSend_856Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>(); late final _sel_pointerAtIndex_1 = _registerName1("pointerAtIndex:"); - ffi.Pointer _objc_msgSend_843( + ffi.Pointer _objc_msgSend_857( ffi.Pointer obj, ffi.Pointer sel, int index, ) { - return __objc_msgSend_843( + return __objc_msgSend_857( obj, sel, index, ); } - late final __objc_msgSend_843Ptr = _lookup< + late final __objc_msgSend_857Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.UnsignedLong)>>('objc_msgSend'); - late final __objc_msgSend_843 = __objc_msgSend_843Ptr.asFunction< + late final __objc_msgSend_857 = __objc_msgSend_857Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, int)>(); @@ -24100,13 +24431,13 @@ class SentryCocoa { _registerName1("insertPointer:atIndex:"); late final _sel_replacePointerAtIndex_withPointer_1 = _registerName1("replacePointerAtIndex:withPointer:"); - void _objc_msgSend_844( + void _objc_msgSend_858( ffi.Pointer obj, ffi.Pointer sel, int index, ffi.Pointer item, ) { - return __objc_msgSend_844( + return __objc_msgSend_858( obj, sel, index, @@ -24114,11 +24445,11 @@ class SentryCocoa { ); } - late final __objc_msgSend_844Ptr = _lookup< + late final __objc_msgSend_858Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.UnsignedLong, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_844 = __objc_msgSend_844Ptr.asFunction< + late final __objc_msgSend_858 = __objc_msgSend_858Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, int, ffi.Pointer)>(); @@ -24130,21 +24461,21 @@ class SentryCocoa { _registerName1("pointerArrayWithWeakObjects"); late final _sel_strongObjectsPointerArray1 = _registerName1("strongObjectsPointerArray"); - ffi.Pointer _objc_msgSend_845( + ffi.Pointer _objc_msgSend_859( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_845( + return __objc_msgSend_859( obj, sel, ); } - late final __objc_msgSend_845Ptr = _lookup< + late final __objc_msgSend_859Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_845 = __objc_msgSend_845Ptr.asFunction< + late final __objc_msgSend_859 = __objc_msgSend_859Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>(); @@ -24152,21 +24483,21 @@ class SentryCocoa { _registerName1("weakObjectsPointerArray"); late final _class_NSProcessInfo1 = _getClass1("NSProcessInfo"); late final _sel_processInfo1 = _registerName1("processInfo"); - ffi.Pointer _objc_msgSend_846( + ffi.Pointer _objc_msgSend_860( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_846( + return __objc_msgSend_860( obj, sel, ); } - late final __objc_msgSend_846Ptr = _lookup< + late final __objc_msgSend_860Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_846 = __objc_msgSend_846Ptr.asFunction< + late final __objc_msgSend_860 = __objc_msgSend_860Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>(); @@ -24183,25 +24514,25 @@ class SentryCocoa { _registerName1("operatingSystemVersionString"); late final _sel_operatingSystemVersion1 = _registerName1("operatingSystemVersion"); - void _objc_msgSend_847( + void _objc_msgSend_861( ffi.Pointer stret, ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_847( + return __objc_msgSend_861( stret, obj, sel, ); } - late final __objc_msgSend_847Ptr = _lookup< + late final __objc_msgSend_861Ptr = _lookup< ffi.NativeFunction< ffi.Void Function( ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend_stret'); - late final __objc_msgSend_847 = __objc_msgSend_847Ptr.asFunction< + late final __objc_msgSend_861 = __objc_msgSend_861Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); @@ -24211,23 +24542,23 @@ class SentryCocoa { late final _sel_physicalMemory1 = _registerName1("physicalMemory"); late final _sel_isOperatingSystemAtLeastVersion_1 = _registerName1("isOperatingSystemAtLeastVersion:"); - bool _objc_msgSend_848( + bool _objc_msgSend_862( ffi.Pointer obj, ffi.Pointer sel, NSOperatingSystemVersion version, ) { - return __objc_msgSend_848( + return __objc_msgSend_862( obj, sel, version, ); } - late final __objc_msgSend_848Ptr = _lookup< + late final __objc_msgSend_862Ptr = _lookup< ffi.NativeFunction< ffi.Bool Function(ffi.Pointer, ffi.Pointer, NSOperatingSystemVersion)>>('objc_msgSend'); - late final __objc_msgSend_848 = __objc_msgSend_848Ptr.asFunction< + late final __objc_msgSend_862 = __objc_msgSend_862Ptr.asFunction< bool Function(ffi.Pointer, ffi.Pointer, NSOperatingSystemVersion)>(); @@ -24246,13 +24577,13 @@ class SentryCocoa { _registerName1("setAutomaticTerminationSupportEnabled:"); late final _sel_beginActivityWithOptions_reason_1 = _registerName1("beginActivityWithOptions:reason:"); - ffi.Pointer _objc_msgSend_849( + ffi.Pointer _objc_msgSend_863( ffi.Pointer obj, ffi.Pointer sel, int options, ffi.Pointer reason, ) { - return __objc_msgSend_849( + return __objc_msgSend_863( obj, sel, options, @@ -24260,28 +24591,28 @@ class SentryCocoa { ); } - late final __objc_msgSend_849Ptr = _lookup< + late final __objc_msgSend_863Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, ffi.Int32, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_849 = __objc_msgSend_849Ptr.asFunction< + late final __objc_msgSend_863 = __objc_msgSend_863Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, int, ffi.Pointer)>(); late final _sel_endActivity_1 = _registerName1("endActivity:"); late final _sel_performActivityWithOptions_reason_usingBlock_1 = _registerName1("performActivityWithOptions:reason:usingBlock:"); - void _objc_msgSend_850( + void _objc_msgSend_864( ffi.Pointer obj, ffi.Pointer sel, int options, ffi.Pointer reason, ffi.Pointer<_ObjCBlock> block, ) { - return __objc_msgSend_850( + return __objc_msgSend_864( obj, sel, options, @@ -24290,7 +24621,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_850Ptr = _lookup< + late final __objc_msgSend_864Ptr = _lookup< ffi.NativeFunction< ffi.Void Function( ffi.Pointer, @@ -24298,19 +24629,19 @@ class SentryCocoa { ffi.Int32, ffi.Pointer, ffi.Pointer<_ObjCBlock>)>>('objc_msgSend'); - late final __objc_msgSend_850 = __objc_msgSend_850Ptr.asFunction< + late final __objc_msgSend_864 = __objc_msgSend_864Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, int, ffi.Pointer, ffi.Pointer<_ObjCBlock>)>(); late final _sel_performExpiringActivityWithReason_usingBlock_1 = _registerName1("performExpiringActivityWithReason:usingBlock:"); - void _objc_msgSend_851( + void _objc_msgSend_865( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer reason, ffi.Pointer<_ObjCBlock> block, ) { - return __objc_msgSend_851( + return __objc_msgSend_865( obj, sel, reason, @@ -24318,35 +24649,35 @@ class SentryCocoa { ); } - late final __objc_msgSend_851Ptr = _lookup< + late final __objc_msgSend_865Ptr = _lookup< ffi.NativeFunction< ffi.Void Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer<_ObjCBlock>)>>('objc_msgSend'); - late final __objc_msgSend_851 = __objc_msgSend_851Ptr.asFunction< + late final __objc_msgSend_865 = __objc_msgSend_865Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer<_ObjCBlock>)>(); late final _sel_userName1 = _registerName1("userName"); late final _sel_fullUserName1 = _registerName1("fullUserName"); late final _sel_thermalState1 = _registerName1("thermalState"); - int _objc_msgSend_852( + int _objc_msgSend_866( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_852( + return __objc_msgSend_866( obj, sel, ); } - late final __objc_msgSend_852Ptr = _lookup< + late final __objc_msgSend_866Ptr = _lookup< ffi.NativeFunction< ffi.Int32 Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_852 = __objc_msgSend_852Ptr.asFunction< + late final __objc_msgSend_866 = __objc_msgSend_866Ptr.asFunction< int Function(ffi.Pointer, ffi.Pointer)>(); late final _sel_isLowPowerModeEnabled1 = @@ -24355,40 +24686,40 @@ class SentryCocoa { late final _sel_isiOSAppOnMac1 = _registerName1("isiOSAppOnMac"); late final _class_NSTextCheckingResult1 = _getClass1("NSTextCheckingResult"); late final _sel_resultType1 = _registerName1("resultType"); - int _objc_msgSend_853( + int _objc_msgSend_867( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_853( + return __objc_msgSend_867( obj, sel, ); } - late final __objc_msgSend_853Ptr = _lookup< + late final __objc_msgSend_867Ptr = _lookup< ffi.NativeFunction< ffi.Int32 Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_853 = __objc_msgSend_853Ptr.asFunction< + late final __objc_msgSend_867 = __objc_msgSend_867Ptr.asFunction< int Function(ffi.Pointer, ffi.Pointer)>(); late final _sel_range1 = _registerName1("range"); late final _sel_orthography1 = _registerName1("orthography"); - ffi.Pointer _objc_msgSend_854( + ffi.Pointer _objc_msgSend_868( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_854( + return __objc_msgSend_868( obj, sel, ); } - late final __objc_msgSend_854Ptr = _lookup< + late final __objc_msgSend_868Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_854 = __objc_msgSend_854Ptr.asFunction< + late final __objc_msgSend_868 = __objc_msgSend_868Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>(); @@ -24400,14 +24731,14 @@ class SentryCocoa { late final _class_NSRegularExpression1 = _getClass1("NSRegularExpression"); late final _sel_regularExpressionWithPattern_options_error_1 = _registerName1("regularExpressionWithPattern:options:error:"); - ffi.Pointer _objc_msgSend_855( + ffi.Pointer _objc_msgSend_869( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer pattern, int options, ffi.Pointer> error, ) { - return __objc_msgSend_855( + return __objc_msgSend_869( obj, sel, pattern, @@ -24416,7 +24747,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_855Ptr = _lookup< + late final __objc_msgSend_869Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, @@ -24424,7 +24755,7 @@ class SentryCocoa { ffi.Pointer, ffi.Int32, ffi.Pointer>)>>('objc_msgSend'); - late final __objc_msgSend_855 = __objc_msgSend_855Ptr.asFunction< + late final __objc_msgSend_869 = __objc_msgSend_869Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, @@ -24434,14 +24765,14 @@ class SentryCocoa { late final _sel_initWithPattern_options_error_1 = _registerName1("initWithPattern:options:error:"); - instancetype _objc_msgSend_856( + instancetype _objc_msgSend_870( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer pattern, int options, ffi.Pointer> error, ) { - return __objc_msgSend_856( + return __objc_msgSend_870( obj, sel, pattern, @@ -24450,7 +24781,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_856Ptr = _lookup< + late final __objc_msgSend_870Ptr = _lookup< ffi.NativeFunction< instancetype Function( ffi.Pointer, @@ -24458,7 +24789,7 @@ class SentryCocoa { ffi.Pointer, ffi.Int32, ffi.Pointer>)>>('objc_msgSend'); - late final __objc_msgSend_856 = __objc_msgSend_856Ptr.asFunction< + late final __objc_msgSend_870 = __objc_msgSend_870Ptr.asFunction< instancetype Function( ffi.Pointer, ffi.Pointer, @@ -24468,21 +24799,21 @@ class SentryCocoa { late final _sel_pattern1 = _registerName1("pattern"); late final _sel_options1 = _registerName1("options"); - int _objc_msgSend_857( + int _objc_msgSend_871( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_857( + return __objc_msgSend_871( obj, sel, ); } - late final __objc_msgSend_857Ptr = _lookup< + late final __objc_msgSend_871Ptr = _lookup< ffi.NativeFunction< ffi.Int32 Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_857 = __objc_msgSend_857Ptr.asFunction< + late final __objc_msgSend_871 = __objc_msgSend_871Ptr.asFunction< int Function(ffi.Pointer, ffi.Pointer)>(); late final _sel_numberOfCaptureGroups1 = @@ -24491,7 +24822,7 @@ class SentryCocoa { _registerName1("escapedPatternForString:"); late final _sel_enumerateMatchesInString_options_range_usingBlock_1 = _registerName1("enumerateMatchesInString:options:range:usingBlock:"); - void _objc_msgSend_858( + void _objc_msgSend_872( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer string, @@ -24499,7 +24830,7 @@ class SentryCocoa { _NSRange range, ffi.Pointer<_ObjCBlock> block, ) { - return __objc_msgSend_858( + return __objc_msgSend_872( obj, sel, string, @@ -24509,7 +24840,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_858Ptr = _lookup< + late final __objc_msgSend_872Ptr = _lookup< ffi.NativeFunction< ffi.Void Function( ffi.Pointer, @@ -24518,20 +24849,20 @@ class SentryCocoa { ffi.Int32, _NSRange, ffi.Pointer<_ObjCBlock>)>>('objc_msgSend'); - late final __objc_msgSend_858 = __objc_msgSend_858Ptr.asFunction< + late final __objc_msgSend_872 = __objc_msgSend_872Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, int, _NSRange, ffi.Pointer<_ObjCBlock>)>(); late final _sel_matchesInString_options_range_1 = _registerName1("matchesInString:options:range:"); - ffi.Pointer _objc_msgSend_859( + ffi.Pointer _objc_msgSend_873( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer string, int options, _NSRange range, ) { - return __objc_msgSend_859( + return __objc_msgSend_873( obj, sel, string, @@ -24540,7 +24871,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_859Ptr = _lookup< + late final __objc_msgSend_873Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, @@ -24548,20 +24879,20 @@ class SentryCocoa { ffi.Pointer, ffi.Int32, _NSRange)>>('objc_msgSend'); - late final __objc_msgSend_859 = __objc_msgSend_859Ptr.asFunction< + late final __objc_msgSend_873 = __objc_msgSend_873Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, int, _NSRange)>(); late final _sel_numberOfMatchesInString_options_range_1 = _registerName1("numberOfMatchesInString:options:range:"); - int _objc_msgSend_860( + int _objc_msgSend_874( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer string, int options, _NSRange range, ) { - return __objc_msgSend_860( + return __objc_msgSend_874( obj, sel, string, @@ -24570,7 +24901,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_860Ptr = _lookup< + late final __objc_msgSend_874Ptr = _lookup< ffi.NativeFunction< ffi.UnsignedLong Function( ffi.Pointer, @@ -24578,20 +24909,20 @@ class SentryCocoa { ffi.Pointer, ffi.Int32, _NSRange)>>('objc_msgSend'); - late final __objc_msgSend_860 = __objc_msgSend_860Ptr.asFunction< + late final __objc_msgSend_874 = __objc_msgSend_874Ptr.asFunction< int Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, int, _NSRange)>(); late final _sel_firstMatchInString_options_range_1 = _registerName1("firstMatchInString:options:range:"); - ffi.Pointer _objc_msgSend_861( + ffi.Pointer _objc_msgSend_875( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer string, int options, _NSRange range, ) { - return __objc_msgSend_861( + return __objc_msgSend_875( obj, sel, string, @@ -24600,7 +24931,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_861Ptr = _lookup< + late final __objc_msgSend_875Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, @@ -24608,13 +24939,13 @@ class SentryCocoa { ffi.Pointer, ffi.Int32, _NSRange)>>('objc_msgSend'); - late final __objc_msgSend_861 = __objc_msgSend_861Ptr.asFunction< + late final __objc_msgSend_875 = __objc_msgSend_875Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, int, _NSRange)>(); late final _sel_rangeOfFirstMatchInString_options_range_1 = _registerName1("rangeOfFirstMatchInString:options:range:"); - void _objc_msgSend_862( + void _objc_msgSend_876( ffi.Pointer<_NSRange> stret, ffi.Pointer obj, ffi.Pointer sel, @@ -24622,7 +24953,7 @@ class SentryCocoa { int options, _NSRange range, ) { - return __objc_msgSend_862( + return __objc_msgSend_876( stret, obj, sel, @@ -24632,7 +24963,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_862Ptr = _lookup< + late final __objc_msgSend_876Ptr = _lookup< ffi.NativeFunction< ffi.Void Function( ffi.Pointer<_NSRange>, @@ -24641,14 +24972,14 @@ class SentryCocoa { ffi.Pointer, ffi.Int32, _NSRange)>>('objc_msgSend_stret'); - late final __objc_msgSend_862 = __objc_msgSend_862Ptr.asFunction< + late final __objc_msgSend_876 = __objc_msgSend_876Ptr.asFunction< void Function(ffi.Pointer<_NSRange>, ffi.Pointer, ffi.Pointer, ffi.Pointer, int, _NSRange)>(); late final _sel_stringByReplacingMatchesInString_options_range_withTemplate_1 = _registerName1( "stringByReplacingMatchesInString:options:range:withTemplate:"); - ffi.Pointer _objc_msgSend_863( + ffi.Pointer _objc_msgSend_877( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer string, @@ -24656,7 +24987,7 @@ class SentryCocoa { _NSRange range, ffi.Pointer templ, ) { - return __objc_msgSend_863( + return __objc_msgSend_877( obj, sel, string, @@ -24666,7 +24997,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_863Ptr = _lookup< + late final __objc_msgSend_877Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, @@ -24675,7 +25006,7 @@ class SentryCocoa { ffi.Int32, _NSRange, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_863 = __objc_msgSend_863Ptr.asFunction< + late final __objc_msgSend_877 = __objc_msgSend_877Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, @@ -24686,7 +25017,7 @@ class SentryCocoa { late final _sel_replaceMatchesInString_options_range_withTemplate_1 = _registerName1("replaceMatchesInString:options:range:withTemplate:"); - int _objc_msgSend_864( + int _objc_msgSend_878( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer string, @@ -24694,7 +25025,7 @@ class SentryCocoa { _NSRange range, ffi.Pointer templ, ) { - return __objc_msgSend_864( + return __objc_msgSend_878( obj, sel, string, @@ -24704,7 +25035,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_864Ptr = _lookup< + late final __objc_msgSend_878Ptr = _lookup< ffi.NativeFunction< ffi.UnsignedLong Function( ffi.Pointer, @@ -24713,13 +25044,13 @@ class SentryCocoa { ffi.Int32, _NSRange, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_864 = __objc_msgSend_864Ptr.asFunction< + late final __objc_msgSend_878 = __objc_msgSend_878Ptr.asFunction< int Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, int, _NSRange, ffi.Pointer)>(); late final _sel_replacementStringForResult_inString_offset_template_1 = _registerName1("replacementStringForResult:inString:offset:template:"); - ffi.Pointer _objc_msgSend_865( + ffi.Pointer _objc_msgSend_879( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer result, @@ -24727,7 +25058,7 @@ class SentryCocoa { int offset, ffi.Pointer templ, ) { - return __objc_msgSend_865( + return __objc_msgSend_879( obj, sel, result, @@ -24737,7 +25068,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_865Ptr = _lookup< + late final __objc_msgSend_879Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, @@ -24746,7 +25077,7 @@ class SentryCocoa { ffi.Pointer, ffi.Long, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_865 = __objc_msgSend_865Ptr.asFunction< + late final __objc_msgSend_879 = __objc_msgSend_879Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, @@ -24758,21 +25089,21 @@ class SentryCocoa { late final _sel_escapedTemplateForString_1 = _registerName1("escapedTemplateForString:"); late final _sel_regularExpression1 = _registerName1("regularExpression"); - ffi.Pointer _objc_msgSend_866( + ffi.Pointer _objc_msgSend_880( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_866( + return __objc_msgSend_880( obj, sel, ); } - late final __objc_msgSend_866Ptr = _lookup< + late final __objc_msgSend_880Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_866 = __objc_msgSend_866Ptr.asFunction< + late final __objc_msgSend_880 = __objc_msgSend_880Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>(); @@ -24782,36 +25113,36 @@ class SentryCocoa { late final _sel_rangeWithName_1 = _registerName1("rangeWithName:"); late final _sel_resultByAdjustingRangesWithOffset_1 = _registerName1("resultByAdjustingRangesWithOffset:"); - ffi.Pointer _objc_msgSend_867( + ffi.Pointer _objc_msgSend_881( ffi.Pointer obj, ffi.Pointer sel, int offset, ) { - return __objc_msgSend_867( + return __objc_msgSend_881( obj, sel, offset, ); } - late final __objc_msgSend_867Ptr = _lookup< + late final __objc_msgSend_881Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Long)>>('objc_msgSend'); - late final __objc_msgSend_867 = __objc_msgSend_867Ptr.asFunction< + late final __objc_msgSend_881 = __objc_msgSend_881Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, int)>(); late final _sel_addressComponents1 = _registerName1("addressComponents"); late final _sel_orthographyCheckingResultWithRange_orthography_1 = _registerName1("orthographyCheckingResultWithRange:orthography:"); - ffi.Pointer _objc_msgSend_868( + ffi.Pointer _objc_msgSend_882( ffi.Pointer obj, ffi.Pointer sel, _NSRange range, ffi.Pointer orthography, ) { - return __objc_msgSend_868( + return __objc_msgSend_882( obj, sel, range, @@ -24819,48 +25150,48 @@ class SentryCocoa { ); } - late final __objc_msgSend_868Ptr = _lookup< + late final __objc_msgSend_882Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, _NSRange, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_868 = __objc_msgSend_868Ptr.asFunction< + late final __objc_msgSend_882 = __objc_msgSend_882Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, _NSRange, ffi.Pointer)>(); late final _sel_spellCheckingResultWithRange_1 = _registerName1("spellCheckingResultWithRange:"); - ffi.Pointer _objc_msgSend_869( + ffi.Pointer _objc_msgSend_883( ffi.Pointer obj, ffi.Pointer sel, _NSRange range, ) { - return __objc_msgSend_869( + return __objc_msgSend_883( obj, sel, range, ); } - late final __objc_msgSend_869Ptr = _lookup< + late final __objc_msgSend_883Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, _NSRange)>>('objc_msgSend'); - late final __objc_msgSend_869 = __objc_msgSend_869Ptr.asFunction< + late final __objc_msgSend_883 = __objc_msgSend_883Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, _NSRange)>(); late final _sel_grammarCheckingResultWithRange_details_1 = _registerName1("grammarCheckingResultWithRange:details:"); - ffi.Pointer _objc_msgSend_870( + ffi.Pointer _objc_msgSend_884( ffi.Pointer obj, ffi.Pointer sel, _NSRange range, ffi.Pointer details, ) { - return __objc_msgSend_870( + return __objc_msgSend_884( obj, sel, range, @@ -24868,26 +25199,26 @@ class SentryCocoa { ); } - late final __objc_msgSend_870Ptr = _lookup< + late final __objc_msgSend_884Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, _NSRange, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_870 = __objc_msgSend_870Ptr.asFunction< + late final __objc_msgSend_884 = __objc_msgSend_884Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, _NSRange, ffi.Pointer)>(); late final _sel_dateCheckingResultWithRange_date_1 = _registerName1("dateCheckingResultWithRange:date:"); - ffi.Pointer _objc_msgSend_871( + ffi.Pointer _objc_msgSend_885( ffi.Pointer obj, ffi.Pointer sel, _NSRange range, ffi.Pointer date, ) { - return __objc_msgSend_871( + return __objc_msgSend_885( obj, sel, range, @@ -24895,20 +25226,20 @@ class SentryCocoa { ); } - late final __objc_msgSend_871Ptr = _lookup< + late final __objc_msgSend_885Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, _NSRange, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_871 = __objc_msgSend_871Ptr.asFunction< + late final __objc_msgSend_885 = __objc_msgSend_885Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, _NSRange, ffi.Pointer)>(); late final _sel_dateCheckingResultWithRange_date_timeZone_duration_1 = _registerName1("dateCheckingResultWithRange:date:timeZone:duration:"); - ffi.Pointer _objc_msgSend_872( + ffi.Pointer _objc_msgSend_886( ffi.Pointer obj, ffi.Pointer sel, _NSRange range, @@ -24916,7 +25247,7 @@ class SentryCocoa { ffi.Pointer timeZone, double duration, ) { - return __objc_msgSend_872( + return __objc_msgSend_886( obj, sel, range, @@ -24926,7 +25257,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_872Ptr = _lookup< + late final __objc_msgSend_886Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, @@ -24935,7 +25266,7 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Double)>>('objc_msgSend'); - late final __objc_msgSend_872 = __objc_msgSend_872Ptr.asFunction< + late final __objc_msgSend_886 = __objc_msgSend_886Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, @@ -24946,13 +25277,13 @@ class SentryCocoa { late final _sel_addressCheckingResultWithRange_components_1 = _registerName1("addressCheckingResultWithRange:components:"); - ffi.Pointer _objc_msgSend_873( + ffi.Pointer _objc_msgSend_887( ffi.Pointer obj, ffi.Pointer sel, _NSRange range, ffi.Pointer components, ) { - return __objc_msgSend_873( + return __objc_msgSend_887( obj, sel, range, @@ -24960,26 +25291,26 @@ class SentryCocoa { ); } - late final __objc_msgSend_873Ptr = _lookup< + late final __objc_msgSend_887Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, _NSRange, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_873 = __objc_msgSend_873Ptr.asFunction< + late final __objc_msgSend_887 = __objc_msgSend_887Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, _NSRange, ffi.Pointer)>(); late final _sel_linkCheckingResultWithRange_URL_1 = _registerName1("linkCheckingResultWithRange:URL:"); - ffi.Pointer _objc_msgSend_874( + ffi.Pointer _objc_msgSend_888( ffi.Pointer obj, ffi.Pointer sel, _NSRange range, ffi.Pointer url, ) { - return __objc_msgSend_874( + return __objc_msgSend_888( obj, sel, range, @@ -24987,26 +25318,26 @@ class SentryCocoa { ); } - late final __objc_msgSend_874Ptr = _lookup< + late final __objc_msgSend_888Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, _NSRange, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_874 = __objc_msgSend_874Ptr.asFunction< + late final __objc_msgSend_888 = __objc_msgSend_888Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, _NSRange, ffi.Pointer)>(); late final _sel_quoteCheckingResultWithRange_replacementString_1 = _registerName1("quoteCheckingResultWithRange:replacementString:"); - ffi.Pointer _objc_msgSend_875( + ffi.Pointer _objc_msgSend_889( ffi.Pointer obj, ffi.Pointer sel, _NSRange range, ffi.Pointer replacementString, ) { - return __objc_msgSend_875( + return __objc_msgSend_889( obj, sel, range, @@ -25014,14 +25345,14 @@ class SentryCocoa { ); } - late final __objc_msgSend_875Ptr = _lookup< + late final __objc_msgSend_889Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, _NSRange, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_875 = __objc_msgSend_875Ptr.asFunction< + late final __objc_msgSend_889 = __objc_msgSend_889Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, _NSRange, ffi.Pointer)>(); @@ -25034,14 +25365,14 @@ class SentryCocoa { late final _sel_correctionCheckingResultWithRange_replacementString_alternativeStrings_1 = _registerName1( "correctionCheckingResultWithRange:replacementString:alternativeStrings:"); - ffi.Pointer _objc_msgSend_876( + ffi.Pointer _objc_msgSend_890( ffi.Pointer obj, ffi.Pointer sel, _NSRange range, ffi.Pointer replacementString, ffi.Pointer alternativeStrings, ) { - return __objc_msgSend_876( + return __objc_msgSend_890( obj, sel, range, @@ -25050,7 +25381,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_876Ptr = _lookup< + late final __objc_msgSend_890Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, @@ -25058,7 +25389,7 @@ class SentryCocoa { _NSRange, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_876 = __objc_msgSend_876Ptr.asFunction< + late final __objc_msgSend_890 = __objc_msgSend_890Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, @@ -25069,14 +25400,14 @@ class SentryCocoa { late final _sel_regularExpressionCheckingResultWithRanges_count_regularExpression_1 = _registerName1( "regularExpressionCheckingResultWithRanges:count:regularExpression:"); - ffi.Pointer _objc_msgSend_877( + ffi.Pointer _objc_msgSend_891( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer<_NSRange> ranges, int count, ffi.Pointer regularExpression, ) { - return __objc_msgSend_877( + return __objc_msgSend_891( obj, sel, ranges, @@ -25085,7 +25416,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_877Ptr = _lookup< + late final __objc_msgSend_891Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, @@ -25093,7 +25424,7 @@ class SentryCocoa { ffi.Pointer<_NSRange>, ffi.UnsignedLong, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_877 = __objc_msgSend_877Ptr.asFunction< + late final __objc_msgSend_891 = __objc_msgSend_891Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, @@ -25107,55 +25438,55 @@ class SentryCocoa { _registerName1("transitInformationCheckingResultWithRange:components:"); late final _class_NSURLCache1 = _getClass1("NSURLCache"); late final _sel_sharedURLCache1 = _registerName1("sharedURLCache"); - ffi.Pointer _objc_msgSend_878( + ffi.Pointer _objc_msgSend_892( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_878( + return __objc_msgSend_892( obj, sel, ); } - late final __objc_msgSend_878Ptr = _lookup< + late final __objc_msgSend_892Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_878 = __objc_msgSend_878Ptr.asFunction< + late final __objc_msgSend_892 = __objc_msgSend_892Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>(); late final _sel_setSharedURLCache_1 = _registerName1("setSharedURLCache:"); - void _objc_msgSend_879( + void _objc_msgSend_893( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer value, ) { - return __objc_msgSend_879( + return __objc_msgSend_893( obj, sel, value, ); } - late final __objc_msgSend_879Ptr = _lookup< + late final __objc_msgSend_893Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_879 = __objc_msgSend_879Ptr.asFunction< + late final __objc_msgSend_893 = __objc_msgSend_893Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); late final _sel_initWithMemoryCapacity_diskCapacity_diskPath_1 = _registerName1("initWithMemoryCapacity:diskCapacity:diskPath:"); - instancetype _objc_msgSend_880( + instancetype _objc_msgSend_894( ffi.Pointer obj, ffi.Pointer sel, int memoryCapacity, int diskCapacity, ffi.Pointer path, ) { - return __objc_msgSend_880( + return __objc_msgSend_894( obj, sel, memoryCapacity, @@ -25164,7 +25495,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_880Ptr = _lookup< + late final __objc_msgSend_894Ptr = _lookup< ffi.NativeFunction< instancetype Function( ffi.Pointer, @@ -25172,20 +25503,20 @@ class SentryCocoa { ffi.UnsignedLong, ffi.UnsignedLong, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_880 = __objc_msgSend_880Ptr.asFunction< + late final __objc_msgSend_894 = __objc_msgSend_894Ptr.asFunction< instancetype Function(ffi.Pointer, ffi.Pointer, int, int, ffi.Pointer)>(); late final _sel_initWithMemoryCapacity_diskCapacity_directoryURL_1 = _registerName1("initWithMemoryCapacity:diskCapacity:directoryURL:"); - instancetype _objc_msgSend_881( + instancetype _objc_msgSend_895( ffi.Pointer obj, ffi.Pointer sel, int memoryCapacity, int diskCapacity, ffi.Pointer directoryURL, ) { - return __objc_msgSend_881( + return __objc_msgSend_895( obj, sel, memoryCapacity, @@ -25194,7 +25525,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_881Ptr = _lookup< + late final __objc_msgSend_895Ptr = _lookup< ffi.NativeFunction< instancetype Function( ffi.Pointer, @@ -25202,20 +25533,20 @@ class SentryCocoa { ffi.UnsignedLong, ffi.UnsignedLong, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_881 = __objc_msgSend_881Ptr.asFunction< + late final __objc_msgSend_895 = __objc_msgSend_895Ptr.asFunction< instancetype Function(ffi.Pointer, ffi.Pointer, int, int, ffi.Pointer)>(); late final _class_NSCachedURLResponse1 = _getClass1("NSCachedURLResponse"); late final _sel_initWithResponse_data_1 = _registerName1("initWithResponse:data:"); - instancetype _objc_msgSend_882( + instancetype _objc_msgSend_896( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer response, ffi.Pointer data, ) { - return __objc_msgSend_882( + return __objc_msgSend_896( obj, sel, response, @@ -25223,20 +25554,20 @@ class SentryCocoa { ); } - late final __objc_msgSend_882Ptr = _lookup< + late final __objc_msgSend_896Ptr = _lookup< ffi.NativeFunction< instancetype Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_882 = __objc_msgSend_882Ptr.asFunction< + late final __objc_msgSend_896 = __objc_msgSend_896Ptr.asFunction< instancetype Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); late final _sel_initWithResponse_data_userInfo_storagePolicy_1 = _registerName1("initWithResponse:data:userInfo:storagePolicy:"); - instancetype _objc_msgSend_883( + instancetype _objc_msgSend_897( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer response, @@ -25244,7 +25575,7 @@ class SentryCocoa { ffi.Pointer userInfo, int storagePolicy, ) { - return __objc_msgSend_883( + return __objc_msgSend_897( obj, sel, response, @@ -25254,7 +25585,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_883Ptr = _lookup< + late final __objc_msgSend_897Ptr = _lookup< ffi.NativeFunction< instancetype Function( ffi.Pointer, @@ -25263,7 +25594,7 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Int32)>>('objc_msgSend'); - late final __objc_msgSend_883 = __objc_msgSend_883Ptr.asFunction< + late final __objc_msgSend_897 = __objc_msgSend_897Ptr.asFunction< instancetype Function( ffi.Pointer, ffi.Pointer, @@ -25273,54 +25604,54 @@ class SentryCocoa { int)>(); late final _sel_storagePolicy1 = _registerName1("storagePolicy"); - int _objc_msgSend_884( + int _objc_msgSend_898( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_884( + return __objc_msgSend_898( obj, sel, ); } - late final __objc_msgSend_884Ptr = _lookup< + late final __objc_msgSend_898Ptr = _lookup< ffi.NativeFunction< ffi.Int32 Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_884 = __objc_msgSend_884Ptr.asFunction< + late final __objc_msgSend_898 = __objc_msgSend_898Ptr.asFunction< int Function(ffi.Pointer, ffi.Pointer)>(); late final _sel_cachedResponseForRequest_1 = _registerName1("cachedResponseForRequest:"); - ffi.Pointer _objc_msgSend_885( + ffi.Pointer _objc_msgSend_899( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer request, ) { - return __objc_msgSend_885( + return __objc_msgSend_899( obj, sel, request, ); } - late final __objc_msgSend_885Ptr = _lookup< + late final __objc_msgSend_899Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_885 = __objc_msgSend_885Ptr.asFunction< + late final __objc_msgSend_899 = __objc_msgSend_899Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); late final _sel_storeCachedResponse_forRequest_1 = _registerName1("storeCachedResponse:forRequest:"); - void _objc_msgSend_886( + void _objc_msgSend_900( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer cachedResponse, ffi.Pointer request, ) { - return __objc_msgSend_886( + return __objc_msgSend_900( obj, sel, cachedResponse, @@ -25328,36 +25659,36 @@ class SentryCocoa { ); } - late final __objc_msgSend_886Ptr = _lookup< + late final __objc_msgSend_900Ptr = _lookup< ffi.NativeFunction< ffi.Void Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_886 = __objc_msgSend_886Ptr.asFunction< + late final __objc_msgSend_900 = __objc_msgSend_900Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); late final _sel_removeCachedResponseForRequest_1 = _registerName1("removeCachedResponseForRequest:"); - void _objc_msgSend_887( + void _objc_msgSend_901( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer request, ) { - return __objc_msgSend_887( + return __objc_msgSend_901( obj, sel, request, ); } - late final __objc_msgSend_887Ptr = _lookup< + late final __objc_msgSend_901Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_887 = __objc_msgSend_887Ptr.asFunction< + late final __objc_msgSend_901 = __objc_msgSend_901Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); @@ -25374,13 +25705,13 @@ class SentryCocoa { late final _class_NSURLSessionDataTask1 = _getClass1("NSURLSessionDataTask"); late final _sel_storeCachedResponse_forDataTask_1 = _registerName1("storeCachedResponse:forDataTask:"); - void _objc_msgSend_888( + void _objc_msgSend_902( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer cachedResponse, ffi.Pointer dataTask, ) { - return __objc_msgSend_888( + return __objc_msgSend_902( obj, sel, cachedResponse, @@ -25388,26 +25719,26 @@ class SentryCocoa { ); } - late final __objc_msgSend_888Ptr = _lookup< + late final __objc_msgSend_902Ptr = _lookup< ffi.NativeFunction< ffi.Void Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_888 = __objc_msgSend_888Ptr.asFunction< + late final __objc_msgSend_902 = __objc_msgSend_902Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); late final _sel_getCachedResponseForDataTask_completionHandler_1 = _registerName1("getCachedResponseForDataTask:completionHandler:"); - void _objc_msgSend_889( + void _objc_msgSend_903( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer dataTask, ffi.Pointer<_ObjCBlock> completionHandler, ) { - return __objc_msgSend_889( + return __objc_msgSend_903( obj, sel, dataTask, @@ -25415,50 +25746,50 @@ class SentryCocoa { ); } - late final __objc_msgSend_889Ptr = _lookup< + late final __objc_msgSend_903Ptr = _lookup< ffi.NativeFunction< ffi.Void Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer<_ObjCBlock>)>>('objc_msgSend'); - late final __objc_msgSend_889 = __objc_msgSend_889Ptr.asFunction< + late final __objc_msgSend_903 = __objc_msgSend_903Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer<_ObjCBlock>)>(); late final _sel_removeCachedResponseForDataTask_1 = _registerName1("removeCachedResponseForDataTask:"); - void _objc_msgSend_890( + void _objc_msgSend_904( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer dataTask, ) { - return __objc_msgSend_890( + return __objc_msgSend_904( obj, sel, dataTask, ); } - late final __objc_msgSend_890Ptr = _lookup< + late final __objc_msgSend_904Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_890 = __objc_msgSend_890Ptr.asFunction< + late final __objc_msgSend_904 = __objc_msgSend_904Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); late final _class_NSURLConnection1 = _getClass1("NSURLConnection"); late final _sel_initWithRequest_delegate_startImmediately_1 = _registerName1("initWithRequest:delegate:startImmediately:"); - instancetype _objc_msgSend_891( + instancetype _objc_msgSend_905( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer request, ffi.Pointer delegate, bool startImmediately, ) { - return __objc_msgSend_891( + return __objc_msgSend_905( obj, sel, request, @@ -25467,7 +25798,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_891Ptr = _lookup< + late final __objc_msgSend_905Ptr = _lookup< ffi.NativeFunction< instancetype Function( ffi.Pointer, @@ -25475,19 +25806,19 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Bool)>>('objc_msgSend'); - late final __objc_msgSend_891 = __objc_msgSend_891Ptr.asFunction< + late final __objc_msgSend_905 = __objc_msgSend_905Ptr.asFunction< instancetype Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer, bool)>(); late final _sel_initWithRequest_delegate_1 = _registerName1("initWithRequest:delegate:"); - instancetype _objc_msgSend_892( + instancetype _objc_msgSend_906( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer request, ffi.Pointer delegate, ) { - return __objc_msgSend_892( + return __objc_msgSend_906( obj, sel, request, @@ -25495,26 +25826,26 @@ class SentryCocoa { ); } - late final __objc_msgSend_892Ptr = _lookup< + late final __objc_msgSend_906Ptr = _lookup< ffi.NativeFunction< instancetype Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_892 = __objc_msgSend_892Ptr.asFunction< + late final __objc_msgSend_906 = __objc_msgSend_906Ptr.asFunction< instancetype Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); late final _sel_connectionWithRequest_delegate_1 = _registerName1("connectionWithRequest:delegate:"); - ffi.Pointer _objc_msgSend_893( + ffi.Pointer _objc_msgSend_907( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer request, ffi.Pointer delegate, ) { - return __objc_msgSend_893( + return __objc_msgSend_907( obj, sel, request, @@ -25522,14 +25853,14 @@ class SentryCocoa { ); } - late final __objc_msgSend_893Ptr = _lookup< + late final __objc_msgSend_907Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_893 = __objc_msgSend_893Ptr.asFunction< + late final __objc_msgSend_907 = __objc_msgSend_907Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, @@ -25539,57 +25870,57 @@ class SentryCocoa { late final _sel_unscheduleFromRunLoop_forMode_1 = _registerName1("unscheduleFromRunLoop:forMode:"); late final _sel_setDelegateQueue_1 = _registerName1("setDelegateQueue:"); - void _objc_msgSend_894( + void _objc_msgSend_908( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer queue, ) { - return __objc_msgSend_894( + return __objc_msgSend_908( obj, sel, queue, ); } - late final __objc_msgSend_894Ptr = _lookup< + late final __objc_msgSend_908Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_894 = __objc_msgSend_894Ptr.asFunction< + late final __objc_msgSend_908 = __objc_msgSend_908Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); late final _sel_canHandleRequest_1 = _registerName1("canHandleRequest:"); - bool _objc_msgSend_895( + bool _objc_msgSend_909( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer request, ) { - return __objc_msgSend_895( + return __objc_msgSend_909( obj, sel, request, ); } - late final __objc_msgSend_895Ptr = _lookup< + late final __objc_msgSend_909Ptr = _lookup< ffi.NativeFunction< ffi.Bool Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_895 = __objc_msgSend_895Ptr.asFunction< + late final __objc_msgSend_909 = __objc_msgSend_909Ptr.asFunction< bool Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); late final _sel_sendSynchronousRequest_returningResponse_error_1 = _registerName1("sendSynchronousRequest:returningResponse:error:"); - ffi.Pointer _objc_msgSend_896( + ffi.Pointer _objc_msgSend_910( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer request, ffi.Pointer> response, ffi.Pointer> error, ) { - return __objc_msgSend_896( + return __objc_msgSend_910( obj, sel, request, @@ -25598,7 +25929,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_896Ptr = _lookup< + late final __objc_msgSend_910Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, @@ -25606,7 +25937,7 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer>, ffi.Pointer>)>>('objc_msgSend'); - late final __objc_msgSend_896 = __objc_msgSend_896Ptr.asFunction< + late final __objc_msgSend_910 = __objc_msgSend_910Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, @@ -25616,14 +25947,14 @@ class SentryCocoa { late final _sel_sendAsynchronousRequest_queue_completionHandler_1 = _registerName1("sendAsynchronousRequest:queue:completionHandler:"); - void _objc_msgSend_897( + void _objc_msgSend_911( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer request, ffi.Pointer queue, ffi.Pointer<_ObjCBlock> handler, ) { - return __objc_msgSend_897( + return __objc_msgSend_911( obj, sel, request, @@ -25632,7 +25963,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_897Ptr = _lookup< + late final __objc_msgSend_911Ptr = _lookup< ffi.NativeFunction< ffi.Void Function( ffi.Pointer, @@ -25640,7 +25971,7 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Pointer<_ObjCBlock>)>>('objc_msgSend'); - late final __objc_msgSend_897 = __objc_msgSend_897Ptr.asFunction< + late final __objc_msgSend_911 = __objc_msgSend_911Ptr.asFunction< void Function( ffi.Pointer, ffi.Pointer, @@ -25650,33 +25981,33 @@ class SentryCocoa { late final _class_NSURLCredential1 = _getClass1("NSURLCredential"); late final _sel_persistence1 = _registerName1("persistence"); - int _objc_msgSend_898( + int _objc_msgSend_912( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_898( + return __objc_msgSend_912( obj, sel, ); } - late final __objc_msgSend_898Ptr = _lookup< + late final __objc_msgSend_912Ptr = _lookup< ffi.NativeFunction< ffi.Int32 Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_898 = __objc_msgSend_898Ptr.asFunction< + late final __objc_msgSend_912 = __objc_msgSend_912Ptr.asFunction< int Function(ffi.Pointer, ffi.Pointer)>(); late final _sel_initWithUser_password_persistence_1 = _registerName1("initWithUser:password:persistence:"); - instancetype _objc_msgSend_899( + instancetype _objc_msgSend_913( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer user, ffi.Pointer password, int persistence, ) { - return __objc_msgSend_899( + return __objc_msgSend_913( obj, sel, user, @@ -25685,7 +26016,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_899Ptr = _lookup< + late final __objc_msgSend_913Ptr = _lookup< ffi.NativeFunction< instancetype Function( ffi.Pointer, @@ -25693,20 +26024,20 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Int32)>>('objc_msgSend'); - late final __objc_msgSend_899 = __objc_msgSend_899Ptr.asFunction< + late final __objc_msgSend_913 = __objc_msgSend_913Ptr.asFunction< instancetype Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer, int)>(); late final _sel_credentialWithUser_password_persistence_1 = _registerName1("credentialWithUser:password:persistence:"); - ffi.Pointer _objc_msgSend_900( + ffi.Pointer _objc_msgSend_914( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer user, ffi.Pointer password, int persistence, ) { - return __objc_msgSend_900( + return __objc_msgSend_914( obj, sel, user, @@ -25715,7 +26046,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_900Ptr = _lookup< + late final __objc_msgSend_914Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, @@ -25723,7 +26054,7 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Int32)>>('objc_msgSend'); - late final __objc_msgSend_900 = __objc_msgSend_900Ptr.asFunction< + late final __objc_msgSend_914 = __objc_msgSend_914Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, @@ -25734,14 +26065,14 @@ class SentryCocoa { late final _sel_hasPassword1 = _registerName1("hasPassword"); late final _sel_initWithIdentity_certificates_persistence_1 = _registerName1("initWithIdentity:certificates:persistence:"); - instancetype _objc_msgSend_901( + instancetype _objc_msgSend_915( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer<__SecIdentity> identity, ffi.Pointer certArray, int persistence, ) { - return __objc_msgSend_901( + return __objc_msgSend_915( obj, sel, identity, @@ -25750,7 +26081,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_901Ptr = _lookup< + late final __objc_msgSend_915Ptr = _lookup< ffi.NativeFunction< instancetype Function( ffi.Pointer, @@ -25758,20 +26089,20 @@ class SentryCocoa { ffi.Pointer<__SecIdentity>, ffi.Pointer, ffi.Int32)>>('objc_msgSend'); - late final __objc_msgSend_901 = __objc_msgSend_901Ptr.asFunction< + late final __objc_msgSend_915 = __objc_msgSend_915Ptr.asFunction< instancetype Function(ffi.Pointer, ffi.Pointer, ffi.Pointer<__SecIdentity>, ffi.Pointer, int)>(); late final _sel_credentialWithIdentity_certificates_persistence_1 = _registerName1("credentialWithIdentity:certificates:persistence:"); - ffi.Pointer _objc_msgSend_902( + ffi.Pointer _objc_msgSend_916( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer<__SecIdentity> identity, ffi.Pointer certArray, int persistence, ) { - return __objc_msgSend_902( + return __objc_msgSend_916( obj, sel, identity, @@ -25780,7 +26111,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_902Ptr = _lookup< + late final __objc_msgSend_916Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, @@ -25788,7 +26119,7 @@ class SentryCocoa { ffi.Pointer<__SecIdentity>, ffi.Pointer, ffi.Int32)>>('objc_msgSend'); - late final __objc_msgSend_902 = __objc_msgSend_902Ptr.asFunction< + late final __objc_msgSend_916 = __objc_msgSend_916Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, @@ -25797,71 +26128,71 @@ class SentryCocoa { int)>(); late final _sel_identity1 = _registerName1("identity"); - ffi.Pointer<__SecIdentity> _objc_msgSend_903( + ffi.Pointer<__SecIdentity> _objc_msgSend_917( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_903( + return __objc_msgSend_917( obj, sel, ); } - late final __objc_msgSend_903Ptr = _lookup< + late final __objc_msgSend_917Ptr = _lookup< ffi.NativeFunction< ffi.Pointer<__SecIdentity> Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_903 = __objc_msgSend_903Ptr.asFunction< + late final __objc_msgSend_917 = __objc_msgSend_917Ptr.asFunction< ffi.Pointer<__SecIdentity> Function( ffi.Pointer, ffi.Pointer)>(); late final _sel_certificates1 = _registerName1("certificates"); late final _sel_initWithTrust_1 = _registerName1("initWithTrust:"); - instancetype _objc_msgSend_904( + instancetype _objc_msgSend_918( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer<__SecTrust> trust, ) { - return __objc_msgSend_904( + return __objc_msgSend_918( obj, sel, trust, ); } - late final __objc_msgSend_904Ptr = _lookup< + late final __objc_msgSend_918Ptr = _lookup< ffi.NativeFunction< instancetype Function(ffi.Pointer, ffi.Pointer, ffi.Pointer<__SecTrust>)>>('objc_msgSend'); - late final __objc_msgSend_904 = __objc_msgSend_904Ptr.asFunction< + late final __objc_msgSend_918 = __objc_msgSend_918Ptr.asFunction< instancetype Function(ffi.Pointer, ffi.Pointer, ffi.Pointer<__SecTrust>)>(); late final _sel_credentialForTrust_1 = _registerName1("credentialForTrust:"); - ffi.Pointer _objc_msgSend_905( + ffi.Pointer _objc_msgSend_919( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer<__SecTrust> trust, ) { - return __objc_msgSend_905( + return __objc_msgSend_919( obj, sel, trust, ); } - late final __objc_msgSend_905Ptr = _lookup< + late final __objc_msgSend_919Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer<__SecTrust>)>>('objc_msgSend'); - late final __objc_msgSend_905 = __objc_msgSend_905Ptr.asFunction< + late final __objc_msgSend_919 = __objc_msgSend_919Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer<__SecTrust>)>(); late final _class_NSURLProtectionSpace1 = _getClass1("NSURLProtectionSpace"); late final _sel_initWithHost_port_protocol_realm_authenticationMethod_1 = _registerName1("initWithHost:port:protocol:realm:authenticationMethod:"); - instancetype _objc_msgSend_906( + instancetype _objc_msgSend_920( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer host, @@ -25870,7 +26201,7 @@ class SentryCocoa { ffi.Pointer realm, ffi.Pointer authenticationMethod, ) { - return __objc_msgSend_906( + return __objc_msgSend_920( obj, sel, host, @@ -25881,7 +26212,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_906Ptr = _lookup< + late final __objc_msgSend_920Ptr = _lookup< ffi.NativeFunction< instancetype Function( ffi.Pointer, @@ -25891,7 +26222,7 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_906 = __objc_msgSend_906Ptr.asFunction< + late final __objc_msgSend_920 = __objc_msgSend_920Ptr.asFunction< instancetype Function( ffi.Pointer, ffi.Pointer, @@ -25913,21 +26244,21 @@ class SentryCocoa { _registerName1("authenticationMethod"); late final _sel_distinguishedNames1 = _registerName1("distinguishedNames"); late final _sel_serverTrust1 = _registerName1("serverTrust"); - ffi.Pointer<__SecTrust> _objc_msgSend_907( + ffi.Pointer<__SecTrust> _objc_msgSend_921( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_907( + return __objc_msgSend_921( obj, sel, ); } - late final __objc_msgSend_907Ptr = _lookup< + late final __objc_msgSend_921Ptr = _lookup< ffi.NativeFunction< ffi.Pointer<__SecTrust> Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_907 = __objc_msgSend_907Ptr.asFunction< + late final __objc_msgSend_921 = __objc_msgSend_921Ptr.asFunction< ffi.Pointer<__SecTrust> Function( ffi.Pointer, ffi.Pointer)>(); @@ -25935,56 +26266,56 @@ class SentryCocoa { _getClass1("NSURLCredentialStorage"); late final _sel_sharedCredentialStorage1 = _registerName1("sharedCredentialStorage"); - ffi.Pointer _objc_msgSend_908( + ffi.Pointer _objc_msgSend_922( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_908( + return __objc_msgSend_922( obj, sel, ); } - late final __objc_msgSend_908Ptr = _lookup< + late final __objc_msgSend_922Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_908 = __objc_msgSend_908Ptr.asFunction< + late final __objc_msgSend_922 = __objc_msgSend_922Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>(); late final _sel_credentialsForProtectionSpace_1 = _registerName1("credentialsForProtectionSpace:"); - ffi.Pointer _objc_msgSend_909( + ffi.Pointer _objc_msgSend_923( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer space, ) { - return __objc_msgSend_909( + return __objc_msgSend_923( obj, sel, space, ); } - late final __objc_msgSend_909Ptr = _lookup< + late final __objc_msgSend_923Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_909 = __objc_msgSend_909Ptr.asFunction< + late final __objc_msgSend_923 = __objc_msgSend_923Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); late final _sel_allCredentials1 = _registerName1("allCredentials"); late final _sel_setCredential_forProtectionSpace_1 = _registerName1("setCredential:forProtectionSpace:"); - void _objc_msgSend_910( + void _objc_msgSend_924( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer credential, ffi.Pointer space, ) { - return __objc_msgSend_910( + return __objc_msgSend_924( obj, sel, credential, @@ -25992,14 +26323,14 @@ class SentryCocoa { ); } - late final __objc_msgSend_910Ptr = _lookup< + late final __objc_msgSend_924Ptr = _lookup< ffi.NativeFunction< ffi.Void Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_910 = __objc_msgSend_910Ptr.asFunction< + late final __objc_msgSend_924 = __objc_msgSend_924Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); @@ -26007,14 +26338,14 @@ class SentryCocoa { _registerName1("removeCredential:forProtectionSpace:"); late final _sel_removeCredential_forProtectionSpace_options_1 = _registerName1("removeCredential:forProtectionSpace:options:"); - void _objc_msgSend_911( + void _objc_msgSend_925( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer credential, ffi.Pointer space, ffi.Pointer options, ) { - return __objc_msgSend_911( + return __objc_msgSend_925( obj, sel, credential, @@ -26023,7 +26354,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_911Ptr = _lookup< + late final __objc_msgSend_925Ptr = _lookup< ffi.NativeFunction< ffi.Void Function( ffi.Pointer, @@ -26031,7 +26362,7 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_911 = __objc_msgSend_911Ptr.asFunction< + late final __objc_msgSend_925 = __objc_msgSend_925Ptr.asFunction< void Function( ffi.Pointer, ffi.Pointer, @@ -26041,23 +26372,23 @@ class SentryCocoa { late final _sel_defaultCredentialForProtectionSpace_1 = _registerName1("defaultCredentialForProtectionSpace:"); - ffi.Pointer _objc_msgSend_912( + ffi.Pointer _objc_msgSend_926( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer space, ) { - return __objc_msgSend_912( + return __objc_msgSend_926( obj, sel, space, ); } - late final __objc_msgSend_912Ptr = _lookup< + late final __objc_msgSend_926Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_912 = __objc_msgSend_912Ptr.asFunction< + late final __objc_msgSend_926 = __objc_msgSend_926Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); @@ -26066,14 +26397,14 @@ class SentryCocoa { late final _sel_getCredentialsForProtectionSpace_task_completionHandler_1 = _registerName1( "getCredentialsForProtectionSpace:task:completionHandler:"); - void _objc_msgSend_913( + void _objc_msgSend_927( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer protectionSpace, ffi.Pointer task, ffi.Pointer<_ObjCBlock> completionHandler, ) { - return __objc_msgSend_913( + return __objc_msgSend_927( obj, sel, protectionSpace, @@ -26082,7 +26413,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_913Ptr = _lookup< + late final __objc_msgSend_927Ptr = _lookup< ffi.NativeFunction< ffi.Void Function( ffi.Pointer, @@ -26090,7 +26421,7 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Pointer<_ObjCBlock>)>>('objc_msgSend'); - late final __objc_msgSend_913 = __objc_msgSend_913Ptr.asFunction< + late final __objc_msgSend_927 = __objc_msgSend_927Ptr.asFunction< void Function( ffi.Pointer, ffi.Pointer, @@ -26100,14 +26431,14 @@ class SentryCocoa { late final _sel_setCredential_forProtectionSpace_task_1 = _registerName1("setCredential:forProtectionSpace:task:"); - void _objc_msgSend_914( + void _objc_msgSend_928( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer credential, ffi.Pointer protectionSpace, ffi.Pointer task, ) { - return __objc_msgSend_914( + return __objc_msgSend_928( obj, sel, credential, @@ -26116,7 +26447,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_914Ptr = _lookup< + late final __objc_msgSend_928Ptr = _lookup< ffi.NativeFunction< ffi.Void Function( ffi.Pointer, @@ -26124,7 +26455,7 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_914 = __objc_msgSend_914Ptr.asFunction< + late final __objc_msgSend_928 = __objc_msgSend_928Ptr.asFunction< void Function( ffi.Pointer, ffi.Pointer, @@ -26134,7 +26465,7 @@ class SentryCocoa { late final _sel_removeCredential_forProtectionSpace_options_task_1 = _registerName1("removeCredential:forProtectionSpace:options:task:"); - void _objc_msgSend_915( + void _objc_msgSend_929( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer credential, @@ -26142,7 +26473,7 @@ class SentryCocoa { ffi.Pointer options, ffi.Pointer task, ) { - return __objc_msgSend_915( + return __objc_msgSend_929( obj, sel, credential, @@ -26152,7 +26483,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_915Ptr = _lookup< + late final __objc_msgSend_929Ptr = _lookup< ffi.NativeFunction< ffi.Void Function( ffi.Pointer, @@ -26161,7 +26492,7 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_915 = __objc_msgSend_915Ptr.asFunction< + late final __objc_msgSend_929 = __objc_msgSend_929Ptr.asFunction< void Function( ffi.Pointer, ffi.Pointer, @@ -26173,14 +26504,14 @@ class SentryCocoa { late final _sel_getDefaultCredentialForProtectionSpace_task_completionHandler_1 = _registerName1( "getDefaultCredentialForProtectionSpace:task:completionHandler:"); - void _objc_msgSend_916( + void _objc_msgSend_930( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer space, ffi.Pointer task, ffi.Pointer<_ObjCBlock> completionHandler, ) { - return __objc_msgSend_916( + return __objc_msgSend_930( obj, sel, space, @@ -26189,7 +26520,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_916Ptr = _lookup< + late final __objc_msgSend_930Ptr = _lookup< ffi.NativeFunction< ffi.Void Function( ffi.Pointer, @@ -26197,7 +26528,7 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Pointer<_ObjCBlock>)>>('objc_msgSend'); - late final __objc_msgSend_916 = __objc_msgSend_916Ptr.asFunction< + late final __objc_msgSend_930 = __objc_msgSend_930Ptr.asFunction< void Function( ffi.Pointer, ffi.Pointer, @@ -26210,14 +26541,14 @@ class SentryCocoa { late final _class_NSURLProtocol1 = _getClass1("NSURLProtocol"); late final _sel_initWithRequest_cachedResponse_client_1 = _registerName1("initWithRequest:cachedResponse:client:"); - instancetype _objc_msgSend_917( + instancetype _objc_msgSend_931( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer request, ffi.Pointer cachedResponse, ffi.Pointer client, ) { - return __objc_msgSend_917( + return __objc_msgSend_931( obj, sel, request, @@ -26226,7 +26557,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_917Ptr = _lookup< + late final __objc_msgSend_931Ptr = _lookup< ffi.NativeFunction< instancetype Function( ffi.Pointer, @@ -26234,7 +26565,7 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_917 = __objc_msgSend_917Ptr.asFunction< + late final __objc_msgSend_931 = __objc_msgSend_931Ptr.asFunction< instancetype Function( ffi.Pointer, ffi.Pointer, @@ -26245,56 +26576,56 @@ class SentryCocoa { late final _sel_client1 = _registerName1("client"); late final _sel_request1 = _registerName1("request"); late final _sel_cachedResponse1 = _registerName1("cachedResponse"); - ffi.Pointer _objc_msgSend_918( + ffi.Pointer _objc_msgSend_932( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_918( + return __objc_msgSend_932( obj, sel, ); } - late final __objc_msgSend_918Ptr = _lookup< + late final __objc_msgSend_932Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_918 = __objc_msgSend_918Ptr.asFunction< + late final __objc_msgSend_932 = __objc_msgSend_932Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>(); late final _sel_canInitWithRequest_1 = _registerName1("canInitWithRequest:"); late final _sel_canonicalRequestForRequest_1 = _registerName1("canonicalRequestForRequest:"); - ffi.Pointer _objc_msgSend_919( + ffi.Pointer _objc_msgSend_933( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer request, ) { - return __objc_msgSend_919( + return __objc_msgSend_933( obj, sel, request, ); } - late final __objc_msgSend_919Ptr = _lookup< + late final __objc_msgSend_933Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_919 = __objc_msgSend_919Ptr.asFunction< + late final __objc_msgSend_933 = __objc_msgSend_933Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); late final _sel_requestIsCacheEquivalent_toRequest_1 = _registerName1("requestIsCacheEquivalent:toRequest:"); - bool _objc_msgSend_920( + bool _objc_msgSend_934( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer a, ffi.Pointer b, ) { - return __objc_msgSend_920( + return __objc_msgSend_934( obj, sel, a, @@ -26302,14 +26633,14 @@ class SentryCocoa { ); } - late final __objc_msgSend_920Ptr = _lookup< + late final __objc_msgSend_934Ptr = _lookup< ffi.NativeFunction< ffi.Bool Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_920 = __objc_msgSend_920Ptr.asFunction< + late final __objc_msgSend_934 = __objc_msgSend_934Ptr.asFunction< bool Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); @@ -26317,13 +26648,13 @@ class SentryCocoa { late final _sel_stopLoading1 = _registerName1("stopLoading"); late final _sel_propertyForKey_inRequest_1 = _registerName1("propertyForKey:inRequest:"); - ffi.Pointer _objc_msgSend_921( + ffi.Pointer _objc_msgSend_935( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer key, ffi.Pointer request, ) { - return __objc_msgSend_921( + return __objc_msgSend_935( obj, sel, key, @@ -26331,14 +26662,14 @@ class SentryCocoa { ); } - late final __objc_msgSend_921Ptr = _lookup< + late final __objc_msgSend_935Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_921 = __objc_msgSend_921Ptr.asFunction< + late final __objc_msgSend_935 = __objc_msgSend_935Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, @@ -26348,46 +26679,46 @@ class SentryCocoa { late final _class_NSMutableURLRequest1 = _getClass1("NSMutableURLRequest"); late final _sel_setURL_1 = _registerName1("setURL:"); late final _sel_setCachePolicy_1 = _registerName1("setCachePolicy:"); - void _objc_msgSend_922( + void _objc_msgSend_936( ffi.Pointer obj, ffi.Pointer sel, int value, ) { - return __objc_msgSend_922( + return __objc_msgSend_936( obj, sel, value, ); } - late final __objc_msgSend_922Ptr = _lookup< + late final __objc_msgSend_936Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Int32)>>('objc_msgSend'); - late final __objc_msgSend_922 = __objc_msgSend_922Ptr.asFunction< + late final __objc_msgSend_936 = __objc_msgSend_936Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, int)>(); late final _sel_setTimeoutInterval_1 = _registerName1("setTimeoutInterval:"); late final _sel_setMainDocumentURL_1 = _registerName1("setMainDocumentURL:"); late final _sel_setNetworkServiceType_1 = _registerName1("setNetworkServiceType:"); - void _objc_msgSend_923( + void _objc_msgSend_937( ffi.Pointer obj, ffi.Pointer sel, int value, ) { - return __objc_msgSend_923( + return __objc_msgSend_937( obj, sel, value, ); } - late final __objc_msgSend_923Ptr = _lookup< + late final __objc_msgSend_937Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Int32)>>('objc_msgSend'); - late final __objc_msgSend_923 = __objc_msgSend_923Ptr.asFunction< + late final __objc_msgSend_937 = __objc_msgSend_937Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, int)>(); late final _sel_setAllowsCellularAccess_1 = @@ -26399,23 +26730,23 @@ class SentryCocoa { late final _sel_setAssumesHTTP3Capable_1 = _registerName1("setAssumesHTTP3Capable:"); late final _sel_setAttribution_1 = _registerName1("setAttribution:"); - void _objc_msgSend_924( + void _objc_msgSend_938( ffi.Pointer obj, ffi.Pointer sel, int value, ) { - return __objc_msgSend_924( + return __objc_msgSend_938( obj, sel, value, ); } - late final __objc_msgSend_924Ptr = _lookup< + late final __objc_msgSend_938Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Int32)>>('objc_msgSend'); - late final __objc_msgSend_924 = __objc_msgSend_924Ptr.asFunction< + late final __objc_msgSend_938 = __objc_msgSend_938Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, int)>(); late final _sel_setRequiresDNSSECValidation_1 = @@ -26428,44 +26759,44 @@ class SentryCocoa { late final _sel_addValue_forHTTPHeaderField_1 = _registerName1("addValue:forHTTPHeaderField:"); late final _sel_setHTTPBody_1 = _registerName1("setHTTPBody:"); - void _objc_msgSend_925( + void _objc_msgSend_939( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer value, ) { - return __objc_msgSend_925( + return __objc_msgSend_939( obj, sel, value, ); } - late final __objc_msgSend_925Ptr = _lookup< + late final __objc_msgSend_939Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_925 = __objc_msgSend_925Ptr.asFunction< + late final __objc_msgSend_939 = __objc_msgSend_939Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); late final _sel_setHTTPBodyStream_1 = _registerName1("setHTTPBodyStream:"); - void _objc_msgSend_926( + void _objc_msgSend_940( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer value, ) { - return __objc_msgSend_926( + return __objc_msgSend_940( obj, sel, value, ); } - late final __objc_msgSend_926Ptr = _lookup< + late final __objc_msgSend_940Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_926 = __objc_msgSend_926Ptr.asFunction< + late final __objc_msgSend_940 = __objc_msgSend_940Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); @@ -26475,14 +26806,14 @@ class SentryCocoa { _registerName1("setHTTPShouldUsePipelining:"); late final _sel_setProperty_forKey_inRequest_1 = _registerName1("setProperty:forKey:inRequest:"); - void _objc_msgSend_927( + void _objc_msgSend_941( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer value, ffi.Pointer key, ffi.Pointer request, ) { - return __objc_msgSend_927( + return __objc_msgSend_941( obj, sel, value, @@ -26491,7 +26822,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_927Ptr = _lookup< + late final __objc_msgSend_941Ptr = _lookup< ffi.NativeFunction< ffi.Void Function( ffi.Pointer, @@ -26499,7 +26830,7 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_927 = __objc_msgSend_927Ptr.asFunction< + late final __objc_msgSend_941 = __objc_msgSend_941Ptr.asFunction< void Function( ffi.Pointer, ffi.Pointer, @@ -26509,13 +26840,13 @@ class SentryCocoa { late final _sel_removePropertyForKey_inRequest_1 = _registerName1("removePropertyForKey:inRequest:"); - void _objc_msgSend_928( + void _objc_msgSend_942( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer key, ffi.Pointer request, ) { - return __objc_msgSend_928( + return __objc_msgSend_942( obj, sel, key, @@ -26523,50 +26854,50 @@ class SentryCocoa { ); } - late final __objc_msgSend_928Ptr = _lookup< + late final __objc_msgSend_942Ptr = _lookup< ffi.NativeFunction< ffi.Void Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_928 = __objc_msgSend_928Ptr.asFunction< + late final __objc_msgSend_942 = __objc_msgSend_942Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); late final _sel_registerClass_1 = _registerName1("registerClass:"); late final _sel_unregisterClass_1 = _registerName1("unregisterClass:"); late final _sel_canInitWithTask_1 = _registerName1("canInitWithTask:"); - bool _objc_msgSend_929( + bool _objc_msgSend_943( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer task, ) { - return __objc_msgSend_929( + return __objc_msgSend_943( obj, sel, task, ); } - late final __objc_msgSend_929Ptr = _lookup< + late final __objc_msgSend_943Ptr = _lookup< ffi.NativeFunction< ffi.Bool Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_929 = __objc_msgSend_929Ptr.asFunction< + late final __objc_msgSend_943 = __objc_msgSend_943Ptr.asFunction< bool Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); late final _sel_initWithTask_cachedResponse_client_1 = _registerName1("initWithTask:cachedResponse:client:"); - instancetype _objc_msgSend_930( + instancetype _objc_msgSend_944( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer task, ffi.Pointer cachedResponse, ffi.Pointer client, ) { - return __objc_msgSend_930( + return __objc_msgSend_944( obj, sel, task, @@ -26575,7 +26906,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_930Ptr = _lookup< + late final __objc_msgSend_944Ptr = _lookup< ffi.NativeFunction< instancetype Function( ffi.Pointer, @@ -26583,7 +26914,7 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_930 = __objc_msgSend_930Ptr.asFunction< + late final __objc_msgSend_944 = __objc_msgSend_944Ptr.asFunction< instancetype Function( ffi.Pointer, ffi.Pointer, @@ -26592,43 +26923,43 @@ class SentryCocoa { ffi.Pointer)>(); late final _sel_task1 = _registerName1("task"); - ffi.Pointer _objc_msgSend_931( + ffi.Pointer _objc_msgSend_945( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_931( + return __objc_msgSend_945( obj, sel, ); } - late final __objc_msgSend_931Ptr = _lookup< + late final __objc_msgSend_945Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_931 = __objc_msgSend_931Ptr.asFunction< + late final __objc_msgSend_945 = __objc_msgSend_945Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>(); late final _class_NSXMLParser1 = _getClass1("NSXMLParser"); late final _sel_initWithStream_1 = _registerName1("initWithStream:"); - instancetype _objc_msgSend_932( + instancetype _objc_msgSend_946( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer stream, ) { - return __objc_msgSend_932( + return __objc_msgSend_946( obj, sel, stream, ); } - late final __objc_msgSend_932Ptr = _lookup< + late final __objc_msgSend_946Ptr = _lookup< ffi.NativeFunction< instancetype Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_932 = __objc_msgSend_932Ptr.asFunction< + late final __objc_msgSend_946 = __objc_msgSend_946Ptr.asFunction< instancetype Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); @@ -26642,65 +26973,65 @@ class SentryCocoa { _registerName1("setShouldReportNamespacePrefixes:"); late final _sel_externalEntityResolvingPolicy1 = _registerName1("externalEntityResolvingPolicy"); - int _objc_msgSend_933( + int _objc_msgSend_947( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_933( + return __objc_msgSend_947( obj, sel, ); } - late final __objc_msgSend_933Ptr = _lookup< + late final __objc_msgSend_947Ptr = _lookup< ffi.NativeFunction< ffi.Int32 Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_933 = __objc_msgSend_933Ptr.asFunction< + late final __objc_msgSend_947 = __objc_msgSend_947Ptr.asFunction< int Function(ffi.Pointer, ffi.Pointer)>(); late final _sel_setExternalEntityResolvingPolicy_1 = _registerName1("setExternalEntityResolvingPolicy:"); - void _objc_msgSend_934( + void _objc_msgSend_948( ffi.Pointer obj, ffi.Pointer sel, int value, ) { - return __objc_msgSend_934( + return __objc_msgSend_948( obj, sel, value, ); } - late final __objc_msgSend_934Ptr = _lookup< + late final __objc_msgSend_948Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Int32)>>('objc_msgSend'); - late final __objc_msgSend_934 = __objc_msgSend_934Ptr.asFunction< + late final __objc_msgSend_948 = __objc_msgSend_948Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, int)>(); late final _sel_allowedExternalEntityURLs1 = _registerName1("allowedExternalEntityURLs"); late final _sel_setAllowedExternalEntityURLs_1 = _registerName1("setAllowedExternalEntityURLs:"); - void _objc_msgSend_935( + void _objc_msgSend_949( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer value, ) { - return __objc_msgSend_935( + return __objc_msgSend_949( obj, sel, value, ); } - late final __objc_msgSend_935Ptr = _lookup< + late final __objc_msgSend_949Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_935 = __objc_msgSend_935Ptr.asFunction< + late final __objc_msgSend_949 = __objc_msgSend_949Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); @@ -26718,14 +27049,14 @@ class SentryCocoa { late final _class_NSFileWrapper1 = _getClass1("NSFileWrapper"); late final _sel_initWithURL_options_error_1 = _registerName1("initWithURL:options:error:"); - instancetype _objc_msgSend_936( + instancetype _objc_msgSend_950( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer url, int options, ffi.Pointer> outError, ) { - return __objc_msgSend_936( + return __objc_msgSend_950( obj, sel, url, @@ -26734,7 +27065,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_936Ptr = _lookup< + late final __objc_msgSend_950Ptr = _lookup< ffi.NativeFunction< instancetype Function( ffi.Pointer, @@ -26742,7 +27073,7 @@ class SentryCocoa { ffi.Pointer, ffi.Int32, ffi.Pointer>)>>('objc_msgSend'); - late final __objc_msgSend_936 = __objc_msgSend_936Ptr.asFunction< + late final __objc_msgSend_950 = __objc_msgSend_950Ptr.asFunction< instancetype Function( ffi.Pointer, ffi.Pointer, @@ -26772,14 +27103,14 @@ class SentryCocoa { _registerName1("matchesContentsOfURL:"); late final _sel_readFromURL_options_error_1 = _registerName1("readFromURL:options:error:"); - bool _objc_msgSend_937( + bool _objc_msgSend_951( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer url, int options, ffi.Pointer> outError, ) { - return __objc_msgSend_937( + return __objc_msgSend_951( obj, sel, url, @@ -26788,7 +27119,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_937Ptr = _lookup< + late final __objc_msgSend_951Ptr = _lookup< ffi.NativeFunction< ffi.Bool Function( ffi.Pointer, @@ -26796,7 +27127,7 @@ class SentryCocoa { ffi.Pointer, ffi.Int32, ffi.Pointer>)>>('objc_msgSend'); - late final __objc_msgSend_937 = __objc_msgSend_937Ptr.asFunction< + late final __objc_msgSend_951 = __objc_msgSend_951Ptr.asFunction< bool Function( ffi.Pointer, ffi.Pointer, @@ -26806,7 +27137,7 @@ class SentryCocoa { late final _sel_writeToURL_options_originalContentsURL_error_1 = _registerName1("writeToURL:options:originalContentsURL:error:"); - bool _objc_msgSend_938( + bool _objc_msgSend_952( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer url, @@ -26814,7 +27145,7 @@ class SentryCocoa { ffi.Pointer originalContentsURL, ffi.Pointer> outError, ) { - return __objc_msgSend_938( + return __objc_msgSend_952( obj, sel, url, @@ -26824,7 +27155,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_938Ptr = _lookup< + late final __objc_msgSend_952Ptr = _lookup< ffi.NativeFunction< ffi.Bool Function( ffi.Pointer, @@ -26833,7 +27164,7 @@ class SentryCocoa { ffi.Int32, ffi.Pointer, ffi.Pointer>)>>('objc_msgSend'); - late final __objc_msgSend_938 = __objc_msgSend_938Ptr.asFunction< + late final __objc_msgSend_952 = __objc_msgSend_952Ptr.asFunction< bool Function( ffi.Pointer, ffi.Pointer, @@ -26845,35 +27176,35 @@ class SentryCocoa { late final _sel_serializedRepresentation1 = _registerName1("serializedRepresentation"); late final _sel_addFileWrapper_1 = _registerName1("addFileWrapper:"); - ffi.Pointer _objc_msgSend_939( + ffi.Pointer _objc_msgSend_953( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer child, ) { - return __objc_msgSend_939( + return __objc_msgSend_953( obj, sel, child, ); } - late final __objc_msgSend_939Ptr = _lookup< + late final __objc_msgSend_953Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_939 = __objc_msgSend_939Ptr.asFunction< + late final __objc_msgSend_953 = __objc_msgSend_953Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); late final _sel_addRegularFileWithContents_preferredFilename_1 = _registerName1("addRegularFileWithContents:preferredFilename:"); - ffi.Pointer _objc_msgSend_940( + ffi.Pointer _objc_msgSend_954( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer data, ffi.Pointer fileName, ) { - return __objc_msgSend_940( + return __objc_msgSend_954( obj, sel, data, @@ -26881,14 +27212,14 @@ class SentryCocoa { ); } - late final __objc_msgSend_940Ptr = _lookup< + late final __objc_msgSend_954Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_940 = __objc_msgSend_940Ptr.asFunction< + late final __objc_msgSend_954 = __objc_msgSend_954Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, @@ -26896,23 +27227,23 @@ class SentryCocoa { ffi.Pointer)>(); late final _sel_removeFileWrapper_1 = _registerName1("removeFileWrapper:"); - void _objc_msgSend_941( + void _objc_msgSend_955( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer child, ) { - return __objc_msgSend_941( + return __objc_msgSend_955( obj, sel, child, ); } - late final __objc_msgSend_941Ptr = _lookup< + late final __objc_msgSend_955Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_941 = __objc_msgSend_941Ptr.asFunction< + late final __objc_msgSend_955 = __objc_msgSend_955Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); @@ -26928,14 +27259,14 @@ class SentryCocoa { late final _sel_updateFromPath_1 = _registerName1("updateFromPath:"); late final _sel_writeToFile_atomically_updateFilenames_1 = _registerName1("writeToFile:atomically:updateFilenames:"); - bool _objc_msgSend_942( + bool _objc_msgSend_956( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer path, bool atomicFlag, bool updateFilenamesFlag, ) { - return __objc_msgSend_942( + return __objc_msgSend_956( obj, sel, path, @@ -26944,11 +27275,11 @@ class SentryCocoa { ); } - late final __objc_msgSend_942Ptr = _lookup< + late final __objc_msgSend_956Ptr = _lookup< ffi.NativeFunction< ffi.Bool Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Bool, ffi.Bool)>>('objc_msgSend'); - late final __objc_msgSend_942 = __objc_msgSend_942Ptr.asFunction< + late final __objc_msgSend_956 = __objc_msgSend_956Ptr.asFunction< bool Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, bool, bool)>(); @@ -26959,21 +27290,21 @@ class SentryCocoa { _registerName1("symbolicLinkDestination"); late final _class_NSURLSession1 = _getClass1("NSURLSession"); late final _sel_sharedSession1 = _registerName1("sharedSession"); - ffi.Pointer _objc_msgSend_943( + ffi.Pointer _objc_msgSend_957( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_943( + return __objc_msgSend_957( obj, sel, ); } - late final __objc_msgSend_943Ptr = _lookup< + late final __objc_msgSend_957Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_943 = __objc_msgSend_943Ptr.asFunction< + late final __objc_msgSend_957 = __objc_msgSend_957Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>(); @@ -26981,21 +27312,21 @@ class SentryCocoa { _getClass1("NSURLSessionConfiguration"); late final _sel_defaultSessionConfiguration1 = _registerName1("defaultSessionConfiguration"); - ffi.Pointer _objc_msgSend_944( + ffi.Pointer _objc_msgSend_958( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_944( + return __objc_msgSend_958( obj, sel, ); } - late final __objc_msgSend_944Ptr = _lookup< + late final __objc_msgSend_958Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_944 = __objc_msgSend_944Ptr.asFunction< + late final __objc_msgSend_958 = __objc_msgSend_958Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>(); @@ -27003,23 +27334,23 @@ class SentryCocoa { _registerName1("ephemeralSessionConfiguration"); late final _sel_backgroundSessionConfigurationWithIdentifier_1 = _registerName1("backgroundSessionConfigurationWithIdentifier:"); - ffi.Pointer _objc_msgSend_945( + ffi.Pointer _objc_msgSend_959( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer identifier, ) { - return __objc_msgSend_945( + return __objc_msgSend_959( obj, sel, identifier, ); } - late final __objc_msgSend_945Ptr = _lookup< + late final __objc_msgSend_959Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_945 = __objc_msgSend_945Ptr.asFunction< + late final __objc_msgSend_959 = __objc_msgSend_959Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); @@ -27055,42 +27386,42 @@ class SentryCocoa { _registerName1("setConnectionProxyDictionary:"); late final _sel_TLSMinimumSupportedProtocol1 = _registerName1("TLSMinimumSupportedProtocol"); - int _objc_msgSend_946( + int _objc_msgSend_960( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_946( + return __objc_msgSend_960( obj, sel, ); } - late final __objc_msgSend_946Ptr = _lookup< + late final __objc_msgSend_960Ptr = _lookup< ffi.NativeFunction< ffi.Int32 Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_946 = __objc_msgSend_946Ptr.asFunction< + late final __objc_msgSend_960 = __objc_msgSend_960Ptr.asFunction< int Function(ffi.Pointer, ffi.Pointer)>(); late final _sel_setTLSMinimumSupportedProtocol_1 = _registerName1("setTLSMinimumSupportedProtocol:"); - void _objc_msgSend_947( + void _objc_msgSend_961( ffi.Pointer obj, ffi.Pointer sel, int value, ) { - return __objc_msgSend_947( + return __objc_msgSend_961( obj, sel, value, ); } - late final __objc_msgSend_947Ptr = _lookup< + late final __objc_msgSend_961Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Int32)>>('objc_msgSend'); - late final __objc_msgSend_947 = __objc_msgSend_947Ptr.asFunction< + late final __objc_msgSend_961 = __objc_msgSend_961Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, int)>(); late final _sel_TLSMaximumSupportedProtocol1 = @@ -27099,42 +27430,42 @@ class SentryCocoa { _registerName1("setTLSMaximumSupportedProtocol:"); late final _sel_TLSMinimumSupportedProtocolVersion1 = _registerName1("TLSMinimumSupportedProtocolVersion"); - int _objc_msgSend_948( + int _objc_msgSend_962( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_948( + return __objc_msgSend_962( obj, sel, ); } - late final __objc_msgSend_948Ptr = _lookup< + late final __objc_msgSend_962Ptr = _lookup< ffi.NativeFunction< ffi.Int32 Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_948 = __objc_msgSend_948Ptr.asFunction< + late final __objc_msgSend_962 = __objc_msgSend_962Ptr.asFunction< int Function(ffi.Pointer, ffi.Pointer)>(); late final _sel_setTLSMinimumSupportedProtocolVersion_1 = _registerName1("setTLSMinimumSupportedProtocolVersion:"); - void _objc_msgSend_949( + void _objc_msgSend_963( ffi.Pointer obj, ffi.Pointer sel, int value, ) { - return __objc_msgSend_949( + return __objc_msgSend_963( obj, sel, value, ); } - late final __objc_msgSend_949Ptr = _lookup< + late final __objc_msgSend_963Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Int32)>>('objc_msgSend'); - late final __objc_msgSend_949 = __objc_msgSend_949Ptr.asFunction< + late final __objc_msgSend_963 = __objc_msgSend_963Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, int)>(); late final _sel_TLSMaximumSupportedProtocolVersion1 = @@ -27160,23 +27491,23 @@ class SentryCocoa { late final _sel_HTTPCookieStorage1 = _registerName1("HTTPCookieStorage"); late final _sel_setHTTPCookieStorage_1 = _registerName1("setHTTPCookieStorage:"); - void _objc_msgSend_950( + void _objc_msgSend_964( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer value, ) { - return __objc_msgSend_950( + return __objc_msgSend_964( obj, sel, value, ); } - late final __objc_msgSend_950Ptr = _lookup< + late final __objc_msgSend_964Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_950 = __objc_msgSend_950Ptr.asFunction< + late final __objc_msgSend_964 = __objc_msgSend_964Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); @@ -27184,23 +27515,23 @@ class SentryCocoa { _registerName1("URLCredentialStorage"); late final _sel_setURLCredentialStorage_1 = _registerName1("setURLCredentialStorage:"); - void _objc_msgSend_951( + void _objc_msgSend_965( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer value, ) { - return __objc_msgSend_951( + return __objc_msgSend_965( obj, sel, value, ); } - late final __objc_msgSend_951Ptr = _lookup< + late final __objc_msgSend_965Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_951 = __objc_msgSend_951Ptr.asFunction< + late final __objc_msgSend_965 = __objc_msgSend_965Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); @@ -27214,78 +27545,78 @@ class SentryCocoa { late final _sel_setProtocolClasses_1 = _registerName1("setProtocolClasses:"); late final _sel_multipathServiceType1 = _registerName1("multipathServiceType"); - int _objc_msgSend_952( + int _objc_msgSend_966( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_952( + return __objc_msgSend_966( obj, sel, ); } - late final __objc_msgSend_952Ptr = _lookup< + late final __objc_msgSend_966Ptr = _lookup< ffi.NativeFunction< ffi.Int32 Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_952 = __objc_msgSend_952Ptr.asFunction< + late final __objc_msgSend_966 = __objc_msgSend_966Ptr.asFunction< int Function(ffi.Pointer, ffi.Pointer)>(); late final _sel_setMultipathServiceType_1 = _registerName1("setMultipathServiceType:"); - void _objc_msgSend_953( + void _objc_msgSend_967( ffi.Pointer obj, ffi.Pointer sel, int value, ) { - return __objc_msgSend_953( + return __objc_msgSend_967( obj, sel, value, ); } - late final __objc_msgSend_953Ptr = _lookup< + late final __objc_msgSend_967Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Int32)>>('objc_msgSend'); - late final __objc_msgSend_953 = __objc_msgSend_953Ptr.asFunction< + late final __objc_msgSend_967 = __objc_msgSend_967Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, int)>(); late final _sel_backgroundSessionConfiguration_1 = _registerName1("backgroundSessionConfiguration:"); late final _sel_sessionWithConfiguration_1 = _registerName1("sessionWithConfiguration:"); - ffi.Pointer _objc_msgSend_954( + ffi.Pointer _objc_msgSend_968( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer configuration, ) { - return __objc_msgSend_954( + return __objc_msgSend_968( obj, sel, configuration, ); } - late final __objc_msgSend_954Ptr = _lookup< + late final __objc_msgSend_968Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_954 = __objc_msgSend_954Ptr.asFunction< + late final __objc_msgSend_968 = __objc_msgSend_968Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); late final _sel_sessionWithConfiguration_delegate_delegateQueue_1 = _registerName1("sessionWithConfiguration:delegate:delegateQueue:"); - ffi.Pointer _objc_msgSend_955( + ffi.Pointer _objc_msgSend_969( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer configuration, ffi.Pointer delegate, ffi.Pointer queue, ) { - return __objc_msgSend_955( + return __objc_msgSend_969( obj, sel, configuration, @@ -27294,7 +27625,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_955Ptr = _lookup< + late final __objc_msgSend_969Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, @@ -27302,7 +27633,7 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_955 = __objc_msgSend_955Ptr.asFunction< + late final __objc_msgSend_969 = __objc_msgSend_969Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, @@ -27324,102 +27655,124 @@ class SentryCocoa { _registerName1("flushWithCompletionHandler:"); late final _sel_getTasksWithCompletionHandler_1 = _registerName1("getTasksWithCompletionHandler:"); - void _objc_msgSend_956( + void _objc_msgSend_970( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer<_ObjCBlock> completionHandler, ) { - return __objc_msgSend_956( + return __objc_msgSend_970( obj, sel, completionHandler, ); } - late final __objc_msgSend_956Ptr = _lookup< + late final __objc_msgSend_970Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer<_ObjCBlock>)>>('objc_msgSend'); - late final __objc_msgSend_956 = __objc_msgSend_956Ptr.asFunction< + late final __objc_msgSend_970 = __objc_msgSend_970Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer<_ObjCBlock>)>(); late final _sel_getAllTasksWithCompletionHandler_1 = _registerName1("getAllTasksWithCompletionHandler:"); - void _objc_msgSend_957( + void _objc_msgSend_971( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer<_ObjCBlock> completionHandler, ) { - return __objc_msgSend_957( + return __objc_msgSend_971( obj, sel, completionHandler, ); } - late final __objc_msgSend_957Ptr = _lookup< + late final __objc_msgSend_971Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer<_ObjCBlock>)>>('objc_msgSend'); - late final __objc_msgSend_957 = __objc_msgSend_957Ptr.asFunction< + late final __objc_msgSend_971 = __objc_msgSend_971Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer<_ObjCBlock>)>(); late final _sel_dataTaskWithRequest_1 = _registerName1("dataTaskWithRequest:"); - ffi.Pointer _objc_msgSend_958( + ffi.Pointer _objc_msgSend_972( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer request, ) { - return __objc_msgSend_958( + return __objc_msgSend_972( obj, sel, request, ); } - late final __objc_msgSend_958Ptr = _lookup< + late final __objc_msgSend_972Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_958 = __objc_msgSend_958Ptr.asFunction< + late final __objc_msgSend_972 = __objc_msgSend_972Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); late final _sel_dataTaskWithURL_1 = _registerName1("dataTaskWithURL:"); - ffi.Pointer _objc_msgSend_959( + ffi.Pointer _objc_msgSend_973( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer url, ) { - return __objc_msgSend_959( + return __objc_msgSend_973( obj, sel, url, ); } - late final __objc_msgSend_959Ptr = _lookup< + late final __objc_msgSend_973Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_959 = __objc_msgSend_959Ptr.asFunction< + late final __objc_msgSend_973 = __objc_msgSend_973Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); late final _class_NSURLSessionUploadTask1 = _getClass1("NSURLSessionUploadTask"); + late final _sel_cancelByProducingResumeData_1 = + _registerName1("cancelByProducingResumeData:"); + void _objc_msgSend_974( + ffi.Pointer obj, + ffi.Pointer sel, + ffi.Pointer<_ObjCBlock> completionHandler, + ) { + return __objc_msgSend_974( + obj, + sel, + completionHandler, + ); + } + + late final __objc_msgSend_974Ptr = _lookup< + ffi.NativeFunction< + ffi.Void Function(ffi.Pointer, ffi.Pointer, + ffi.Pointer<_ObjCBlock>)>>('objc_msgSend'); + late final __objc_msgSend_974 = __objc_msgSend_974Ptr.asFunction< + void Function(ffi.Pointer, ffi.Pointer, + ffi.Pointer<_ObjCBlock>)>(); + late final _sel_uploadTaskWithRequest_fromFile_1 = _registerName1("uploadTaskWithRequest:fromFile:"); - ffi.Pointer _objc_msgSend_960( + ffi.Pointer _objc_msgSend_975( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer request, ffi.Pointer fileURL, ) { - return __objc_msgSend_960( + return __objc_msgSend_975( obj, sel, request, @@ -27427,14 +27780,14 @@ class SentryCocoa { ); } - late final __objc_msgSend_960Ptr = _lookup< + late final __objc_msgSend_975Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_960 = __objc_msgSend_960Ptr.asFunction< + late final __objc_msgSend_975 = __objc_msgSend_975Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, @@ -27443,13 +27796,13 @@ class SentryCocoa { late final _sel_uploadTaskWithRequest_fromData_1 = _registerName1("uploadTaskWithRequest:fromData:"); - ffi.Pointer _objc_msgSend_961( + ffi.Pointer _objc_msgSend_976( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer request, ffi.Pointer bodyData, ) { - return __objc_msgSend_961( + return __objc_msgSend_976( obj, sel, request, @@ -27457,129 +27810,129 @@ class SentryCocoa { ); } - late final __objc_msgSend_961Ptr = _lookup< + late final __objc_msgSend_976Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_961 = __objc_msgSend_961Ptr.asFunction< + late final __objc_msgSend_976 = __objc_msgSend_976Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); - late final _sel_uploadTaskWithStreamedRequest_1 = - _registerName1("uploadTaskWithStreamedRequest:"); - ffi.Pointer _objc_msgSend_962( + late final _sel_uploadTaskWithResumeData_1 = + _registerName1("uploadTaskWithResumeData:"); + ffi.Pointer _objc_msgSend_977( ffi.Pointer obj, ffi.Pointer sel, - ffi.Pointer request, + ffi.Pointer resumeData, ) { - return __objc_msgSend_962( + return __objc_msgSend_977( obj, sel, - request, + resumeData, ); } - late final __objc_msgSend_962Ptr = _lookup< + late final __objc_msgSend_977Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_962 = __objc_msgSend_962Ptr.asFunction< + late final __objc_msgSend_977 = __objc_msgSend_977Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); - late final _class_NSURLSessionDownloadTask1 = - _getClass1("NSURLSessionDownloadTask"); - late final _sel_cancelByProducingResumeData_1 = - _registerName1("cancelByProducingResumeData:"); - void _objc_msgSend_963( + late final _sel_uploadTaskWithStreamedRequest_1 = + _registerName1("uploadTaskWithStreamedRequest:"); + ffi.Pointer _objc_msgSend_978( ffi.Pointer obj, ffi.Pointer sel, - ffi.Pointer<_ObjCBlock> completionHandler, + ffi.Pointer request, ) { - return __objc_msgSend_963( + return __objc_msgSend_978( obj, sel, - completionHandler, + request, ); } - late final __objc_msgSend_963Ptr = _lookup< + late final __objc_msgSend_978Ptr = _lookup< ffi.NativeFunction< - ffi.Void Function(ffi.Pointer, ffi.Pointer, - ffi.Pointer<_ObjCBlock>)>>('objc_msgSend'); - late final __objc_msgSend_963 = __objc_msgSend_963Ptr.asFunction< - void Function(ffi.Pointer, ffi.Pointer, - ffi.Pointer<_ObjCBlock>)>(); + ffi.Pointer Function(ffi.Pointer, + ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); + late final __objc_msgSend_978 = __objc_msgSend_978Ptr.asFunction< + ffi.Pointer Function(ffi.Pointer, + ffi.Pointer, ffi.Pointer)>(); + late final _class_NSURLSessionDownloadTask1 = + _getClass1("NSURLSessionDownloadTask"); late final _sel_downloadTaskWithRequest_1 = _registerName1("downloadTaskWithRequest:"); - ffi.Pointer _objc_msgSend_964( + ffi.Pointer _objc_msgSend_979( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer request, ) { - return __objc_msgSend_964( + return __objc_msgSend_979( obj, sel, request, ); } - late final __objc_msgSend_964Ptr = _lookup< + late final __objc_msgSend_979Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_964 = __objc_msgSend_964Ptr.asFunction< + late final __objc_msgSend_979 = __objc_msgSend_979Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); late final _sel_downloadTaskWithURL_1 = _registerName1("downloadTaskWithURL:"); - ffi.Pointer _objc_msgSend_965( + ffi.Pointer _objc_msgSend_980( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer url, ) { - return __objc_msgSend_965( + return __objc_msgSend_980( obj, sel, url, ); } - late final __objc_msgSend_965Ptr = _lookup< + late final __objc_msgSend_980Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_965 = __objc_msgSend_965Ptr.asFunction< + late final __objc_msgSend_980 = __objc_msgSend_980Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); late final _sel_downloadTaskWithResumeData_1 = _registerName1("downloadTaskWithResumeData:"); - ffi.Pointer _objc_msgSend_966( + ffi.Pointer _objc_msgSend_981( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer resumeData, ) { - return __objc_msgSend_966( + return __objc_msgSend_981( obj, sel, resumeData, ); } - late final __objc_msgSend_966Ptr = _lookup< + late final __objc_msgSend_981Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_966 = __objc_msgSend_966Ptr.asFunction< + late final __objc_msgSend_981 = __objc_msgSend_981Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); @@ -27588,7 +27941,7 @@ class SentryCocoa { late final _sel_readDataOfMinLength_maxLength_timeout_completionHandler_1 = _registerName1( "readDataOfMinLength:maxLength:timeout:completionHandler:"); - void _objc_msgSend_967( + void _objc_msgSend_982( ffi.Pointer obj, ffi.Pointer sel, int minBytes, @@ -27596,7 +27949,7 @@ class SentryCocoa { double timeout, ffi.Pointer<_ObjCBlock> completionHandler, ) { - return __objc_msgSend_967( + return __objc_msgSend_982( obj, sel, minBytes, @@ -27606,7 +27959,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_967Ptr = _lookup< + late final __objc_msgSend_982Ptr = _lookup< ffi.NativeFunction< ffi.Void Function( ffi.Pointer, @@ -27615,20 +27968,20 @@ class SentryCocoa { ffi.UnsignedLong, ffi.Double, ffi.Pointer<_ObjCBlock>)>>('objc_msgSend'); - late final __objc_msgSend_967 = __objc_msgSend_967Ptr.asFunction< + late final __objc_msgSend_982 = __objc_msgSend_982Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, int, int, double, ffi.Pointer<_ObjCBlock>)>(); late final _sel_writeData_timeout_completionHandler_1 = _registerName1("writeData:timeout:completionHandler:"); - void _objc_msgSend_968( + void _objc_msgSend_983( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer data, double timeout, ffi.Pointer<_ObjCBlock> completionHandler, ) { - return __objc_msgSend_968( + return __objc_msgSend_983( obj, sel, data, @@ -27637,7 +27990,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_968Ptr = _lookup< + late final __objc_msgSend_983Ptr = _lookup< ffi.NativeFunction< ffi.Void Function( ffi.Pointer, @@ -27645,7 +27998,7 @@ class SentryCocoa { ffi.Pointer, ffi.Double, ffi.Pointer<_ObjCBlock>)>>('objc_msgSend'); - late final __objc_msgSend_968 = __objc_msgSend_968Ptr.asFunction< + late final __objc_msgSend_983 = __objc_msgSend_983Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, double, ffi.Pointer<_ObjCBlock>)>(); @@ -27658,13 +28011,13 @@ class SentryCocoa { _registerName1("stopSecureConnection"); late final _sel_streamTaskWithHostName_port_1 = _registerName1("streamTaskWithHostName:port:"); - ffi.Pointer _objc_msgSend_969( + ffi.Pointer _objc_msgSend_984( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer hostname, int port, ) { - return __objc_msgSend_969( + return __objc_msgSend_984( obj, sel, hostname, @@ -27672,21 +28025,21 @@ class SentryCocoa { ); } - late final __objc_msgSend_969Ptr = _lookup< + late final __objc_msgSend_984Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Long)>>('objc_msgSend'); - late final __objc_msgSend_969 = __objc_msgSend_969Ptr.asFunction< + late final __objc_msgSend_984 = __objc_msgSend_984Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, int)>(); late final _class_NSNetService1 = _getClass1("NSNetService"); late final _sel_initWithDomain_type_name_port_1 = _registerName1("initWithDomain:type:name:port:"); - instancetype _objc_msgSend_970( + instancetype _objc_msgSend_985( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer domain, @@ -27694,7 +28047,7 @@ class SentryCocoa { ffi.Pointer name, int port, ) { - return __objc_msgSend_970( + return __objc_msgSend_985( obj, sel, domain, @@ -27704,7 +28057,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_970Ptr = _lookup< + late final __objc_msgSend_985Ptr = _lookup< ffi.NativeFunction< instancetype Function( ffi.Pointer, @@ -27713,7 +28066,7 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Int)>>('objc_msgSend'); - late final __objc_msgSend_970 = __objc_msgSend_970Ptr.asFunction< + late final __objc_msgSend_985 = __objc_msgSend_985Ptr.asFunction< instancetype Function( ffi.Pointer, ffi.Pointer, @@ -27729,81 +28082,81 @@ class SentryCocoa { _registerName1("setIncludesPeerToPeer:"); late final _sel_type1 = _registerName1("type"); late final _sel_publishWithOptions_1 = _registerName1("publishWithOptions:"); - void _objc_msgSend_971( + void _objc_msgSend_986( ffi.Pointer obj, ffi.Pointer sel, int options, ) { - return __objc_msgSend_971( + return __objc_msgSend_986( obj, sel, options, ); } - late final __objc_msgSend_971Ptr = _lookup< + late final __objc_msgSend_986Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Int32)>>('objc_msgSend'); - late final __objc_msgSend_971 = __objc_msgSend_971Ptr.asFunction< + late final __objc_msgSend_986 = __objc_msgSend_986Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, int)>(); late final _sel_resolve1 = _registerName1("resolve"); late final _sel_stop1 = _registerName1("stop"); late final _sel_dictionaryFromTXTRecordData_1 = _registerName1("dictionaryFromTXTRecordData:"); - ffi.Pointer _objc_msgSend_972( + ffi.Pointer _objc_msgSend_987( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer txtData, ) { - return __objc_msgSend_972( + return __objc_msgSend_987( obj, sel, txtData, ); } - late final __objc_msgSend_972Ptr = _lookup< + late final __objc_msgSend_987Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_972 = __objc_msgSend_972Ptr.asFunction< + late final __objc_msgSend_987 = __objc_msgSend_987Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); late final _sel_dataFromTXTRecordDictionary_1 = _registerName1("dataFromTXTRecordDictionary:"); - ffi.Pointer _objc_msgSend_973( + ffi.Pointer _objc_msgSend_988( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer txtDictionary, ) { - return __objc_msgSend_973( + return __objc_msgSend_988( obj, sel, txtDictionary, ); } - late final __objc_msgSend_973Ptr = _lookup< + late final __objc_msgSend_988Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_973 = __objc_msgSend_973Ptr.asFunction< + late final __objc_msgSend_988 = __objc_msgSend_988Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); late final _sel_resolveWithTimeout_1 = _registerName1("resolveWithTimeout:"); late final _sel_getInputStream_outputStream_1 = _registerName1("getInputStream:outputStream:"); - bool _objc_msgSend_974( + bool _objc_msgSend_989( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer> inputStream, ffi.Pointer> outputStream, ) { - return __objc_msgSend_974( + return __objc_msgSend_989( obj, sel, inputStream, @@ -27811,14 +28164,14 @@ class SentryCocoa { ); } - late final __objc_msgSend_974Ptr = _lookup< + late final __objc_msgSend_989Ptr = _lookup< ffi.NativeFunction< ffi.Bool Function( ffi.Pointer, ffi.Pointer, ffi.Pointer>, ffi.Pointer>)>>('objc_msgSend'); - late final __objc_msgSend_974 = __objc_msgSend_974Ptr.asFunction< + late final __objc_msgSend_989 = __objc_msgSend_989Ptr.asFunction< bool Function( ffi.Pointer, ffi.Pointer, @@ -27831,23 +28184,23 @@ class SentryCocoa { late final _sel_stopMonitoring1 = _registerName1("stopMonitoring"); late final _sel_streamTaskWithNetService_1 = _registerName1("streamTaskWithNetService:"); - ffi.Pointer _objc_msgSend_975( + ffi.Pointer _objc_msgSend_990( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer service, ) { - return __objc_msgSend_975( + return __objc_msgSend_990( obj, sel, service, ); } - late final __objc_msgSend_975Ptr = _lookup< + late final __objc_msgSend_990Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_975 = __objc_msgSend_975Ptr.asFunction< + late final __objc_msgSend_990 = __objc_msgSend_990Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); @@ -27855,32 +28208,32 @@ class SentryCocoa { _getClass1("NSURLSessionWebSocketTask"); late final _class_NSURLSessionWebSocketMessage1 = _getClass1("NSURLSessionWebSocketMessage"); - int _objc_msgSend_976( + int _objc_msgSend_991( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_976( + return __objc_msgSend_991( obj, sel, ); } - late final __objc_msgSend_976Ptr = _lookup< + late final __objc_msgSend_991Ptr = _lookup< ffi.NativeFunction< ffi.Int32 Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_976 = __objc_msgSend_976Ptr.asFunction< + late final __objc_msgSend_991 = __objc_msgSend_991Ptr.asFunction< int Function(ffi.Pointer, ffi.Pointer)>(); late final _sel_sendMessage_completionHandler_1 = _registerName1("sendMessage:completionHandler:"); - void _objc_msgSend_977( + void _objc_msgSend_992( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer message, ffi.Pointer<_ObjCBlock> completionHandler, ) { - return __objc_msgSend_977( + return __objc_msgSend_992( obj, sel, message, @@ -27888,70 +28241,70 @@ class SentryCocoa { ); } - late final __objc_msgSend_977Ptr = _lookup< + late final __objc_msgSend_992Ptr = _lookup< ffi.NativeFunction< ffi.Void Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer<_ObjCBlock>)>>('objc_msgSend'); - late final __objc_msgSend_977 = __objc_msgSend_977Ptr.asFunction< + late final __objc_msgSend_992 = __objc_msgSend_992Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer<_ObjCBlock>)>(); late final _sel_receiveMessageWithCompletionHandler_1 = _registerName1("receiveMessageWithCompletionHandler:"); - void _objc_msgSend_978( + void _objc_msgSend_993( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer<_ObjCBlock> completionHandler, ) { - return __objc_msgSend_978( + return __objc_msgSend_993( obj, sel, completionHandler, ); } - late final __objc_msgSend_978Ptr = _lookup< + late final __objc_msgSend_993Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer<_ObjCBlock>)>>('objc_msgSend'); - late final __objc_msgSend_978 = __objc_msgSend_978Ptr.asFunction< + late final __objc_msgSend_993 = __objc_msgSend_993Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer<_ObjCBlock>)>(); late final _sel_sendPingWithPongReceiveHandler_1 = _registerName1("sendPingWithPongReceiveHandler:"); - void _objc_msgSend_979( + void _objc_msgSend_994( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer<_ObjCBlock> pongReceiveHandler, ) { - return __objc_msgSend_979( + return __objc_msgSend_994( obj, sel, pongReceiveHandler, ); } - late final __objc_msgSend_979Ptr = _lookup< + late final __objc_msgSend_994Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer<_ObjCBlock>)>>('objc_msgSend'); - late final __objc_msgSend_979 = __objc_msgSend_979Ptr.asFunction< + late final __objc_msgSend_994 = __objc_msgSend_994Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer<_ObjCBlock>)>(); late final _sel_cancelWithCloseCode_reason_1 = _registerName1("cancelWithCloseCode:reason:"); - void _objc_msgSend_980( + void _objc_msgSend_995( ffi.Pointer obj, ffi.Pointer sel, int closeCode, ffi.Pointer reason, ) { - return __objc_msgSend_980( + return __objc_msgSend_995( obj, sel, closeCode, @@ -27959,11 +28312,11 @@ class SentryCocoa { ); } - late final __objc_msgSend_980Ptr = _lookup< + late final __objc_msgSend_995Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Int32, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_980 = __objc_msgSend_980Ptr.asFunction< + late final __objc_msgSend_995 = __objc_msgSend_995Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, int, ffi.Pointer)>(); @@ -27971,55 +28324,55 @@ class SentryCocoa { late final _sel_setMaximumMessageSize_1 = _registerName1("setMaximumMessageSize:"); late final _sel_closeCode1 = _registerName1("closeCode"); - int _objc_msgSend_981( + int _objc_msgSend_996( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_981( + return __objc_msgSend_996( obj, sel, ); } - late final __objc_msgSend_981Ptr = _lookup< + late final __objc_msgSend_996Ptr = _lookup< ffi.NativeFunction< ffi.Int32 Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_981 = __objc_msgSend_981Ptr.asFunction< + late final __objc_msgSend_996 = __objc_msgSend_996Ptr.asFunction< int Function(ffi.Pointer, ffi.Pointer)>(); late final _sel_closeReason1 = _registerName1("closeReason"); late final _sel_webSocketTaskWithURL_1 = _registerName1("webSocketTaskWithURL:"); - ffi.Pointer _objc_msgSend_982( + ffi.Pointer _objc_msgSend_997( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer url, ) { - return __objc_msgSend_982( + return __objc_msgSend_997( obj, sel, url, ); } - late final __objc_msgSend_982Ptr = _lookup< + late final __objc_msgSend_997Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_982 = __objc_msgSend_982Ptr.asFunction< + late final __objc_msgSend_997 = __objc_msgSend_997Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); late final _sel_webSocketTaskWithURL_protocols_1 = _registerName1("webSocketTaskWithURL:protocols:"); - ffi.Pointer _objc_msgSend_983( + ffi.Pointer _objc_msgSend_998( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer url, ffi.Pointer protocols, ) { - return __objc_msgSend_983( + return __objc_msgSend_998( obj, sel, url, @@ -28027,14 +28380,14 @@ class SentryCocoa { ); } - late final __objc_msgSend_983Ptr = _lookup< + late final __objc_msgSend_998Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_983 = __objc_msgSend_983Ptr.asFunction< + late final __objc_msgSend_998 = __objc_msgSend_998Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, @@ -28043,35 +28396,35 @@ class SentryCocoa { late final _sel_webSocketTaskWithRequest_1 = _registerName1("webSocketTaskWithRequest:"); - ffi.Pointer _objc_msgSend_984( + ffi.Pointer _objc_msgSend_999( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer request, ) { - return __objc_msgSend_984( + return __objc_msgSend_999( obj, sel, request, ); } - late final __objc_msgSend_984Ptr = _lookup< + late final __objc_msgSend_999Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_984 = __objc_msgSend_984Ptr.asFunction< + late final __objc_msgSend_999 = __objc_msgSend_999Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); late final _sel_dataTaskWithRequest_completionHandler_1 = _registerName1("dataTaskWithRequest:completionHandler:"); - ffi.Pointer _objc_msgSend_985( + ffi.Pointer _objc_msgSend_1000( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer request, ffi.Pointer<_ObjCBlock> completionHandler, ) { - return __objc_msgSend_985( + return __objc_msgSend_1000( obj, sel, request, @@ -28079,14 +28432,14 @@ class SentryCocoa { ); } - late final __objc_msgSend_985Ptr = _lookup< + late final __objc_msgSend_1000Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer<_ObjCBlock>)>>('objc_msgSend'); - late final __objc_msgSend_985 = __objc_msgSend_985Ptr.asFunction< + late final __objc_msgSend_1000 = __objc_msgSend_1000Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, @@ -28095,13 +28448,13 @@ class SentryCocoa { late final _sel_dataTaskWithURL_completionHandler_1 = _registerName1("dataTaskWithURL:completionHandler:"); - ffi.Pointer _objc_msgSend_986( + ffi.Pointer _objc_msgSend_1001( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer url, ffi.Pointer<_ObjCBlock> completionHandler, ) { - return __objc_msgSend_986( + return __objc_msgSend_1001( obj, sel, url, @@ -28109,14 +28462,14 @@ class SentryCocoa { ); } - late final __objc_msgSend_986Ptr = _lookup< + late final __objc_msgSend_1001Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer<_ObjCBlock>)>>('objc_msgSend'); - late final __objc_msgSend_986 = __objc_msgSend_986Ptr.asFunction< + late final __objc_msgSend_1001 = __objc_msgSend_1001Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, @@ -28125,14 +28478,14 @@ class SentryCocoa { late final _sel_uploadTaskWithRequest_fromFile_completionHandler_1 = _registerName1("uploadTaskWithRequest:fromFile:completionHandler:"); - ffi.Pointer _objc_msgSend_987( + ffi.Pointer _objc_msgSend_1002( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer request, ffi.Pointer fileURL, ffi.Pointer<_ObjCBlock> completionHandler, ) { - return __objc_msgSend_987( + return __objc_msgSend_1002( obj, sel, request, @@ -28141,7 +28494,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_987Ptr = _lookup< + late final __objc_msgSend_1002Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, @@ -28149,7 +28502,7 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Pointer<_ObjCBlock>)>>('objc_msgSend'); - late final __objc_msgSend_987 = __objc_msgSend_987Ptr.asFunction< + late final __objc_msgSend_1002 = __objc_msgSend_1002Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, @@ -28159,14 +28512,14 @@ class SentryCocoa { late final _sel_uploadTaskWithRequest_fromData_completionHandler_1 = _registerName1("uploadTaskWithRequest:fromData:completionHandler:"); - ffi.Pointer _objc_msgSend_988( + ffi.Pointer _objc_msgSend_1003( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer request, ffi.Pointer bodyData, ffi.Pointer<_ObjCBlock> completionHandler, ) { - return __objc_msgSend_988( + return __objc_msgSend_1003( obj, sel, request, @@ -28175,7 +28528,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_988Ptr = _lookup< + late final __objc_msgSend_1003Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, @@ -28183,7 +28536,7 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Pointer<_ObjCBlock>)>>('objc_msgSend'); - late final __objc_msgSend_988 = __objc_msgSend_988Ptr.asFunction< + late final __objc_msgSend_1003 = __objc_msgSend_1003Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, @@ -28191,15 +28544,45 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer<_ObjCBlock>)>(); + late final _sel_uploadTaskWithResumeData_completionHandler_1 = + _registerName1("uploadTaskWithResumeData:completionHandler:"); + ffi.Pointer _objc_msgSend_1004( + ffi.Pointer obj, + ffi.Pointer sel, + ffi.Pointer resumeData, + ffi.Pointer<_ObjCBlock> completionHandler, + ) { + return __objc_msgSend_1004( + obj, + sel, + resumeData, + completionHandler, + ); + } + + late final __objc_msgSend_1004Ptr = _lookup< + ffi.NativeFunction< + ffi.Pointer Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer<_ObjCBlock>)>>('objc_msgSend'); + late final __objc_msgSend_1004 = __objc_msgSend_1004Ptr.asFunction< + ffi.Pointer Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer<_ObjCBlock>)>(); + late final _sel_downloadTaskWithRequest_completionHandler_1 = _registerName1("downloadTaskWithRequest:completionHandler:"); - ffi.Pointer _objc_msgSend_989( + ffi.Pointer _objc_msgSend_1005( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer request, ffi.Pointer<_ObjCBlock> completionHandler, ) { - return __objc_msgSend_989( + return __objc_msgSend_1005( obj, sel, request, @@ -28207,14 +28590,14 @@ class SentryCocoa { ); } - late final __objc_msgSend_989Ptr = _lookup< + late final __objc_msgSend_1005Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer<_ObjCBlock>)>>('objc_msgSend'); - late final __objc_msgSend_989 = __objc_msgSend_989Ptr.asFunction< + late final __objc_msgSend_1005 = __objc_msgSend_1005Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, @@ -28223,13 +28606,13 @@ class SentryCocoa { late final _sel_downloadTaskWithURL_completionHandler_1 = _registerName1("downloadTaskWithURL:completionHandler:"); - ffi.Pointer _objc_msgSend_990( + ffi.Pointer _objc_msgSend_1006( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer url, ffi.Pointer<_ObjCBlock> completionHandler, ) { - return __objc_msgSend_990( + return __objc_msgSend_1006( obj, sel, url, @@ -28237,14 +28620,14 @@ class SentryCocoa { ); } - late final __objc_msgSend_990Ptr = _lookup< + late final __objc_msgSend_1006Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer<_ObjCBlock>)>>('objc_msgSend'); - late final __objc_msgSend_990 = __objc_msgSend_990Ptr.asFunction< + late final __objc_msgSend_1006 = __objc_msgSend_1006Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, @@ -28253,13 +28636,13 @@ class SentryCocoa { late final _sel_downloadTaskWithResumeData_completionHandler_1 = _registerName1("downloadTaskWithResumeData:completionHandler:"); - ffi.Pointer _objc_msgSend_991( + ffi.Pointer _objc_msgSend_1007( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer resumeData, ffi.Pointer<_ObjCBlock> completionHandler, ) { - return __objc_msgSend_991( + return __objc_msgSend_1007( obj, sel, resumeData, @@ -28267,14 +28650,14 @@ class SentryCocoa { ); } - late final __objc_msgSend_991Ptr = _lookup< + late final __objc_msgSend_1007Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer<_ObjCBlock>)>>('objc_msgSend'); - late final __objc_msgSend_991 = __objc_msgSend_991Ptr.asFunction< + late final __objc_msgSend_1007 = __objc_msgSend_1007Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, @@ -28282,33 +28665,33 @@ class SentryCocoa { ffi.Pointer<_ObjCBlock>)>(); late final _class_NSProtocolChecker1 = _getClass1("NSProtocolChecker"); - ffi.Pointer _objc_msgSend_992( + ffi.Pointer _objc_msgSend_1008( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_992( + return __objc_msgSend_1008( obj, sel, ); } - late final __objc_msgSend_992Ptr = _lookup< + late final __objc_msgSend_1008Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_992 = __objc_msgSend_992Ptr.asFunction< + late final __objc_msgSend_1008 = __objc_msgSend_1008Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>(); late final _sel_protocolCheckerWithTarget_protocol_1 = _registerName1("protocolCheckerWithTarget:protocol:"); - instancetype _objc_msgSend_993( + instancetype _objc_msgSend_1009( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer anObject, ffi.Pointer aProtocol, ) { - return __objc_msgSend_993( + return __objc_msgSend_1009( obj, sel, anObject, @@ -28316,14 +28699,14 @@ class SentryCocoa { ); } - late final __objc_msgSend_993Ptr = _lookup< + late final __objc_msgSend_1009Ptr = _lookup< ffi.NativeFunction< instancetype Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_993 = __objc_msgSend_993Ptr.asFunction< + late final __objc_msgSend_1009 = __objc_msgSend_1009Ptr.asFunction< instancetype Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); @@ -28335,6 +28718,10 @@ class SentryCocoa { late final _sel_currentDirectoryURL1 = _registerName1("currentDirectoryURL"); late final _sel_setCurrentDirectoryURL_1 = _registerName1("setCurrentDirectoryURL:"); + late final _sel_launchRequirementData1 = + _registerName1("launchRequirementData"); + late final _sel_setLaunchRequirementData_1 = + _registerName1("setLaunchRequirementData:"); late final _sel_standardInput1 = _registerName1("standardInput"); late final _sel_setStandardInput_1 = _registerName1("setStandardInput:"); late final _sel_standardOutput1 = _registerName1("standardOutput"); @@ -28348,68 +28735,68 @@ class SentryCocoa { late final _sel_isRunning1 = _registerName1("isRunning"); late final _sel_terminationStatus1 = _registerName1("terminationStatus"); late final _sel_terminationReason1 = _registerName1("terminationReason"); - int _objc_msgSend_994( + int _objc_msgSend_1010( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_994( + return __objc_msgSend_1010( obj, sel, ); } - late final __objc_msgSend_994Ptr = _lookup< + late final __objc_msgSend_1010Ptr = _lookup< ffi.NativeFunction< ffi.Int32 Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_994 = __objc_msgSend_994Ptr.asFunction< + late final __objc_msgSend_1010 = __objc_msgSend_1010Ptr.asFunction< int Function(ffi.Pointer, ffi.Pointer)>(); late final _sel_terminationHandler1 = _registerName1("terminationHandler"); - ffi.Pointer<_ObjCBlock> _objc_msgSend_995( + ffi.Pointer<_ObjCBlock> _objc_msgSend_1011( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_995( + return __objc_msgSend_1011( obj, sel, ); } - late final __objc_msgSend_995Ptr = _lookup< + late final __objc_msgSend_1011Ptr = _lookup< ffi.NativeFunction< ffi.Pointer<_ObjCBlock> Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_995 = __objc_msgSend_995Ptr.asFunction< + late final __objc_msgSend_1011 = __objc_msgSend_1011Ptr.asFunction< ffi.Pointer<_ObjCBlock> Function( ffi.Pointer, ffi.Pointer)>(); late final _sel_setTerminationHandler_1 = _registerName1("setTerminationHandler:"); - void _objc_msgSend_996( + void _objc_msgSend_1012( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer<_ObjCBlock> value, ) { - return __objc_msgSend_996( + return __objc_msgSend_1012( obj, sel, value, ); } - late final __objc_msgSend_996Ptr = _lookup< + late final __objc_msgSend_1012Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer<_ObjCBlock>)>>('objc_msgSend'); - late final __objc_msgSend_996 = __objc_msgSend_996Ptr.asFunction< + late final __objc_msgSend_1012 = __objc_msgSend_1012Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer<_ObjCBlock>)>(); late final _sel_launchedTaskWithExecutableURL_arguments_error_terminationHandler_1 = _registerName1( "launchedTaskWithExecutableURL:arguments:error:terminationHandler:"); - ffi.Pointer _objc_msgSend_997( + ffi.Pointer _objc_msgSend_1013( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer url, @@ -28417,7 +28804,7 @@ class SentryCocoa { ffi.Pointer> error, ffi.Pointer<_ObjCBlock> terminationHandler, ) { - return __objc_msgSend_997( + return __objc_msgSend_1013( obj, sel, url, @@ -28427,7 +28814,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_997Ptr = _lookup< + late final __objc_msgSend_1013Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, @@ -28436,7 +28823,7 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer>, ffi.Pointer<_ObjCBlock>)>>('objc_msgSend'); - late final __objc_msgSend_997 = __objc_msgSend_997Ptr.asFunction< + late final __objc_msgSend_1013 = __objc_msgSend_1013Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, @@ -28453,13 +28840,13 @@ class SentryCocoa { late final _sel_launch1 = _registerName1("launch"); late final _sel_launchedTaskWithLaunchPath_arguments_1 = _registerName1("launchedTaskWithLaunchPath:arguments:"); - ffi.Pointer _objc_msgSend_998( + ffi.Pointer _objc_msgSend_1014( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer path, ffi.Pointer arguments, ) { - return __objc_msgSend_998( + return __objc_msgSend_1014( obj, sel, path, @@ -28467,14 +28854,14 @@ class SentryCocoa { ); } - late final __objc_msgSend_998Ptr = _lookup< + late final __objc_msgSend_1014Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_998 = __objc_msgSend_998Ptr.asFunction< + late final __objc_msgSend_1014 = __objc_msgSend_1014Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, @@ -28484,35 +28871,35 @@ class SentryCocoa { late final _class_NSXMLElement1 = _getClass1("NSXMLElement"); late final _class_NSXMLNode1 = _getClass1("NSXMLNode"); late final _sel_initWithKind_1 = _registerName1("initWithKind:"); - instancetype _objc_msgSend_999( + instancetype _objc_msgSend_1015( ffi.Pointer obj, ffi.Pointer sel, int kind, ) { - return __objc_msgSend_999( + return __objc_msgSend_1015( obj, sel, kind, ); } - late final __objc_msgSend_999Ptr = _lookup< + late final __objc_msgSend_1015Ptr = _lookup< ffi.NativeFunction< instancetype Function(ffi.Pointer, ffi.Pointer, ffi.Int32)>>('objc_msgSend'); - late final __objc_msgSend_999 = __objc_msgSend_999Ptr.asFunction< + late final __objc_msgSend_1015 = __objc_msgSend_1015Ptr.asFunction< instancetype Function( ffi.Pointer, ffi.Pointer, int)>(); late final _sel_initWithKind_options_1 = _registerName1("initWithKind:options:"); - instancetype _objc_msgSend_1000( + instancetype _objc_msgSend_1016( ffi.Pointer obj, ffi.Pointer sel, int kind, int options, ) { - return __objc_msgSend_1000( + return __objc_msgSend_1016( obj, sel, kind, @@ -28520,34 +28907,34 @@ class SentryCocoa { ); } - late final __objc_msgSend_1000Ptr = _lookup< + late final __objc_msgSend_1016Ptr = _lookup< ffi.NativeFunction< instancetype Function(ffi.Pointer, ffi.Pointer, ffi.Int32, ffi.Int32)>>('objc_msgSend'); - late final __objc_msgSend_1000 = __objc_msgSend_1000Ptr.asFunction< + late final __objc_msgSend_1016 = __objc_msgSend_1016Ptr.asFunction< instancetype Function( ffi.Pointer, ffi.Pointer, int, int)>(); late final _sel_document1 = _registerName1("document"); late final _sel_documentWithRootElement_1 = _registerName1("documentWithRootElement:"); - ffi.Pointer _objc_msgSend_1001( + ffi.Pointer _objc_msgSend_1017( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer element, ) { - return __objc_msgSend_1001( + return __objc_msgSend_1017( obj, sel, element, ); } - late final __objc_msgSend_1001Ptr = _lookup< + late final __objc_msgSend_1017Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_1001 = __objc_msgSend_1001Ptr.asFunction< + late final __objc_msgSend_1017 = __objc_msgSend_1017Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); @@ -28558,14 +28945,14 @@ class SentryCocoa { _registerName1("elementWithName:stringValue:"); late final _sel_elementWithName_children_attributes_1 = _registerName1("elementWithName:children:attributes:"); - ffi.Pointer _objc_msgSend_1002( + ffi.Pointer _objc_msgSend_1018( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer name, ffi.Pointer children, ffi.Pointer attributes, ) { - return __objc_msgSend_1002( + return __objc_msgSend_1018( obj, sel, name, @@ -28574,7 +28961,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_1002Ptr = _lookup< + late final __objc_msgSend_1018Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, @@ -28582,7 +28969,7 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_1002 = __objc_msgSend_1002Ptr.asFunction< + late final __objc_msgSend_1018 = __objc_msgSend_1018Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, @@ -28604,21 +28991,21 @@ class SentryCocoa { _registerName1("textWithStringValue:"); late final _sel_DTDNodeWithXMLString_1 = _registerName1("DTDNodeWithXMLString:"); - int _objc_msgSend_1003( + int _objc_msgSend_1019( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_1003( + return __objc_msgSend_1019( obj, sel, ); } - late final __objc_msgSend_1003Ptr = _lookup< + late final __objc_msgSend_1019Ptr = _lookup< ffi.NativeFunction< ffi.Int32 Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_1003 = __objc_msgSend_1003Ptr.asFunction< + late final __objc_msgSend_1019 = __objc_msgSend_1019Ptr.asFunction< int Function(ffi.Pointer, ffi.Pointer)>(); late final _sel_objectValue1 = _registerName1("objectValue"); @@ -28626,13 +29013,13 @@ class SentryCocoa { late final _sel_setStringValue_1 = _registerName1("setStringValue:"); late final _sel_setStringValue_resolvingEntities_1 = _registerName1("setStringValue:resolvingEntities:"); - void _objc_msgSend_1004( + void _objc_msgSend_1020( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer string, bool resolve, ) { - return __objc_msgSend_1004( + return __objc_msgSend_1020( obj, sel, string, @@ -28640,11 +29027,11 @@ class SentryCocoa { ); } - late final __objc_msgSend_1004Ptr = _lookup< + late final __objc_msgSend_1020Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Bool)>>('objc_msgSend'); - late final __objc_msgSend_1004 = __objc_msgSend_1004Ptr.asFunction< + late final __objc_msgSend_1020 = __objc_msgSend_1020Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, bool)>(); @@ -28653,14 +29040,14 @@ class SentryCocoa { late final _class_NSXMLDocument1 = _getClass1("NSXMLDocument"); late final _sel_initWithXMLString_options_error_1 = _registerName1("initWithXMLString:options:error:"); - instancetype _objc_msgSend_1005( + instancetype _objc_msgSend_1021( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer string, int mask, ffi.Pointer> error, ) { - return __objc_msgSend_1005( + return __objc_msgSend_1021( obj, sel, string, @@ -28669,7 +29056,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_1005Ptr = _lookup< + late final __objc_msgSend_1021Ptr = _lookup< ffi.NativeFunction< instancetype Function( ffi.Pointer, @@ -28677,7 +29064,7 @@ class SentryCocoa { ffi.Pointer, ffi.Int32, ffi.Pointer>)>>('objc_msgSend'); - late final __objc_msgSend_1005 = __objc_msgSend_1005Ptr.asFunction< + late final __objc_msgSend_1021 = __objc_msgSend_1021Ptr.asFunction< instancetype Function( ffi.Pointer, ffi.Pointer, @@ -28685,14 +29072,14 @@ class SentryCocoa { int, ffi.Pointer>)>(); - instancetype _objc_msgSend_1006( + instancetype _objc_msgSend_1022( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer url, int mask, ffi.Pointer> error, ) { - return __objc_msgSend_1006( + return __objc_msgSend_1022( obj, sel, url, @@ -28701,7 +29088,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_1006Ptr = _lookup< + late final __objc_msgSend_1022Ptr = _lookup< ffi.NativeFunction< instancetype Function( ffi.Pointer, @@ -28709,7 +29096,7 @@ class SentryCocoa { ffi.Pointer, ffi.Int32, ffi.Pointer>)>>('objc_msgSend'); - late final __objc_msgSend_1006 = __objc_msgSend_1006Ptr.asFunction< + late final __objc_msgSend_1022 = __objc_msgSend_1022Ptr.asFunction< instancetype Function( ffi.Pointer, ffi.Pointer, @@ -28719,14 +29106,14 @@ class SentryCocoa { late final _sel_initWithData_options_error_1 = _registerName1("initWithData:options:error:"); - instancetype _objc_msgSend_1007( + instancetype _objc_msgSend_1023( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer data, int mask, ffi.Pointer> error, ) { - return __objc_msgSend_1007( + return __objc_msgSend_1023( obj, sel, data, @@ -28735,7 +29122,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_1007Ptr = _lookup< + late final __objc_msgSend_1023Ptr = _lookup< ffi.NativeFunction< instancetype Function( ffi.Pointer, @@ -28743,7 +29130,7 @@ class SentryCocoa { ffi.Pointer, ffi.Int32, ffi.Pointer>)>>('objc_msgSend'); - late final __objc_msgSend_1007 = __objc_msgSend_1007Ptr.asFunction< + late final __objc_msgSend_1023 = __objc_msgSend_1023Ptr.asFunction< instancetype Function( ffi.Pointer, ffi.Pointer, @@ -28761,42 +29148,42 @@ class SentryCocoa { late final _sel_isStandalone1 = _registerName1("isStandalone"); late final _sel_setStandalone_1 = _registerName1("setStandalone:"); late final _sel_documentContentKind1 = _registerName1("documentContentKind"); - int _objc_msgSend_1008( + int _objc_msgSend_1024( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_1008( + return __objc_msgSend_1024( obj, sel, ); } - late final __objc_msgSend_1008Ptr = _lookup< + late final __objc_msgSend_1024Ptr = _lookup< ffi.NativeFunction< ffi.Int32 Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_1008 = __objc_msgSend_1008Ptr.asFunction< + late final __objc_msgSend_1024 = __objc_msgSend_1024Ptr.asFunction< int Function(ffi.Pointer, ffi.Pointer)>(); late final _sel_setDocumentContentKind_1 = _registerName1("setDocumentContentKind:"); - void _objc_msgSend_1009( + void _objc_msgSend_1025( ffi.Pointer obj, ffi.Pointer sel, int value, ) { - return __objc_msgSend_1009( + return __objc_msgSend_1025( obj, sel, value, ); } - late final __objc_msgSend_1009Ptr = _lookup< + late final __objc_msgSend_1025Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Int32)>>('objc_msgSend'); - late final __objc_msgSend_1009 = __objc_msgSend_1009Ptr.asFunction< + late final __objc_msgSend_1025 = __objc_msgSend_1025Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, int)>(); late final _sel_setMIMEType_1 = _registerName1("setMIMEType:"); @@ -28805,13 +29192,13 @@ class SentryCocoa { late final _sel_setSystemID_1 = _registerName1("setSystemID:"); late final _sel_insertChild_atIndex_1 = _registerName1("insertChild:atIndex:"); - void _objc_msgSend_1010( + void _objc_msgSend_1026( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer child, int index, ) { - return __objc_msgSend_1010( + return __objc_msgSend_1026( obj, sel, child, @@ -28819,23 +29206,23 @@ class SentryCocoa { ); } - late final __objc_msgSend_1010Ptr = _lookup< + late final __objc_msgSend_1026Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.UnsignedLong)>>('objc_msgSend'); - late final __objc_msgSend_1010 = __objc_msgSend_1010Ptr.asFunction< + late final __objc_msgSend_1026 = __objc_msgSend_1026Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, int)>(); late final _sel_insertChildren_atIndex_1 = _registerName1("insertChildren:atIndex:"); - void _objc_msgSend_1011( + void _objc_msgSend_1027( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer children, int index, ) { - return __objc_msgSend_1011( + return __objc_msgSend_1027( obj, sel, children, @@ -28843,46 +29230,46 @@ class SentryCocoa { ); } - late final __objc_msgSend_1011Ptr = _lookup< + late final __objc_msgSend_1027Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.UnsignedLong)>>('objc_msgSend'); - late final __objc_msgSend_1011 = __objc_msgSend_1011Ptr.asFunction< + late final __objc_msgSend_1027 = __objc_msgSend_1027Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, int)>(); late final _sel_removeChildAtIndex_1 = _registerName1("removeChildAtIndex:"); late final _sel_setChildren_1 = _registerName1("setChildren:"); late final _sel_addChild_1 = _registerName1("addChild:"); - void _objc_msgSend_1012( + void _objc_msgSend_1028( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer child, ) { - return __objc_msgSend_1012( + return __objc_msgSend_1028( obj, sel, child, ); } - late final __objc_msgSend_1012Ptr = _lookup< + late final __objc_msgSend_1028Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_1012 = __objc_msgSend_1012Ptr.asFunction< + late final __objc_msgSend_1028 = __objc_msgSend_1028Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); late final _sel_replaceChildAtIndex_withNode_1 = _registerName1("replaceChildAtIndex:withNode:"); - void _objc_msgSend_1013( + void _objc_msgSend_1029( ffi.Pointer obj, ffi.Pointer sel, int index, ffi.Pointer node, ) { - return __objc_msgSend_1013( + return __objc_msgSend_1029( obj, sel, index, @@ -28890,52 +29277,52 @@ class SentryCocoa { ); } - late final __objc_msgSend_1013Ptr = _lookup< + late final __objc_msgSend_1029Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.UnsignedLong, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_1013 = __objc_msgSend_1013Ptr.asFunction< + late final __objc_msgSend_1029 = __objc_msgSend_1029Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, int, ffi.Pointer)>(); late final _class_NSXMLDTDNode1 = _getClass1("NSXMLDTDNode"); late final _sel_initWithXMLString_1 = _registerName1("initWithXMLString:"); late final _sel_DTDKind1 = _registerName1("DTDKind"); - int _objc_msgSend_1014( + int _objc_msgSend_1030( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_1014( + return __objc_msgSend_1030( obj, sel, ); } - late final __objc_msgSend_1014Ptr = _lookup< + late final __objc_msgSend_1030Ptr = _lookup< ffi.NativeFunction< ffi.Int32 Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_1014 = __objc_msgSend_1014Ptr.asFunction< + late final __objc_msgSend_1030 = __objc_msgSend_1030Ptr.asFunction< int Function(ffi.Pointer, ffi.Pointer)>(); late final _sel_setDTDKind_1 = _registerName1("setDTDKind:"); - void _objc_msgSend_1015( + void _objc_msgSend_1031( ffi.Pointer obj, ffi.Pointer sel, int value, ) { - return __objc_msgSend_1015( + return __objc_msgSend_1031( obj, sel, value, ); } - late final __objc_msgSend_1015Ptr = _lookup< + late final __objc_msgSend_1031Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Int32)>>('objc_msgSend'); - late final __objc_msgSend_1015 = __objc_msgSend_1015Ptr.asFunction< + late final __objc_msgSend_1031 = __objc_msgSend_1031Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, int)>(); late final _sel_isExternal1 = _registerName1("isExternal"); @@ -28945,45 +29332,45 @@ class SentryCocoa { late final _sel_prefixForName_1 = _registerName1("prefixForName:"); late final _sel_predefinedNamespaceForPrefix_1 = _registerName1("predefinedNamespaceForPrefix:"); - ffi.Pointer _objc_msgSend_1016( + ffi.Pointer _objc_msgSend_1032( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer name, ) { - return __objc_msgSend_1016( + return __objc_msgSend_1032( obj, sel, name, ); } - late final __objc_msgSend_1016Ptr = _lookup< + late final __objc_msgSend_1032Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_1016 = __objc_msgSend_1016Ptr.asFunction< + late final __objc_msgSend_1032 = __objc_msgSend_1032Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); late final _sel_entityDeclarationForName_1 = _registerName1("entityDeclarationForName:"); - ffi.Pointer _objc_msgSend_1017( + ffi.Pointer _objc_msgSend_1033( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer name, ) { - return __objc_msgSend_1017( + return __objc_msgSend_1033( obj, sel, name, ); } - late final __objc_msgSend_1017Ptr = _lookup< + late final __objc_msgSend_1033Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_1017 = __objc_msgSend_1017Ptr.asFunction< + late final __objc_msgSend_1033 = __objc_msgSend_1033Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); @@ -28993,13 +29380,13 @@ class SentryCocoa { _registerName1("elementDeclarationForName:"); late final _sel_attributeDeclarationForName_elementName_1 = _registerName1("attributeDeclarationForName:elementName:"); - ffi.Pointer _objc_msgSend_1018( + ffi.Pointer _objc_msgSend_1034( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer name, ffi.Pointer elementName, ) { - return __objc_msgSend_1018( + return __objc_msgSend_1034( obj, sel, name, @@ -29007,14 +29394,14 @@ class SentryCocoa { ); } - late final __objc_msgSend_1018Ptr = _lookup< + late final __objc_msgSend_1034Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_1018 = __objc_msgSend_1018Ptr.asFunction< + late final __objc_msgSend_1034 = __objc_msgSend_1034Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, @@ -29024,117 +29411,117 @@ class SentryCocoa { late final _sel_predefinedEntityDeclarationForName_1 = _registerName1("predefinedEntityDeclarationForName:"); late final _sel_DTD1 = _registerName1("DTD"); - ffi.Pointer _objc_msgSend_1019( + ffi.Pointer _objc_msgSend_1035( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_1019( + return __objc_msgSend_1035( obj, sel, ); } - late final __objc_msgSend_1019Ptr = _lookup< + late final __objc_msgSend_1035Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_1019 = __objc_msgSend_1019Ptr.asFunction< + late final __objc_msgSend_1035 = __objc_msgSend_1035Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>(); late final _sel_setDTD_1 = _registerName1("setDTD:"); - void _objc_msgSend_1020( + void _objc_msgSend_1036( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer value, ) { - return __objc_msgSend_1020( + return __objc_msgSend_1036( obj, sel, value, ); } - late final __objc_msgSend_1020Ptr = _lookup< + late final __objc_msgSend_1036Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_1020 = __objc_msgSend_1020Ptr.asFunction< + late final __objc_msgSend_1036 = __objc_msgSend_1036Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); late final _sel_setRootElement_1 = _registerName1("setRootElement:"); - void _objc_msgSend_1021( + void _objc_msgSend_1037( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer root, ) { - return __objc_msgSend_1021( + return __objc_msgSend_1037( obj, sel, root, ); } - late final __objc_msgSend_1021Ptr = _lookup< + late final __objc_msgSend_1037Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_1021 = __objc_msgSend_1021Ptr.asFunction< + late final __objc_msgSend_1037 = __objc_msgSend_1037Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); late final _sel_rootElement1 = _registerName1("rootElement"); - ffi.Pointer _objc_msgSend_1022( + ffi.Pointer _objc_msgSend_1038( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_1022( + return __objc_msgSend_1038( obj, sel, ); } - late final __objc_msgSend_1022Ptr = _lookup< + late final __objc_msgSend_1038Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_1022 = __objc_msgSend_1022Ptr.asFunction< + late final __objc_msgSend_1038 = __objc_msgSend_1038Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>(); late final _sel_XMLData1 = _registerName1("XMLData"); late final _sel_XMLDataWithOptions_1 = _registerName1("XMLDataWithOptions:"); - ffi.Pointer _objc_msgSend_1023( + ffi.Pointer _objc_msgSend_1039( ffi.Pointer obj, ffi.Pointer sel, int options, ) { - return __objc_msgSend_1023( + return __objc_msgSend_1039( obj, sel, options, ); } - late final __objc_msgSend_1023Ptr = _lookup< + late final __objc_msgSend_1039Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Int32)>>('objc_msgSend'); - late final __objc_msgSend_1023 = __objc_msgSend_1023Ptr.asFunction< + late final __objc_msgSend_1039 = __objc_msgSend_1039Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, int)>(); late final _sel_objectByApplyingXSLT_arguments_error_1 = _registerName1("objectByApplyingXSLT:arguments:error:"); - ffi.Pointer _objc_msgSend_1024( + ffi.Pointer _objc_msgSend_1040( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer xslt, ffi.Pointer arguments, ffi.Pointer> error, ) { - return __objc_msgSend_1024( + return __objc_msgSend_1040( obj, sel, xslt, @@ -29143,7 +29530,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_1024Ptr = _lookup< + late final __objc_msgSend_1040Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, @@ -29151,7 +29538,7 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Pointer>)>>('objc_msgSend'); - late final __objc_msgSend_1024 = __objc_msgSend_1024Ptr.asFunction< + late final __objc_msgSend_1040 = __objc_msgSend_1040Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, @@ -29161,14 +29548,14 @@ class SentryCocoa { late final _sel_objectByApplyingXSLTString_arguments_error_1 = _registerName1("objectByApplyingXSLTString:arguments:error:"); - ffi.Pointer _objc_msgSend_1025( + ffi.Pointer _objc_msgSend_1041( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer xslt, ffi.Pointer arguments, ffi.Pointer> error, ) { - return __objc_msgSend_1025( + return __objc_msgSend_1041( obj, sel, xslt, @@ -29177,7 +29564,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_1025Ptr = _lookup< + late final __objc_msgSend_1041Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, @@ -29185,7 +29572,7 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Pointer>)>>('objc_msgSend'); - late final __objc_msgSend_1025 = __objc_msgSend_1025Ptr.asFunction< + late final __objc_msgSend_1041 = __objc_msgSend_1041Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, @@ -29195,14 +29582,14 @@ class SentryCocoa { late final _sel_objectByApplyingXSLTAtURL_arguments_error_1 = _registerName1("objectByApplyingXSLTAtURL:arguments:error:"); - ffi.Pointer _objc_msgSend_1026( + ffi.Pointer _objc_msgSend_1042( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer xsltURL, ffi.Pointer argument, ffi.Pointer> error, ) { - return __objc_msgSend_1026( + return __objc_msgSend_1042( obj, sel, xsltURL, @@ -29211,7 +29598,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_1026Ptr = _lookup< + late final __objc_msgSend_1042Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, @@ -29219,7 +29606,7 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Pointer>)>>('objc_msgSend'); - late final __objc_msgSend_1026 = __objc_msgSend_1026Ptr.asFunction< + late final __objc_msgSend_1042 = __objc_msgSend_1042Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, @@ -29230,63 +29617,63 @@ class SentryCocoa { late final _sel_validateAndReturnError_1 = _registerName1("validateAndReturnError:"); late final _sel_rootDocument1 = _registerName1("rootDocument"); - ffi.Pointer _objc_msgSend_1027( + ffi.Pointer _objc_msgSend_1043( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_1027( + return __objc_msgSend_1043( obj, sel, ); } - late final __objc_msgSend_1027Ptr = _lookup< + late final __objc_msgSend_1043Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_1027 = __objc_msgSend_1027Ptr.asFunction< + late final __objc_msgSend_1043 = __objc_msgSend_1043Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>(); late final _sel_parent1 = _registerName1("parent"); - ffi.Pointer _objc_msgSend_1028( + ffi.Pointer _objc_msgSend_1044( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_1028( + return __objc_msgSend_1044( obj, sel, ); } - late final __objc_msgSend_1028Ptr = _lookup< + late final __objc_msgSend_1044Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_1028 = __objc_msgSend_1028Ptr.asFunction< + late final __objc_msgSend_1044 = __objc_msgSend_1044Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>(); late final _sel_childCount1 = _registerName1("childCount"); late final _sel_children1 = _registerName1("children"); late final _sel_childAtIndex_1 = _registerName1("childAtIndex:"); - ffi.Pointer _objc_msgSend_1029( + ffi.Pointer _objc_msgSend_1045( ffi.Pointer obj, ffi.Pointer sel, int index, ) { - return __objc_msgSend_1029( + return __objc_msgSend_1045( obj, sel, index, ); } - late final __objc_msgSend_1029Ptr = _lookup< + late final __objc_msgSend_1045Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.UnsignedLong)>>('objc_msgSend'); - late final __objc_msgSend_1029 = __objc_msgSend_1029Ptr.asFunction< + late final __objc_msgSend_1045 = __objc_msgSend_1045Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, int)>(); @@ -29303,45 +29690,45 @@ class SentryCocoa { late final _sel_XMLString1 = _registerName1("XMLString"); late final _sel_XMLStringWithOptions_1 = _registerName1("XMLStringWithOptions:"); - ffi.Pointer _objc_msgSend_1030( + ffi.Pointer _objc_msgSend_1046( ffi.Pointer obj, ffi.Pointer sel, int options, ) { - return __objc_msgSend_1030( + return __objc_msgSend_1046( obj, sel, options, ); } - late final __objc_msgSend_1030Ptr = _lookup< + late final __objc_msgSend_1046Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Int32)>>('objc_msgSend'); - late final __objc_msgSend_1030 = __objc_msgSend_1030Ptr.asFunction< + late final __objc_msgSend_1046 = __objc_msgSend_1046Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, int)>(); late final _sel_canonicalXMLStringPreservingComments_1 = _registerName1("canonicalXMLStringPreservingComments:"); - ffi.Pointer _objc_msgSend_1031( + ffi.Pointer _objc_msgSend_1047( ffi.Pointer obj, ffi.Pointer sel, bool comments, ) { - return __objc_msgSend_1031( + return __objc_msgSend_1047( obj, sel, comments, ); } - late final __objc_msgSend_1031Ptr = _lookup< + late final __objc_msgSend_1047Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Bool)>>('objc_msgSend'); - late final __objc_msgSend_1031 = __objc_msgSend_1031Ptr.asFunction< + late final __objc_msgSend_1047 = __objc_msgSend_1047Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, bool)>(); @@ -29349,14 +29736,14 @@ class SentryCocoa { _registerName1("nodesForXPath:error:"); late final _sel_objectsForXQuery_constants_error_1 = _registerName1("objectsForXQuery:constants:error:"); - ffi.Pointer _objc_msgSend_1032( + ffi.Pointer _objc_msgSend_1048( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer xquery, ffi.Pointer constants, ffi.Pointer> error, ) { - return __objc_msgSend_1032( + return __objc_msgSend_1048( obj, sel, xquery, @@ -29365,7 +29752,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_1032Ptr = _lookup< + late final __objc_msgSend_1048Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, @@ -29373,7 +29760,7 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Pointer>)>>('objc_msgSend'); - late final __objc_msgSend_1032 = __objc_msgSend_1032Ptr.asFunction< + late final __objc_msgSend_1048 = __objc_msgSend_1048Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, @@ -29401,13 +29788,13 @@ class SentryCocoa { late final _sel_attributeForName_1 = _registerName1("attributeForName:"); late final _sel_attributeForLocalName_URI_1 = _registerName1("attributeForLocalName:URI:"); - ffi.Pointer _objc_msgSend_1033( + ffi.Pointer _objc_msgSend_1049( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer localName, ffi.Pointer URI, ) { - return __objc_msgSend_1033( + return __objc_msgSend_1049( obj, sel, localName, @@ -29415,14 +29802,14 @@ class SentryCocoa { ); } - late final __objc_msgSend_1033Ptr = _lookup< + late final __objc_msgSend_1049Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_1033 = __objc_msgSend_1033Ptr.asFunction< + late final __objc_msgSend_1049 = __objc_msgSend_1049Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, @@ -29445,571 +29832,69 @@ class SentryCocoa { _registerName1("setAttributesAsDictionary:"); late final _class_PrivateSentrySDKOnly1 = _getClass1("PrivateSentrySDKOnly"); late final _class_SentryEnvelope1 = _getClass1("SentryEnvelope"); - late final _class_SentryId1 = _getClass1("SentryId"); - late final _class_NSUUID1 = _getClass1("NSUUID"); - late final _sel_UUID1 = _registerName1("UUID"); - late final _sel_initWithUUIDString_1 = _registerName1("initWithUUIDString:"); - late final _sel_initWithUUIDBytes_1 = _registerName1("initWithUUIDBytes:"); - instancetype _objc_msgSend_1034( - ffi.Pointer obj, - ffi.Pointer sel, - ffi.Pointer bytes, - ) { - return __objc_msgSend_1034( - obj, - sel, - bytes, - ); - } - - late final __objc_msgSend_1034Ptr = _lookup< - ffi.NativeFunction< - instancetype Function(ffi.Pointer, ffi.Pointer, - ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_1034 = __objc_msgSend_1034Ptr.asFunction< - instancetype Function(ffi.Pointer, ffi.Pointer, - ffi.Pointer)>(); - - late final _sel_getUUIDBytes_1 = _registerName1("getUUIDBytes:"); - void _objc_msgSend_1035( - ffi.Pointer obj, - ffi.Pointer sel, - ffi.Pointer uuid, - ) { - return __objc_msgSend_1035( - obj, - sel, - uuid, - ); - } - - late final __objc_msgSend_1035Ptr = _lookup< - ffi.NativeFunction< - ffi.Void Function(ffi.Pointer, ffi.Pointer, - ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_1035 = __objc_msgSend_1035Ptr.asFunction< - void Function(ffi.Pointer, ffi.Pointer, - ffi.Pointer)>(); - - int _objc_msgSend_1036( - ffi.Pointer obj, - ffi.Pointer sel, - ffi.Pointer otherUUID, - ) { - return __objc_msgSend_1036( - obj, - sel, - otherUUID, - ); - } - - late final __objc_msgSend_1036Ptr = _lookup< - ffi.NativeFunction< - ffi.Int32 Function(ffi.Pointer, ffi.Pointer, - ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_1036 = __objc_msgSend_1036Ptr.asFunction< - int Function(ffi.Pointer, ffi.Pointer, - ffi.Pointer)>(); - - late final _sel_UUIDString1 = _registerName1("UUIDString"); - late final _sel_initWithUUID_1 = _registerName1("initWithUUID:"); - instancetype _objc_msgSend_1037( - ffi.Pointer obj, - ffi.Pointer sel, - ffi.Pointer uuid, - ) { - return __objc_msgSend_1037( - obj, - sel, - uuid, - ); - } - - late final __objc_msgSend_1037Ptr = _lookup< - ffi.NativeFunction< - instancetype Function(ffi.Pointer, ffi.Pointer, - ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_1037 = __objc_msgSend_1037Ptr.asFunction< - instancetype Function(ffi.Pointer, ffi.Pointer, - ffi.Pointer)>(); - - late final _sel_sentryIdString1 = _registerName1("sentryIdString"); - late final _sel_empty1 = _registerName1("empty"); - ffi.Pointer _objc_msgSend_1038( - ffi.Pointer obj, - ffi.Pointer sel, - ) { - return __objc_msgSend_1038( - obj, - sel, - ); - } - - late final __objc_msgSend_1038Ptr = _lookup< - ffi.NativeFunction< - ffi.Pointer Function( - ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_1038 = __objc_msgSend_1038Ptr.asFunction< - ffi.Pointer Function( - ffi.Pointer, ffi.Pointer)>(); - - late final _class_SentryEnvelopeItem1 = _getClass1("SentryEnvelopeItem"); - late final _class_SentryEvent1 = _getClass1("SentryEvent"); - late final _sel_initWithEvent_1 = _registerName1("initWithEvent:"); - instancetype _objc_msgSend_1039( - ffi.Pointer obj, - ffi.Pointer sel, - ffi.Pointer event, - ) { - return __objc_msgSend_1039( - obj, - sel, - event, - ); - } - - late final __objc_msgSend_1039Ptr = _lookup< - ffi.NativeFunction< - instancetype Function(ffi.Pointer, ffi.Pointer, - ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_1039 = __objc_msgSend_1039Ptr.asFunction< - instancetype Function(ffi.Pointer, ffi.Pointer, - ffi.Pointer)>(); - - late final _class_SentrySession1 = _getClass1("SentrySession"); - late final _sel_initWithSession_1 = _registerName1("initWithSession:"); - instancetype _objc_msgSend_1040( - ffi.Pointer obj, - ffi.Pointer sel, - ffi.Pointer session, - ) { - return __objc_msgSend_1040( - obj, - sel, - session, - ); - } - - late final __objc_msgSend_1040Ptr = _lookup< - ffi.NativeFunction< - instancetype Function(ffi.Pointer, ffi.Pointer, - ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_1040 = __objc_msgSend_1040Ptr.asFunction< - instancetype Function(ffi.Pointer, ffi.Pointer, - ffi.Pointer)>(); - - late final _class_SentryUserFeedback1 = _getClass1("SentryUserFeedback"); - late final _sel_initWithUserFeedback_1 = - _registerName1("initWithUserFeedback:"); - instancetype _objc_msgSend_1041( - ffi.Pointer obj, - ffi.Pointer sel, - ffi.Pointer userFeedback, - ) { - return __objc_msgSend_1041( - obj, - sel, - userFeedback, - ); - } - - late final __objc_msgSend_1041Ptr = _lookup< - ffi.NativeFunction< - instancetype Function(ffi.Pointer, ffi.Pointer, - ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_1041 = __objc_msgSend_1041Ptr.asFunction< - instancetype Function(ffi.Pointer, ffi.Pointer, - ffi.Pointer)>(); - - late final _class_SentryAttachment1 = _getClass1("SentryAttachment"); - late final _sel_initWithAttachment_maxAttachmentSize_1 = - _registerName1("initWithAttachment:maxAttachmentSize:"); - instancetype _objc_msgSend_1042( - ffi.Pointer obj, - ffi.Pointer sel, - ffi.Pointer attachment, - int maxAttachmentSize, - ) { - return __objc_msgSend_1042( - obj, - sel, - attachment, - maxAttachmentSize, - ); - } - - late final __objc_msgSend_1042Ptr = _lookup< - ffi.NativeFunction< - instancetype Function(ffi.Pointer, ffi.Pointer, - ffi.Pointer, ffi.UnsignedLong)>>('objc_msgSend'); - late final __objc_msgSend_1042 = __objc_msgSend_1042Ptr.asFunction< - instancetype Function(ffi.Pointer, ffi.Pointer, - ffi.Pointer, int)>(); - - late final _class_SentryEnvelopeItemHeader1 = - _getClass1("SentryEnvelopeItemHeader"); - late final _sel_initWithHeader_data_1 = - _registerName1("initWithHeader:data:"); - instancetype _objc_msgSend_1043( - ffi.Pointer obj, - ffi.Pointer sel, - ffi.Pointer header, - ffi.Pointer data, - ) { - return __objc_msgSend_1043( - obj, - sel, - header, - data, - ); - } - - late final __objc_msgSend_1043Ptr = _lookup< - ffi.NativeFunction< - instancetype Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_1043 = __objc_msgSend_1043Ptr.asFunction< - instancetype Function(ffi.Pointer, ffi.Pointer, - ffi.Pointer, ffi.Pointer)>(); - - late final _sel_header1 = _registerName1("header"); - ffi.Pointer _objc_msgSend_1044( - ffi.Pointer obj, - ffi.Pointer sel, - ) { - return __objc_msgSend_1044( - obj, - sel, - ); - } - - late final __objc_msgSend_1044Ptr = _lookup< - ffi.NativeFunction< - ffi.Pointer Function( - ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_1044 = __objc_msgSend_1044Ptr.asFunction< - ffi.Pointer Function( - ffi.Pointer, ffi.Pointer)>(); - - late final _sel_initWithId_singleItem_1 = - _registerName1("initWithId:singleItem:"); - instancetype _objc_msgSend_1045( - ffi.Pointer obj, - ffi.Pointer sel, - ffi.Pointer id, - ffi.Pointer item, - ) { - return __objc_msgSend_1045( - obj, - sel, - id, - item, - ); - } - - late final __objc_msgSend_1045Ptr = _lookup< - ffi.NativeFunction< - instancetype Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_1045 = __objc_msgSend_1045Ptr.asFunction< - instancetype Function(ffi.Pointer, ffi.Pointer, - ffi.Pointer, ffi.Pointer)>(); - - late final _class_SentryEnvelopeHeader1 = _getClass1("SentryEnvelopeHeader"); - late final _sel_initWithId_1 = _registerName1("initWithId:"); - instancetype _objc_msgSend_1046( - ffi.Pointer obj, - ffi.Pointer sel, - ffi.Pointer eventId, - ) { - return __objc_msgSend_1046( - obj, - sel, - eventId, - ); - } - - late final __objc_msgSend_1046Ptr = _lookup< - ffi.NativeFunction< - instancetype Function(ffi.Pointer, ffi.Pointer, - ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_1046 = __objc_msgSend_1046Ptr.asFunction< - instancetype Function(ffi.Pointer, ffi.Pointer, - ffi.Pointer)>(); - - late final _class_SentryTraceContext1 = _getClass1("SentryTraceContext"); - late final _sel_initWithId_traceContext_1 = - _registerName1("initWithId:traceContext:"); - instancetype _objc_msgSend_1047( - ffi.Pointer obj, - ffi.Pointer sel, - ffi.Pointer eventId, - ffi.Pointer traceContext, - ) { - return __objc_msgSend_1047( - obj, - sel, - eventId, - traceContext, - ); - } - - late final __objc_msgSend_1047Ptr = _lookup< - ffi.NativeFunction< - instancetype Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_1047 = __objc_msgSend_1047Ptr.asFunction< - instancetype Function(ffi.Pointer, ffi.Pointer, - ffi.Pointer, ffi.Pointer)>(); - - late final _class_SentrySdkInfo1 = _getClass1("SentrySdkInfo"); - late final _sel_initWithId_sdkInfo_traceContext_1 = - _registerName1("initWithId:sdkInfo:traceContext:"); - instancetype _objc_msgSend_1048( - ffi.Pointer obj, - ffi.Pointer sel, - ffi.Pointer eventId, - ffi.Pointer sdkInfo, - ffi.Pointer traceContext, - ) { - return __objc_msgSend_1048( - obj, - sel, - eventId, - sdkInfo, - traceContext, - ); - } - - late final __objc_msgSend_1048Ptr = _lookup< - ffi.NativeFunction< - instancetype Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_1048 = __objc_msgSend_1048Ptr.asFunction< - instancetype Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer)>(); - - late final _sel_eventId1 = _registerName1("eventId"); - late final _sel_sdkInfo1 = _registerName1("sdkInfo"); - ffi.Pointer _objc_msgSend_1049( - ffi.Pointer obj, - ffi.Pointer sel, - ) { - return __objc_msgSend_1049( - obj, - sel, - ); - } - - late final __objc_msgSend_1049Ptr = _lookup< - ffi.NativeFunction< - ffi.Pointer Function( - ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_1049 = __objc_msgSend_1049Ptr.asFunction< - ffi.Pointer Function( - ffi.Pointer, ffi.Pointer)>(); - - late final _sel_traceContext1 = _registerName1("traceContext"); - ffi.Pointer _objc_msgSend_1050( - ffi.Pointer obj, - ffi.Pointer sel, - ) { - return __objc_msgSend_1050( - obj, - sel, - ); - } - - late final __objc_msgSend_1050Ptr = _lookup< - ffi.NativeFunction< - ffi.Pointer Function( - ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_1050 = __objc_msgSend_1050Ptr.asFunction< - ffi.Pointer Function( - ffi.Pointer, ffi.Pointer)>(); - - late final _sel_sentAt1 = _registerName1("sentAt"); - late final _sel_setSentAt_1 = _registerName1("setSentAt:"); - late final _sel_initWithHeader_singleItem_1 = - _registerName1("initWithHeader:singleItem:"); - instancetype _objc_msgSend_1051( - ffi.Pointer obj, - ffi.Pointer sel, - ffi.Pointer header, - ffi.Pointer item, - ) { - return __objc_msgSend_1051( - obj, - sel, - header, - item, - ); - } - - late final __objc_msgSend_1051Ptr = _lookup< - ffi.NativeFunction< - instancetype Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_1051 = __objc_msgSend_1051Ptr.asFunction< - instancetype Function(ffi.Pointer, ffi.Pointer, - ffi.Pointer, ffi.Pointer)>(); - - late final _sel_initWithId_items_1 = _registerName1("initWithId:items:"); - instancetype _objc_msgSend_1052( - ffi.Pointer obj, - ffi.Pointer sel, - ffi.Pointer id, - ffi.Pointer items, - ) { - return __objc_msgSend_1052( - obj, - sel, - id, - items, - ); - } - - late final __objc_msgSend_1052Ptr = _lookup< - ffi.NativeFunction< - instancetype Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_1052 = __objc_msgSend_1052Ptr.asFunction< - instancetype Function(ffi.Pointer, ffi.Pointer, - ffi.Pointer, ffi.Pointer)>(); - - late final _sel_initWithSessions_1 = _registerName1("initWithSessions:"); - late final _sel_initWithHeader_items_1 = - _registerName1("initWithHeader:items:"); - instancetype _objc_msgSend_1053( - ffi.Pointer obj, - ffi.Pointer sel, - ffi.Pointer header, - ffi.Pointer items, - ) { - return __objc_msgSend_1053( - obj, - sel, - header, - items, - ); - } - - late final __objc_msgSend_1053Ptr = _lookup< - ffi.NativeFunction< - instancetype Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_1053 = __objc_msgSend_1053Ptr.asFunction< - instancetype Function(ffi.Pointer, ffi.Pointer, - ffi.Pointer, ffi.Pointer)>(); - - ffi.Pointer _objc_msgSend_1054( - ffi.Pointer obj, - ffi.Pointer sel, - ) { - return __objc_msgSend_1054( - obj, - sel, - ); - } - - late final __objc_msgSend_1054Ptr = _lookup< - ffi.NativeFunction< - ffi.Pointer Function( - ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_1054 = __objc_msgSend_1054Ptr.asFunction< - ffi.Pointer Function( - ffi.Pointer, ffi.Pointer)>(); - - late final _sel_items1 = _registerName1("items"); late final _sel_storeEnvelope_1 = _registerName1("storeEnvelope:"); - void _objc_msgSend_1055( + void _objc_msgSend_1050( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer envelope, ) { - return __objc_msgSend_1055( + return __objc_msgSend_1050( obj, sel, envelope, ); } - late final __objc_msgSend_1055Ptr = _lookup< + late final __objc_msgSend_1050Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_1055 = __objc_msgSend_1055Ptr.asFunction< + late final __objc_msgSend_1050 = __objc_msgSend_1050Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); late final _sel_captureEnvelope_1 = _registerName1("captureEnvelope:"); late final _sel_envelopeWithData_1 = _registerName1("envelopeWithData:"); - ffi.Pointer _objc_msgSend_1056( + ffi.Pointer _objc_msgSend_1051( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer data, ) { - return __objc_msgSend_1056( + return __objc_msgSend_1051( obj, sel, data, ); } - late final __objc_msgSend_1056Ptr = _lookup< + late final __objc_msgSend_1051Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_1056 = __objc_msgSend_1056Ptr.asFunction< + late final __objc_msgSend_1051 = __objc_msgSend_1051Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); late final _sel_getDebugImages1 = _registerName1("getDebugImages"); late final _sel_getDebugImagesCrashed_1 = _registerName1("getDebugImagesCrashed:"); - ffi.Pointer _objc_msgSend_1057( + ffi.Pointer _objc_msgSend_1052( ffi.Pointer obj, ffi.Pointer sel, bool isCrash, ) { - return __objc_msgSend_1057( + return __objc_msgSend_1052( obj, sel, isCrash, ); } - late final __objc_msgSend_1057Ptr = _lookup< + late final __objc_msgSend_1052Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Bool)>>('objc_msgSend'); - late final __objc_msgSend_1057 = __objc_msgSend_1057Ptr.asFunction< + late final __objc_msgSend_1052 = __objc_msgSend_1052Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, bool)>(); @@ -30019,38 +29904,39 @@ class SentryCocoa { late final _sel_getSdkName1 = _registerName1("getSdkName"); late final _sel_getSdkVersionString1 = _registerName1("getSdkVersionString"); late final _sel_getExtraContext1 = _registerName1("getExtraContext"); + late final _class_SentryId2 = _getClass1("Sentry.SentryId"); late final _sel_startProfilerForTrace_1 = _registerName1("startProfilerForTrace:"); - int _objc_msgSend_1058( + int _objc_msgSend_1053( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer traceId, ) { - return __objc_msgSend_1058( + return __objc_msgSend_1053( obj, sel, traceId, ); } - late final __objc_msgSend_1058Ptr = _lookup< + late final __objc_msgSend_1053Ptr = _lookup< ffi.NativeFunction< ffi.Uint64 Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_1058 = __objc_msgSend_1058Ptr.asFunction< + late final __objc_msgSend_1053 = __objc_msgSend_1053Ptr.asFunction< int Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); late final _sel_collectProfileBetween_and_forTrace_1 = _registerName1("collectProfileBetween:and:forTrace:"); - ffi.Pointer _objc_msgSend_1059( + ffi.Pointer _objc_msgSend_1054( ffi.Pointer obj, ffi.Pointer sel, int startSystemTime, int endSystemTime, ffi.Pointer traceId, ) { - return __objc_msgSend_1059( + return __objc_msgSend_1054( obj, sel, startSystemTime, @@ -30059,7 +29945,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_1059Ptr = _lookup< + late final __objc_msgSend_1054Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, @@ -30067,29 +29953,29 @@ class SentryCocoa { ffi.Uint64, ffi.Uint64, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_1059 = __objc_msgSend_1059Ptr.asFunction< + late final __objc_msgSend_1054 = __objc_msgSend_1054Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, int, int, ffi.Pointer)>(); late final _sel_discardProfilerForTrace_1 = _registerName1("discardProfilerForTrace:"); - void _objc_msgSend_1060( + void _objc_msgSend_1055( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer traceId, ) { - return __objc_msgSend_1060( + return __objc_msgSend_1055( obj, sel, traceId, ); } - late final __objc_msgSend_1060Ptr = _lookup< + late final __objc_msgSend_1055Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_1060 = __objc_msgSend_1060Ptr.asFunction< + late final __objc_msgSend_1055 = __objc_msgSend_1055Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); @@ -30097,82 +29983,82 @@ class SentryCocoa { _getClass1("SentryAppStartMeasurement"); late final _sel_onAppStartMeasurementAvailable1 = _registerName1("onAppStartMeasurementAvailable"); - ffi.Pointer<_ObjCBlock> _objc_msgSend_1061( + ffi.Pointer<_ObjCBlock> _objc_msgSend_1056( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_1061( + return __objc_msgSend_1056( obj, sel, ); } - late final __objc_msgSend_1061Ptr = _lookup< + late final __objc_msgSend_1056Ptr = _lookup< ffi.NativeFunction< ffi.Pointer<_ObjCBlock> Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_1061 = __objc_msgSend_1061Ptr.asFunction< + late final __objc_msgSend_1056 = __objc_msgSend_1056Ptr.asFunction< ffi.Pointer<_ObjCBlock> Function( ffi.Pointer, ffi.Pointer)>(); late final _sel_setOnAppStartMeasurementAvailable_1 = _registerName1("setOnAppStartMeasurementAvailable:"); - void _objc_msgSend_1062( + void _objc_msgSend_1057( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer<_ObjCBlock> value, ) { - return __objc_msgSend_1062( + return __objc_msgSend_1057( obj, sel, value, ); } - late final __objc_msgSend_1062Ptr = _lookup< + late final __objc_msgSend_1057Ptr = _lookup< ffi.NativeFunction< ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer<_ObjCBlock>)>>('objc_msgSend'); - late final __objc_msgSend_1062 = __objc_msgSend_1062Ptr.asFunction< + late final __objc_msgSend_1057 = __objc_msgSend_1057Ptr.asFunction< void Function(ffi.Pointer, ffi.Pointer, ffi.Pointer<_ObjCBlock>)>(); late final _sel_appStartMeasurement1 = _registerName1("appStartMeasurement"); - ffi.Pointer _objc_msgSend_1063( + ffi.Pointer _objc_msgSend_1058( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_1063( + return __objc_msgSend_1058( obj, sel, ); } - late final __objc_msgSend_1063Ptr = _lookup< + late final __objc_msgSend_1058Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_1063 = __objc_msgSend_1063Ptr.asFunction< + late final __objc_msgSend_1058 = __objc_msgSend_1058Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>(); late final _sel_installationID1 = _registerName1("installationID"); late final _class_SentryOptions1 = _getClass1("SentryOptions"); - ffi.Pointer _objc_msgSend_1064( + ffi.Pointer _objc_msgSend_1059( ffi.Pointer obj, ffi.Pointer sel, ) { - return __objc_msgSend_1064( + return __objc_msgSend_1059( obj, sel, ); } - late final __objc_msgSend_1064Ptr = _lookup< + late final __objc_msgSend_1059Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_1064 = __objc_msgSend_1064Ptr.asFunction< + late final __objc_msgSend_1059 = __objc_msgSend_1059Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer)>(); @@ -30182,71 +30068,224 @@ class SentryCocoa { _registerName1("setAppStartMeasurementHybridSDKMode:"); late final _class_SentryUser1 = _getClass1("SentryUser"); late final _sel_userWithDictionary_1 = _registerName1("userWithDictionary:"); - ffi.Pointer _objc_msgSend_1065( + ffi.Pointer _objc_msgSend_1060( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer dictionary, ) { - return __objc_msgSend_1065( + return __objc_msgSend_1060( obj, sel, dictionary, ); } - late final __objc_msgSend_1065Ptr = _lookup< + late final __objc_msgSend_1060Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_1065 = __objc_msgSend_1065Ptr.asFunction< + late final __objc_msgSend_1060 = __objc_msgSend_1060Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); late final _class_SentryBreadcrumb1 = _getClass1("SentryBreadcrumb"); late final _sel_breadcrumbWithDictionary_1 = _registerName1("breadcrumbWithDictionary:"); - ffi.Pointer _objc_msgSend_1066( + ffi.Pointer _objc_msgSend_1061( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer dictionary, ) { - return __objc_msgSend_1066( + return __objc_msgSend_1061( obj, sel, dictionary, ); } - late final __objc_msgSend_1066Ptr = _lookup< + late final __objc_msgSend_1061Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_1066 = __objc_msgSend_1066Ptr.asFunction< + late final __objc_msgSend_1061 = __objc_msgSend_1061Ptr.asFunction< ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); -} - -class _ObjCWrapper implements ffi.Finalizable { - final ffi.Pointer _id; - final SentryCocoa _lib; - bool _pendingRelease; - _ObjCWrapper._(this._id, this._lib, - {bool retain = false, bool release = false}) - : _pendingRelease = release { - if (retain) { - _lib._objc_retain(_id.cast()); - } - if (release) { - _lib._objc_releaseFinalizer2.attach(this, _id.cast(), detach: this); - } + late final _class_SentryCurrentDateProvider1 = + _getClass1("SentryCurrentDateProvider"); + late final _sel_timezoneOffset1 = _registerName1("timezoneOffset"); + late final _sel_systemTime1 = _registerName1("systemTime"); + int _objc_msgSend_1062( + ffi.Pointer obj, + ffi.Pointer sel, + ) { + return __objc_msgSend_1062( + obj, + sel, + ); } - /// Releases the reference to the underlying ObjC object held by this wrapper. - /// Throws a StateError if this wrapper doesn't currently hold a reference. - void release() { - if (_pendingRelease) { - _pendingRelease = false; + late final __objc_msgSend_1062Ptr = _lookup< + ffi.NativeFunction< + ffi.Uint64 Function( + ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); + late final __objc_msgSend_1062 = __objc_msgSend_1062Ptr.asFunction< + int Function(ffi.Pointer, ffi.Pointer)>(); + + late final _sel_bucketTimestamp1 = _registerName1("bucketTimestamp"); + late final _class_SentryId11 = _getClass1("Sentry.SentryId"); + late final _sel_empty1 = _registerName1("empty"); + ffi.Pointer _objc_msgSend_1063( + ffi.Pointer obj, + ffi.Pointer sel, + ) { + return __objc_msgSend_1063( + obj, + sel, + ); + } + + late final __objc_msgSend_1063Ptr = _lookup< + ffi.NativeFunction< + ffi.Pointer Function( + ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); + late final __objc_msgSend_1063 = __objc_msgSend_1063Ptr.asFunction< + ffi.Pointer Function( + ffi.Pointer, ffi.Pointer)>(); + + late final _sel_setEmpty_1 = _registerName1("setEmpty:"); + void _objc_msgSend_1064( + ffi.Pointer obj, + ffi.Pointer sel, + ffi.Pointer value, + ) { + return __objc_msgSend_1064( + obj, + sel, + value, + ); + } + + late final __objc_msgSend_1064Ptr = _lookup< + ffi.NativeFunction< + ffi.Void Function(ffi.Pointer, ffi.Pointer, + ffi.Pointer)>>('objc_msgSend'); + late final __objc_msgSend_1064 = __objc_msgSend_1064Ptr.asFunction< + void Function(ffi.Pointer, ffi.Pointer, + ffi.Pointer)>(); + + late final _sel_sentryIdString1 = _registerName1("sentryIdString"); + late final _class_NSUUID1 = _getClass1("NSUUID"); + late final _sel_UUID1 = _registerName1("UUID"); + late final _sel_initWithUUIDString_1 = _registerName1("initWithUUIDString:"); + late final _sel_initWithUUIDBytes_1 = _registerName1("initWithUUIDBytes:"); + instancetype _objc_msgSend_1065( + ffi.Pointer obj, + ffi.Pointer sel, + ffi.Pointer bytes, + ) { + return __objc_msgSend_1065( + obj, + sel, + bytes, + ); + } + + late final __objc_msgSend_1065Ptr = _lookup< + ffi.NativeFunction< + instancetype Function(ffi.Pointer, ffi.Pointer, + ffi.Pointer)>>('objc_msgSend'); + late final __objc_msgSend_1065 = __objc_msgSend_1065Ptr.asFunction< + instancetype Function(ffi.Pointer, ffi.Pointer, + ffi.Pointer)>(); + + late final _sel_getUUIDBytes_1 = _registerName1("getUUIDBytes:"); + void _objc_msgSend_1066( + ffi.Pointer obj, + ffi.Pointer sel, + ffi.Pointer uuid, + ) { + return __objc_msgSend_1066( + obj, + sel, + uuid, + ); + } + + late final __objc_msgSend_1066Ptr = _lookup< + ffi.NativeFunction< + ffi.Void Function(ffi.Pointer, ffi.Pointer, + ffi.Pointer)>>('objc_msgSend'); + late final __objc_msgSend_1066 = __objc_msgSend_1066Ptr.asFunction< + void Function(ffi.Pointer, ffi.Pointer, + ffi.Pointer)>(); + + int _objc_msgSend_1067( + ffi.Pointer obj, + ffi.Pointer sel, + ffi.Pointer otherUUID, + ) { + return __objc_msgSend_1067( + obj, + sel, + otherUUID, + ); + } + + late final __objc_msgSend_1067Ptr = _lookup< + ffi.NativeFunction< + ffi.Int32 Function(ffi.Pointer, ffi.Pointer, + ffi.Pointer)>>('objc_msgSend'); + late final __objc_msgSend_1067 = __objc_msgSend_1067Ptr.asFunction< + int Function(ffi.Pointer, ffi.Pointer, + ffi.Pointer)>(); + + late final _sel_UUIDString1 = _registerName1("UUIDString"); + late final _sel_initWithUuid_1 = _registerName1("initWithUuid:"); + instancetype _objc_msgSend_1068( + ffi.Pointer obj, + ffi.Pointer sel, + ffi.Pointer uuid, + ) { + return __objc_msgSend_1068( + obj, + sel, + uuid, + ); + } + + late final __objc_msgSend_1068Ptr = _lookup< + ffi.NativeFunction< + instancetype Function(ffi.Pointer, ffi.Pointer, + ffi.Pointer)>>('objc_msgSend'); + late final __objc_msgSend_1068 = __objc_msgSend_1068Ptr.asFunction< + instancetype Function(ffi.Pointer, ffi.Pointer, + ffi.Pointer)>(); + + late final _sel_isEqual_1 = _registerName1("isEqual:"); +} + +class _ObjCWrapper implements ffi.Finalizable { + final ffi.Pointer _id; + final SentryCocoa _lib; + bool _pendingRelease; + + _ObjCWrapper._(this._id, this._lib, + {bool retain = false, bool release = false}) + : _pendingRelease = release { + if (retain) { + _lib._objc_retain(_id.cast()); + } + if (release) { + _lib._objc_releaseFinalizer2.attach(this, _id.cast(), detach: this); + } + } + + /// Releases the reference to the underlying ObjC object held by this wrapper. + /// Throws a StateError if this wrapper doesn't currently hold a reference. + void release() { + if (_pendingRelease) { + _pendingRelease = false; _lib._objc_release(_id.cast()); _lib._objc_releaseFinalizer2.detach(this); } else { @@ -30614,7 +30653,7 @@ class NSObject extends _ObjCWrapper { bool validateValue_forKey_error_(ffi.Pointer> ioValue, NSString? inKey, ffi.Pointer> outError) { - return _lib._objc_msgSend_226(_id, _lib._sel_validateValue_forKey_error_1, + return _lib._objc_msgSend_225(_id, _lib._sel_validateValue_forKey_error_1, ioValue, inKey?._id ?? ffi.nullptr, outError); } @@ -30651,7 +30690,7 @@ class NSObject extends _ObjCWrapper { ffi.Pointer> ioValue, NSString? inKeyPath, ffi.Pointer> outError) { - return _lib._objc_msgSend_226( + return _lib._objc_msgSend_225( _id, _lib._sel_validateValue_forKeyPath_error_1, ioValue, @@ -32756,7 +32795,7 @@ class NSString extends NSObject { } NSString initWithFormat_arguments_( - NSString? format, ffi.Pointer<__va_list_tag> argList) { + NSString? format, ffi.Pointer argList) { final _ret = _lib._objc_msgSend_348( _id, _lib._sel_initWithFormat_arguments_1, @@ -32772,7 +32811,7 @@ class NSString extends NSObject { } NSString initWithFormat_locale_arguments_( - NSString? format, NSObject locale, ffi.Pointer<__va_list_tag> argList) { + NSString? format, NSObject locale, ffi.Pointer argList) { final _ret = _lib._objc_msgSend_349( _id, _lib._sel_initWithFormat_locale_arguments_1, @@ -32813,7 +32852,7 @@ class NSString extends NSObject { NSString initWithValidatedFormat_validFormatSpecifiers_arguments_error_( NSString? format, NSString? validFormatSpecifiers, - ffi.Pointer<__va_list_tag> argList, + ffi.Pointer argList, ffi.Pointer> error) { final _ret = _lib._objc_msgSend_352( _id, @@ -32830,7 +32869,7 @@ class NSString extends NSObject { NSString? format, NSString? validFormatSpecifiers, NSObject locale, - ffi.Pointer<__va_list_tag> argList, + ffi.Pointer argList, ffi.Pointer> error) { final _ret = _lib._objc_msgSend_353( _id, @@ -34563,6 +34602,26 @@ class NSURL extends NSObject { return NSURL._(_ret, _lib, retain: true, release: true); } + NSURL initWithString_encodingInvalidCharacters_( + NSString? URLString, bool encodingInvalidCharacters) { + final _ret = _lib._objc_msgSend_29( + _id, + _lib._sel_initWithString_encodingInvalidCharacters_1, + URLString?._id ?? ffi.nullptr, + encodingInvalidCharacters); + return NSURL._(_ret, _lib, retain: true, release: true); + } + + static NSURL URLWithString_encodingInvalidCharacters_( + SentryCocoa _lib, NSString? URLString, bool encodingInvalidCharacters) { + final _ret = _lib._objc_msgSend_29( + _lib._class_NSURL1, + _lib._sel_URLWithString_encodingInvalidCharacters_1, + URLString?._id ?? ffi.nullptr, + encodingInvalidCharacters); + return NSURL._(_ret, _lib, retain: true, release: true); + } + NSURL initWithDataRepresentation_relativeToURL_( NSData? data, NSURL? baseURL) { final _ret = _lib._objc_msgSend_37( @@ -34743,12 +34802,6 @@ class NSURL extends NSObject { : NSURL._(_ret, _lib, retain: true, release: true); } - bool checkResourceIsReachableAndReturnError_( - ffi.Pointer> error) { - return _lib._objc_msgSend_225( - _id, _lib._sel_checkResourceIsReachableAndReturnError_1, error); - } - bool isFileReferenceURL() { return _lib._objc_msgSend_12(_id, _lib._sel_isFileReferenceURL1); } @@ -34769,13 +34822,13 @@ class NSURL extends NSObject { ffi.Pointer> value, NSString key, ffi.Pointer> error) { - return _lib._objc_msgSend_226( + return _lib._objc_msgSend_225( _id, _lib._sel_getResourceValue_forKey_error_1, value, key._id, error); } NSObject resourceValuesForKeys_error_( NSArray? keys, ffi.Pointer> error) { - final _ret = _lib._objc_msgSend_227( + final _ret = _lib._objc_msgSend_226( _id, _lib._sel_resourceValuesForKeys_error_1, keys?._id ?? ffi.nullptr, @@ -34785,13 +34838,13 @@ class NSURL extends NSObject { bool setResourceValue_forKey_error_(NSObject value, NSString key, ffi.Pointer> error) { - return _lib._objc_msgSend_228(_id, + return _lib._objc_msgSend_227(_id, _lib._sel_setResourceValue_forKey_error_1, value._id, key._id, error); } bool setResourceValues_error_( NSObject? keyedValues, ffi.Pointer> error) { - return _lib._objc_msgSend_229(_id, _lib._sel_setResourceValues_error_1, + return _lib._objc_msgSend_228(_id, _lib._sel_setResourceValues_error_1, keyedValues?._id ?? ffi.nullptr, error); } @@ -34815,7 +34868,7 @@ class NSURL extends NSObject { NSArray? keys, NSURL? relativeURL, ffi.Pointer> error) { - final _ret = _lib._objc_msgSend_230( + final _ret = _lib._objc_msgSend_229( _id, _lib._sel_bookmarkDataWithOptions_includingResourceValuesForKeys_relativeToURL_error_1, options, @@ -34832,7 +34885,7 @@ class NSURL extends NSObject { NSURL? relativeURL, ffi.Pointer isStale, ffi.Pointer> error) { - final _ret = _lib._objc_msgSend_231( + final _ret = _lib._objc_msgSend_230( _id, _lib._sel_initByResolvingBookmarkData_options_relativeToURL_bookmarkDataIsStale_error_1, bookmarkData?._id ?? ffi.nullptr, @@ -34851,7 +34904,7 @@ class NSURL extends NSObject { NSURL? relativeURL, ffi.Pointer isStale, ffi.Pointer> error) { - final _ret = _lib._objc_msgSend_231( + final _ret = _lib._objc_msgSend_230( _lib._class_NSURL1, _lib._sel_URLByResolvingBookmarkData_options_relativeToURL_bookmarkDataIsStale_error_1, bookmarkData?._id ?? ffi.nullptr, @@ -34864,7 +34917,7 @@ class NSURL extends NSObject { static NSObject resourceValuesForKeys_fromBookmarkData_( SentryCocoa _lib, NSArray? keys, NSData? bookmarkData) { - final _ret = _lib._objc_msgSend_232( + final _ret = _lib._objc_msgSend_231( _lib._class_NSURL1, _lib._sel_resourceValuesForKeys_fromBookmarkData_1, keys?._id ?? ffi.nullptr, @@ -34878,7 +34931,7 @@ class NSURL extends NSObject { NSURL? bookmarkFileURL, int options, ffi.Pointer> error) { - return _lib._objc_msgSend_233( + return _lib._objc_msgSend_232( _lib._class_NSURL1, _lib._sel_writeBookmarkData_toURL_options_error_1, bookmarkData?._id ?? ffi.nullptr, @@ -34889,7 +34942,7 @@ class NSURL extends NSObject { static NSData bookmarkDataWithContentsOfURL_error_(SentryCocoa _lib, NSURL? bookmarkFileURL, ffi.Pointer> error) { - final _ret = _lib._objc_msgSend_234( + final _ret = _lib._objc_msgSend_233( _lib._class_NSURL1, _lib._sel_bookmarkDataWithContentsOfURL_error_1, bookmarkFileURL?._id ?? ffi.nullptr, @@ -34899,7 +34952,7 @@ class NSURL extends NSObject { static NSURL URLByResolvingAliasFileAtURL_options_error_(SentryCocoa _lib, NSURL? url, int options, ffi.Pointer> error) { - final _ret = _lib._objc_msgSend_235( + final _ret = _lib._objc_msgSend_234( _lib._class_NSURL1, _lib._sel_URLByResolvingAliasFileAtURL_options_error_1, url?._id ?? ffi.nullptr, @@ -34921,7 +34974,7 @@ class NSURL extends NSObject { ffi.Pointer> value, NSString key, ffi.Pointer> error) { - return _lib._objc_msgSend_226( + return _lib._objc_msgSend_225( _id, _lib._sel_getPromisedItemResourceValue_forKey_error_1, value, @@ -34931,7 +34984,7 @@ class NSURL extends NSObject { NSDictionary promisedItemResourceValuesForKeys_error_( NSArray? keys, ffi.Pointer> error) { - final _ret = _lib._objc_msgSend_236( + final _ret = _lib._objc_msgSend_235( _id, _lib._sel_promisedItemResourceValuesForKeys_error_1, keys?._id ?? ffi.nullptr, @@ -34941,7 +34994,7 @@ class NSURL extends NSObject { bool checkPromisedItemIsReachableAndReturnError_( ffi.Pointer> error) { - return _lib._objc_msgSend_225( + return _lib._objc_msgSend_236( _id, _lib._sel_checkPromisedItemIsReachableAndReturnError_1, error); } @@ -35015,6 +35068,12 @@ class NSURL extends NSObject { : NSURL._(_ret, _lib, retain: true, release: true); } + bool checkResourceIsReachableAndReturnError_( + ffi.Pointer> error) { + return _lib._objc_msgSend_236( + _id, _lib._sel_checkResourceIsReachableAndReturnError_1, error); + } + NSURL? get URLByStandardizingPath { final _ret = _lib._objc_msgSend_40(_id, _lib._sel_URLByStandardizingPath1); return _ret.address == 0 @@ -37929,7 +37988,7 @@ class NSPredicate extends NSObject { } static NSPredicate predicateWithFormat_arguments_(SentryCocoa _lib, - NSString? predicateFormat, ffi.Pointer<__va_list_tag> argList) { + NSString? predicateFormat, ffi.Pointer argList) { final _ret = _lib._objc_msgSend_135( _lib._class_NSPredicate1, _lib._sel_predicateWithFormat_arguments_1, @@ -38085,18 +38144,6 @@ class NSPredicate extends NSObject { } } -class __va_list_tag extends ffi.Struct { - @ffi.UnsignedInt() - external int gp_offset; - - @ffi.UnsignedInt() - external int fp_offset; - - external ffi.Pointer overflow_arg_area; - - external ffi.Pointer reg_save_area; -} - bool _ObjCBlock_bool_ObjCObject_NSDictionary_fnPtrTrampoline( ffi.Pointer<_ObjCBlock> block, ffi.Pointer arg0, @@ -40105,6 +40152,13 @@ class NSLocale extends NSObject { return NSString._(_ret, _lib, retain: true, release: true); } + NSString? get languageIdentifier { + final _ret = _lib._objc_msgSend_20(_id, _lib._sel_languageIdentifier1); + return _ret.address == 0 + ? null + : NSString._(_ret, _lib, retain: true, release: true); + } + NSString? get countryCode { final _ret = _lib._objc_msgSend_20(_id, _lib._sel_countryCode1); return _ret.address == 0 @@ -40120,6 +40174,13 @@ class NSLocale extends NSObject { return NSString._(_ret, _lib, retain: true, release: true); } + NSString? get regionCode { + final _ret = _lib._objc_msgSend_20(_id, _lib._sel_regionCode1); + return _ret.address == 0 + ? null + : NSString._(_ret, _lib, retain: true, release: true); + } + NSString? get scriptCode { final _ret = _lib._objc_msgSend_20(_id, _lib._sel_scriptCode1); return _ret.address == 0 @@ -41133,6 +41194,8 @@ abstract class NSDataWritingOptions { static const int NSDataWritingFileProtectionCompleteUntilFirstUserAuthentication = 1073741824; + static const int NSDataWritingFileProtectionCompleteWhenUserInactive = + 1342177280; static const int NSDataWritingFileProtectionMask = 4026531840; static const int NSAtomicWrite = 1; } @@ -51366,7 +51429,7 @@ class NSMutableString extends NSString { @override NSMutableString initWithFormat_arguments_( - NSString? format, ffi.Pointer<__va_list_tag> argList) { + NSString? format, ffi.Pointer argList) { final _ret = _lib._objc_msgSend_348( _id, _lib._sel_initWithFormat_arguments_1, @@ -51384,7 +51447,7 @@ class NSMutableString extends NSString { @override NSMutableString initWithFormat_locale_arguments_( - NSString? format, NSObject locale, ffi.Pointer<__va_list_tag> argList) { + NSString? format, NSObject locale, ffi.Pointer argList) { final _ret = _lib._objc_msgSend_349( _id, _lib._sel_initWithFormat_locale_arguments_1, @@ -51429,7 +51492,7 @@ class NSMutableString extends NSString { initWithValidatedFormat_validFormatSpecifiers_arguments_error_( NSString? format, NSString? validFormatSpecifiers, - ffi.Pointer<__va_list_tag> argList, + ffi.Pointer argList, ffi.Pointer> error) { final _ret = _lib._objc_msgSend_352( _id, @@ -51447,7 +51510,7 @@ class NSMutableString extends NSString { NSString? format, NSString? validFormatSpecifiers, NSObject locale, - ffi.Pointer<__va_list_tag> argList, + ffi.Pointer argList, ffi.Pointer> error) { final _ret = _lib._objc_msgSend_353( _id, @@ -52095,12 +52158,12 @@ class NSBundle extends NSObject { } bool preflightAndReturnError_(ffi.Pointer> error) { - return _lib._objc_msgSend_225( + return _lib._objc_msgSend_236( _id, _lib._sel_preflightAndReturnError_1, error); } bool loadAndReturnError_(ffi.Pointer> error) { - return _lib._objc_msgSend_225(_id, _lib._sel_loadAndReturnError_1, error); + return _lib._objc_msgSend_236(_id, _lib._sel_loadAndReturnError_1, error); } NSURL? get bundleURL { @@ -52367,7 +52430,7 @@ class NSBundle extends NSObject { NSAttributedString localizedAttributedStringForKey_value_table_( NSString? key, NSString? value, NSString? tableName) { - final _ret = _lib._objc_msgSend_676( + final _ret = _lib._objc_msgSend_680( _id, _lib._sel_localizedAttributedStringForKey_value_table_1, key?._id ?? ffi.nullptr, @@ -52449,7 +52512,7 @@ class NSBundle extends NSObject { SentryCocoa _lib, NSArray? localizationsArray, NSArray? preferencesArray) { - final _ret = _lib._objc_msgSend_677( + final _ret = _lib._objc_msgSend_681( _lib._class_NSBundle1, _lib._sel_preferredLocalizationsFromArray_forPreferences_1, localizationsArray?._id ?? ffi.nullptr, @@ -52465,7 +52528,7 @@ class NSBundle extends NSObject { } void setPreservationPriority_forTags_(double priority, NSSet? tags) { - _lib._objc_msgSend_678(_id, _lib._sel_setPreservationPriority_forTags_1, + _lib._objc_msgSend_682(_id, _lib._sel_setPreservationPriority_forTags_1, priority, tags?._id ?? ffi.nullptr); } @@ -52757,7 +52820,7 @@ class NSAttributedString extends NSObject { NSAttributedString? format, int options, NSLocale? locale, - ffi.Pointer<__va_list_tag> arguments) { + ffi.Pointer arguments) { final _ret = _lib._objc_msgSend_673( _id, _lib._sel_initWithFormat_options_locale_arguments_1, @@ -52787,8 +52850,62 @@ class NSAttributedString extends NSObject { return NSAttributedString._(_ret, _lib, retain: true, release: true); } - NSAttributedString attributedStringByInflectingString() { + NSAttributedString initWithFormat_options_locale_context_( + NSAttributedString? format, + int options, + NSLocale? locale, + NSDictionary? context) { final _ret = _lib._objc_msgSend_675( + _id, + _lib._sel_initWithFormat_options_locale_context_1, + format?._id ?? ffi.nullptr, + options, + locale?._id ?? ffi.nullptr, + context?._id ?? ffi.nullptr); + return NSAttributedString._(_ret, _lib, retain: true, release: true); + } + + NSAttributedString initWithFormat_options_locale_context_arguments_( + NSAttributedString? format, + int options, + NSLocale? locale, + NSDictionary? context, + ffi.Pointer arguments) { + final _ret = _lib._objc_msgSend_676( + _id, + _lib._sel_initWithFormat_options_locale_context_arguments_1, + format?._id ?? ffi.nullptr, + options, + locale?._id ?? ffi.nullptr, + context?._id ?? ffi.nullptr, + arguments); + return NSAttributedString._(_ret, _lib, retain: true, release: true); + } + + static NSAttributedString localizedAttributedStringWithFormat_context_( + SentryCocoa _lib, NSAttributedString? format, NSDictionary? context) { + final _ret = _lib._objc_msgSend_677( + _lib._class_NSAttributedString1, + _lib._sel_localizedAttributedStringWithFormat_context_1, + format?._id ?? ffi.nullptr, + context?._id ?? ffi.nullptr); + return NSAttributedString._(_ret, _lib, retain: true, release: true); + } + + static NSAttributedString + localizedAttributedStringWithFormat_options_context_(SentryCocoa _lib, + NSAttributedString? format, int options, NSDictionary? context) { + final _ret = _lib._objc_msgSend_678( + _lib._class_NSAttributedString1, + _lib._sel_localizedAttributedStringWithFormat_options_context_1, + format?._id ?? ffi.nullptr, + options, + context?._id ?? ffi.nullptr); + return NSAttributedString._(_ret, _lib, retain: true, release: true); + } + + NSAttributedString attributedStringByInflectingString() { + final _ret = _lib._objc_msgSend_679( _id, _lib._sel_attributedStringByInflectingString1); return NSAttributedString._(_ret, _lib, retain: true, release: true); } @@ -53327,12 +53444,12 @@ class NSMutableAttributedString extends NSAttributedString { } void setAttributes_range_(NSDictionary? attrs, _NSRange range) { - _lib._objc_msgSend_679( + _lib._objc_msgSend_683( _id, _lib._sel_setAttributes_range_1, attrs?._id ?? ffi.nullptr, range); } NSMutableString? get mutableString { - final _ret = _lib._objc_msgSend_680(_id, _lib._sel_mutableString1); + final _ret = _lib._objc_msgSend_684(_id, _lib._sel_mutableString1); return _ret.address == 0 ? null : NSMutableString._(_ret, _lib, retain: true, release: true); @@ -53340,23 +53457,23 @@ class NSMutableAttributedString extends NSAttributedString { void addAttribute_value_range_( NSString name, NSObject value, _NSRange range) { - _lib._objc_msgSend_681( + _lib._objc_msgSend_685( _id, _lib._sel_addAttribute_value_range_1, name._id, value._id, range); } void addAttributes_range_(NSDictionary? attrs, _NSRange range) { - _lib._objc_msgSend_679( + _lib._objc_msgSend_683( _id, _lib._sel_addAttributes_range_1, attrs?._id ?? ffi.nullptr, range); } void removeAttribute_range_(NSString name, _NSRange range) { - _lib._objc_msgSend_682( + _lib._objc_msgSend_686( _id, _lib._sel_removeAttribute_range_1, name._id, range); } void replaceCharactersInRange_withAttributedString_( _NSRange range, NSAttributedString? attrString) { - _lib._objc_msgSend_683( + _lib._objc_msgSend_687( _id, _lib._sel_replaceCharactersInRange_withAttributedString_1, range, @@ -53365,12 +53482,12 @@ class NSMutableAttributedString extends NSAttributedString { void insertAttributedString_atIndex_( NSAttributedString? attrString, int loc) { - _lib._objc_msgSend_684(_id, _lib._sel_insertAttributedString_atIndex_1, + _lib._objc_msgSend_688(_id, _lib._sel_insertAttributedString_atIndex_1, attrString?._id ?? ffi.nullptr, loc); } void appendAttributedString_(NSAttributedString? attrString) { - _lib._objc_msgSend_685(_id, _lib._sel_appendAttributedString_1, + _lib._objc_msgSend_689(_id, _lib._sel_appendAttributedString_1, attrString?._id ?? ffi.nullptr); } @@ -53379,7 +53496,7 @@ class NSMutableAttributedString extends NSAttributedString { } void setAttributedString_(NSAttributedString? attrString) { - _lib._objc_msgSend_685( + _lib._objc_msgSend_689( _id, _lib._sel_setAttributedString_1, attrString?._id ?? ffi.nullptr); } @@ -53392,7 +53509,7 @@ class NSMutableAttributedString extends NSAttributedString { } void appendLocalizedFormat_(NSAttributedString? format) { - _lib._objc_msgSend_685( + _lib._objc_msgSend_689( _id, _lib._sel_appendLocalizedFormat_1, format?._id ?? ffi.nullptr); } @@ -53488,7 +53605,7 @@ class NSMutableAttributedString extends NSAttributedString { NSAttributedString? format, int options, NSLocale? locale, - ffi.Pointer<__va_list_tag> arguments) { + ffi.Pointer arguments) { final _ret = _lib._objc_msgSend_673( _id, _lib._sel_initWithFormat_options_locale_arguments_1, @@ -53518,6 +53635,62 @@ class NSMutableAttributedString extends NSAttributedString { return NSMutableAttributedString._(_ret, _lib, retain: true, release: true); } + @override + NSMutableAttributedString initWithFormat_options_locale_context_( + NSAttributedString? format, + int options, + NSLocale? locale, + NSDictionary? context) { + final _ret = _lib._objc_msgSend_675( + _id, + _lib._sel_initWithFormat_options_locale_context_1, + format?._id ?? ffi.nullptr, + options, + locale?._id ?? ffi.nullptr, + context?._id ?? ffi.nullptr); + return NSMutableAttributedString._(_ret, _lib, retain: true, release: true); + } + + @override + NSMutableAttributedString initWithFormat_options_locale_context_arguments_( + NSAttributedString? format, + int options, + NSLocale? locale, + NSDictionary? context, + ffi.Pointer arguments) { + final _ret = _lib._objc_msgSend_676( + _id, + _lib._sel_initWithFormat_options_locale_context_arguments_1, + format?._id ?? ffi.nullptr, + options, + locale?._id ?? ffi.nullptr, + context?._id ?? ffi.nullptr, + arguments); + return NSMutableAttributedString._(_ret, _lib, retain: true, release: true); + } + + static NSMutableAttributedString localizedAttributedStringWithFormat_context_( + SentryCocoa _lib, NSAttributedString? format, NSDictionary? context) { + final _ret = _lib._objc_msgSend_677( + _lib._class_NSMutableAttributedString1, + _lib._sel_localizedAttributedStringWithFormat_context_1, + format?._id ?? ffi.nullptr, + context?._id ?? ffi.nullptr); + return NSMutableAttributedString._(_ret, _lib, retain: true, release: true); + } + + static NSMutableAttributedString + localizedAttributedStringWithFormat_options_context_(SentryCocoa _lib, + NSAttributedString? format, int options, NSDictionary? context) { + final _ret = _lib._objc_msgSend_678( + _lib._class_NSMutableAttributedString1, + _lib._sel_localizedAttributedStringWithFormat_options_context_1, + format?._id ?? ffi.nullptr, + options, + context?._id ?? ffi.nullptr); + return NSMutableAttributedString._(_ret, _lib, retain: true, release: true); + } + @override NSMutableAttributedString init() { final _ret = _lib._objc_msgSend_2(_id, _lib._sel_init1); @@ -53639,11 +53812,11 @@ class NSDateFormatter extends NSFormatter { } int get formattingContext { - return _lib._objc_msgSend_690(_id, _lib._sel_formattingContext1); + return _lib._objc_msgSend_694(_id, _lib._sel_formattingContext1); } set formattingContext(int value) { - return _lib._objc_msgSend_691(_id, _lib._sel_setFormattingContext_1, value); + return _lib._objc_msgSend_695(_id, _lib._sel_setFormattingContext_1, value); } bool getObjectValue_forString_range_error_( @@ -53651,7 +53824,7 @@ class NSDateFormatter extends NSFormatter { NSString? string, ffi.Pointer<_NSRange> rangep, ffi.Pointer> error) { - return _lib._objc_msgSend_692( + return _lib._objc_msgSend_696( _id, _lib._sel_getObjectValue_forString_range_error_1, obj, @@ -53674,7 +53847,7 @@ class NSDateFormatter extends NSFormatter { static NSString localizedStringFromDate_dateStyle_timeStyle_( SentryCocoa _lib, NSDate? date, int dstyle, int tstyle) { - final _ret = _lib._objc_msgSend_693( + final _ret = _lib._objc_msgSend_697( _lib._class_NSDateFormatter1, _lib._sel_localizedStringFromDate_dateStyle_timeStyle_1, date?._id ?? ffi.nullptr, @@ -53685,7 +53858,7 @@ class NSDateFormatter extends NSFormatter { static NSString dateFormatFromTemplate_options_locale_( SentryCocoa _lib, NSString? tmplate, int opts, NSLocale? locale) { - final _ret = _lib._objc_msgSend_694( + final _ret = _lib._objc_msgSend_698( _lib._class_NSDateFormatter1, _lib._sel_dateFormatFromTemplate_options_locale_1, tmplate?._id ?? ffi.nullptr, @@ -53695,12 +53868,12 @@ class NSDateFormatter extends NSFormatter { } static int getDefaultFormatterBehavior(SentryCocoa _lib) { - return _lib._objc_msgSend_695( + return _lib._objc_msgSend_699( _lib._class_NSDateFormatter1, _lib._sel_defaultFormatterBehavior1); } static void setDefaultFormatterBehavior(SentryCocoa _lib, int value) { - return _lib._objc_msgSend_696(_lib._class_NSDateFormatter1, + return _lib._objc_msgSend_700(_lib._class_NSDateFormatter1, _lib._sel_setDefaultFormatterBehavior_1, value); } @@ -53722,19 +53895,19 @@ class NSDateFormatter extends NSFormatter { } int get dateStyle { - return _lib._objc_msgSend_697(_id, _lib._sel_dateStyle1); + return _lib._objc_msgSend_701(_id, _lib._sel_dateStyle1); } set dateStyle(int value) { - return _lib._objc_msgSend_698(_id, _lib._sel_setDateStyle_1, value); + return _lib._objc_msgSend_702(_id, _lib._sel_setDateStyle_1, value); } int get timeStyle { - return _lib._objc_msgSend_697(_id, _lib._sel_timeStyle1); + return _lib._objc_msgSend_701(_id, _lib._sel_timeStyle1); } set timeStyle(int value) { - return _lib._objc_msgSend_698(_id, _lib._sel_setTimeStyle_1, value); + return _lib._objc_msgSend_702(_id, _lib._sel_setTimeStyle_1, value); } NSLocale? get locale { @@ -53745,7 +53918,7 @@ class NSDateFormatter extends NSFormatter { } set locale(NSLocale? value) { - return _lib._objc_msgSend_699( + return _lib._objc_msgSend_703( _id, _lib._sel_setLocale_1, value?._id ?? ffi.nullptr); } @@ -53759,11 +53932,11 @@ class NSDateFormatter extends NSFormatter { } int get formatterBehavior { - return _lib._objc_msgSend_695(_id, _lib._sel_formatterBehavior1); + return _lib._objc_msgSend_699(_id, _lib._sel_formatterBehavior1); } set formatterBehavior(int value) { - return _lib._objc_msgSend_696(_id, _lib._sel_setFormatterBehavior_1, value); + return _lib._objc_msgSend_700(_id, _lib._sel_setFormatterBehavior_1, value); } NSTimeZone? get timeZone { @@ -53779,14 +53952,14 @@ class NSDateFormatter extends NSFormatter { } NSCalendar? get calendar { - final _ret = _lib._objc_msgSend_700(_id, _lib._sel_calendar1); + final _ret = _lib._objc_msgSend_704(_id, _lib._sel_calendar1); return _ret.address == 0 ? null : NSCalendar._(_ret, _lib, retain: true, release: true); } set calendar(NSCalendar? value) { - return _lib._objc_msgSend_706( + return _lib._objc_msgSend_710( _id, _lib._sel_setCalendar_1, value?._id ?? ffi.nullptr); } @@ -53830,7 +54003,7 @@ class NSDateFormatter extends NSFormatter { } set eraSymbols(NSArray? value) { - return _lib._objc_msgSend_731( + return _lib._objc_msgSend_735( _id, _lib._sel_setEraSymbols_1, value?._id ?? ffi.nullptr); } @@ -53842,7 +54015,7 @@ class NSDateFormatter extends NSFormatter { } set monthSymbols(NSArray? value) { - return _lib._objc_msgSend_731( + return _lib._objc_msgSend_735( _id, _lib._sel_setMonthSymbols_1, value?._id ?? ffi.nullptr); } @@ -53854,7 +54027,7 @@ class NSDateFormatter extends NSFormatter { } set shortMonthSymbols(NSArray? value) { - return _lib._objc_msgSend_731( + return _lib._objc_msgSend_735( _id, _lib._sel_setShortMonthSymbols_1, value?._id ?? ffi.nullptr); } @@ -53866,7 +54039,7 @@ class NSDateFormatter extends NSFormatter { } set weekdaySymbols(NSArray? value) { - return _lib._objc_msgSend_731( + return _lib._objc_msgSend_735( _id, _lib._sel_setWeekdaySymbols_1, value?._id ?? ffi.nullptr); } @@ -53878,7 +54051,7 @@ class NSDateFormatter extends NSFormatter { } set shortWeekdaySymbols(NSArray? value) { - return _lib._objc_msgSend_731( + return _lib._objc_msgSend_735( _id, _lib._sel_setShortWeekdaySymbols_1, value?._id ?? ffi.nullptr); } @@ -53914,7 +54087,7 @@ class NSDateFormatter extends NSFormatter { } set longEraSymbols(NSArray? value) { - return _lib._objc_msgSend_731( + return _lib._objc_msgSend_735( _id, _lib._sel_setLongEraSymbols_1, value?._id ?? ffi.nullptr); } @@ -53926,7 +54099,7 @@ class NSDateFormatter extends NSFormatter { } set veryShortMonthSymbols(NSArray? value) { - return _lib._objc_msgSend_731( + return _lib._objc_msgSend_735( _id, _lib._sel_setVeryShortMonthSymbols_1, value?._id ?? ffi.nullptr); } @@ -53938,7 +54111,7 @@ class NSDateFormatter extends NSFormatter { } set standaloneMonthSymbols(NSArray? value) { - return _lib._objc_msgSend_731( + return _lib._objc_msgSend_735( _id, _lib._sel_setStandaloneMonthSymbols_1, value?._id ?? ffi.nullptr); } @@ -53951,7 +54124,7 @@ class NSDateFormatter extends NSFormatter { } set shortStandaloneMonthSymbols(NSArray? value) { - return _lib._objc_msgSend_731(_id, + return _lib._objc_msgSend_735(_id, _lib._sel_setShortStandaloneMonthSymbols_1, value?._id ?? ffi.nullptr); } @@ -53964,7 +54137,7 @@ class NSDateFormatter extends NSFormatter { } set veryShortStandaloneMonthSymbols(NSArray? value) { - return _lib._objc_msgSend_731( + return _lib._objc_msgSend_735( _id, _lib._sel_setVeryShortStandaloneMonthSymbols_1, value?._id ?? ffi.nullptr); @@ -53978,7 +54151,7 @@ class NSDateFormatter extends NSFormatter { } set veryShortWeekdaySymbols(NSArray? value) { - return _lib._objc_msgSend_731( + return _lib._objc_msgSend_735( _id, _lib._sel_setVeryShortWeekdaySymbols_1, value?._id ?? ffi.nullptr); } @@ -53991,7 +54164,7 @@ class NSDateFormatter extends NSFormatter { } set standaloneWeekdaySymbols(NSArray? value) { - return _lib._objc_msgSend_731(_id, _lib._sel_setStandaloneWeekdaySymbols_1, + return _lib._objc_msgSend_735(_id, _lib._sel_setStandaloneWeekdaySymbols_1, value?._id ?? ffi.nullptr); } @@ -54004,7 +54177,7 @@ class NSDateFormatter extends NSFormatter { } set shortStandaloneWeekdaySymbols(NSArray? value) { - return _lib._objc_msgSend_731( + return _lib._objc_msgSend_735( _id, _lib._sel_setShortStandaloneWeekdaySymbols_1, value?._id ?? ffi.nullptr); @@ -54019,7 +54192,7 @@ class NSDateFormatter extends NSFormatter { } set veryShortStandaloneWeekdaySymbols(NSArray? value) { - return _lib._objc_msgSend_731( + return _lib._objc_msgSend_735( _id, _lib._sel_setVeryShortStandaloneWeekdaySymbols_1, value?._id ?? ffi.nullptr); @@ -54033,7 +54206,7 @@ class NSDateFormatter extends NSFormatter { } set quarterSymbols(NSArray? value) { - return _lib._objc_msgSend_731( + return _lib._objc_msgSend_735( _id, _lib._sel_setQuarterSymbols_1, value?._id ?? ffi.nullptr); } @@ -54045,7 +54218,7 @@ class NSDateFormatter extends NSFormatter { } set shortQuarterSymbols(NSArray? value) { - return _lib._objc_msgSend_731( + return _lib._objc_msgSend_735( _id, _lib._sel_setShortQuarterSymbols_1, value?._id ?? ffi.nullptr); } @@ -54058,7 +54231,7 @@ class NSDateFormatter extends NSFormatter { } set standaloneQuarterSymbols(NSArray? value) { - return _lib._objc_msgSend_731(_id, _lib._sel_setStandaloneQuarterSymbols_1, + return _lib._objc_msgSend_735(_id, _lib._sel_setStandaloneQuarterSymbols_1, value?._id ?? ffi.nullptr); } @@ -54071,7 +54244,7 @@ class NSDateFormatter extends NSFormatter { } set shortStandaloneQuarterSymbols(NSArray? value) { - return _lib._objc_msgSend_731( + return _lib._objc_msgSend_735( _id, _lib._sel_setShortStandaloneQuarterSymbols_1, value?._id ?? ffi.nullptr); @@ -54236,7 +54409,7 @@ class NSFormatter extends NSObject { NSAttributedString attributedStringForObjectValue_withDefaultAttributes_( NSObject obj, NSDictionary? attrs) { - final _ret = _lib._objc_msgSend_686( + final _ret = _lib._objc_msgSend_690( _id, _lib._sel_attributedStringForObjectValue_withDefaultAttributes_1, obj._id, @@ -54254,7 +54427,7 @@ class NSFormatter extends NSObject { ffi.Pointer> obj, NSString? string, ffi.Pointer> error) { - return _lib._objc_msgSend_687( + return _lib._objc_msgSend_691( _id, _lib._sel_getObjectValue_forString_errorDescription_1, obj, @@ -54266,7 +54439,7 @@ class NSFormatter extends NSObject { NSString? partialString, ffi.Pointer> newString, ffi.Pointer> error) { - return _lib._objc_msgSend_688( + return _lib._objc_msgSend_692( _id, _lib._sel_isPartialStringValid_newEditingString_errorDescription_1, partialString?._id ?? ffi.nullptr, @@ -54281,7 +54454,7 @@ class NSFormatter extends NSObject { NSString? origString, _NSRange origSelRange, ffi.Pointer> error) { - return _lib._objc_msgSend_689( + return _lib._objc_msgSend_693( _id, _lib._sel_isPartialStringValid_proposedSelectedRange_originalString_originalSelectedRange_errorDescription_1, partialStringPtr, @@ -54430,7 +54603,7 @@ class NSCalendar extends NSObject { } static NSCalendar? getCurrentCalendar(SentryCocoa _lib) { - final _ret = _lib._objc_msgSend_700( + final _ret = _lib._objc_msgSend_704( _lib._class_NSCalendar1, _lib._sel_currentCalendar1); return _ret.address == 0 ? null @@ -54438,7 +54611,7 @@ class NSCalendar extends NSObject { } static NSCalendar? getAutoupdatingCurrentCalendar(SentryCocoa _lib) { - final _ret = _lib._objc_msgSend_700( + final _ret = _lib._objc_msgSend_704( _lib._class_NSCalendar1, _lib._sel_autoupdatingCurrentCalendar1); return _ret.address == 0 ? null @@ -54447,7 +54620,7 @@ class NSCalendar extends NSObject { static NSCalendar calendarWithIdentifier_( SentryCocoa _lib, NSString calendarIdentifierConstant) { - final _ret = _lib._objc_msgSend_701(_lib._class_NSCalendar1, + final _ret = _lib._objc_msgSend_705(_lib._class_NSCalendar1, _lib._sel_calendarWithIdentifier_1, calendarIdentifierConstant._id); return NSCalendar._(_ret, _lib, retain: true, release: true); } @@ -54477,7 +54650,7 @@ class NSCalendar extends NSObject { } set locale(NSLocale? value) { - return _lib._objc_msgSend_699( + return _lib._objc_msgSend_703( _id, _lib._sel_setLocale_1, value?._id ?? ffi.nullptr); } @@ -54658,21 +54831,21 @@ class NSCalendar extends NSObject { } void minimumRangeOfUnit_(ffi.Pointer<_NSRange> stret, int unit) { - _lib._objc_msgSend_702(stret, _id, _lib._sel_minimumRangeOfUnit_1, unit); + _lib._objc_msgSend_706(stret, _id, _lib._sel_minimumRangeOfUnit_1, unit); } void maximumRangeOfUnit_(ffi.Pointer<_NSRange> stret, int unit) { - _lib._objc_msgSend_702(stret, _id, _lib._sel_maximumRangeOfUnit_1, unit); + _lib._objc_msgSend_706(stret, _id, _lib._sel_maximumRangeOfUnit_1, unit); } void rangeOfUnit_inUnit_forDate_( ffi.Pointer<_NSRange> stret, int smaller, int larger, NSDate? date) { - _lib._objc_msgSend_703(stret, _id, _lib._sel_rangeOfUnit_inUnit_forDate_1, + _lib._objc_msgSend_707(stret, _id, _lib._sel_rangeOfUnit_inUnit_forDate_1, smaller, larger, date?._id ?? ffi.nullptr); } int ordinalityOfUnit_inUnit_forDate_(int smaller, int larger, NSDate? date) { - return _lib._objc_msgSend_704( + return _lib._objc_msgSend_708( _id, _lib._sel_ordinalityOfUnit_inUnit_forDate_1, smaller, @@ -54685,7 +54858,7 @@ class NSCalendar extends NSObject { ffi.Pointer> datep, ffi.Pointer tip, NSDate? date) { - return _lib._objc_msgSend_705( + return _lib._objc_msgSend_709( _id, _lib._sel_rangeOfUnit_startDate_interval_forDate_1, unit, @@ -54695,20 +54868,20 @@ class NSCalendar extends NSObject { } NSDate dateFromComponents_(NSDateComponents? comps) { - final _ret = _lib._objc_msgSend_710( + final _ret = _lib._objc_msgSend_714( _id, _lib._sel_dateFromComponents_1, comps?._id ?? ffi.nullptr); return NSDate._(_ret, _lib, retain: true, release: true); } NSDateComponents components_fromDate_(int unitFlags, NSDate? date) { - final _ret = _lib._objc_msgSend_711(_id, _lib._sel_components_fromDate_1, + final _ret = _lib._objc_msgSend_715(_id, _lib._sel_components_fromDate_1, unitFlags, date?._id ?? ffi.nullptr); return NSDateComponents._(_ret, _lib, retain: true, release: true); } NSDate dateByAddingComponents_toDate_options_( NSDateComponents? comps, NSDate? date, int opts) { - final _ret = _lib._objc_msgSend_712( + final _ret = _lib._objc_msgSend_716( _id, _lib._sel_dateByAddingComponents_toDate_options_1, comps?._id ?? ffi.nullptr, @@ -54719,7 +54892,7 @@ class NSCalendar extends NSObject { NSDateComponents components_fromDate_toDate_options_( int unitFlags, NSDate? startingDate, NSDate? resultDate, int opts) { - final _ret = _lib._objc_msgSend_713( + final _ret = _lib._objc_msgSend_717( _id, _lib._sel_components_fromDate_toDate_options_1, unitFlags, @@ -54735,7 +54908,7 @@ class NSCalendar extends NSObject { ffi.Pointer monthValuePointer, ffi.Pointer dayValuePointer, NSDate? date) { - _lib._objc_msgSend_714( + _lib._objc_msgSend_718( _id, _lib._sel_getEra_year_month_day_fromDate_1, eraValuePointer, @@ -54751,7 +54924,7 @@ class NSCalendar extends NSObject { ffi.Pointer weekValuePointer, ffi.Pointer weekdayValuePointer, NSDate? date) { - _lib._objc_msgSend_714( + _lib._objc_msgSend_718( _id, _lib._sel_getEra_yearForWeekOfYear_weekOfYear_weekday_fromDate_1, eraValuePointer, @@ -54767,7 +54940,7 @@ class NSCalendar extends NSObject { ffi.Pointer secondValuePointer, ffi.Pointer nanosecondValuePointer, NSDate? date) { - _lib._objc_msgSend_714( + _lib._objc_msgSend_718( _id, _lib._sel_getHour_minute_second_nanosecond_fromDate_1, hourValuePointer, @@ -54778,7 +54951,7 @@ class NSCalendar extends NSObject { } int component_fromDate_(int unit, NSDate? date) { - return _lib._objc_msgSend_715( + return _lib._objc_msgSend_719( _id, _lib._sel_component_fromDate_1, unit, date?._id ?? ffi.nullptr); } @@ -54791,7 +54964,7 @@ class NSCalendar extends NSObject { int minuteValue, int secondValue, int nanosecondValue) { - final _ret = _lib._objc_msgSend_716( + final _ret = _lib._objc_msgSend_720( _id, _lib._sel_dateWithEra_year_month_day_hour_minute_second_nanosecond_1, eraValue, @@ -54815,7 +54988,7 @@ class NSCalendar extends NSObject { int minuteValue, int secondValue, int nanosecondValue) { - final _ret = _lib._objc_msgSend_716( + final _ret = _lib._objc_msgSend_720( _id, _lib._sel_dateWithEra_yearForWeekOfYear_weekOfYear_weekday_hour_minute_second_nanosecond_1, eraValue, @@ -54837,7 +55010,7 @@ class NSCalendar extends NSObject { NSDateComponents componentsInTimeZone_fromDate_( NSTimeZone? timezone, NSDate? date) { - final _ret = _lib._objc_msgSend_717( + final _ret = _lib._objc_msgSend_721( _id, _lib._sel_componentsInTimeZone_fromDate_1, timezone?._id ?? ffi.nullptr, @@ -54847,7 +55020,7 @@ class NSCalendar extends NSObject { int compareDate_toDate_toUnitGranularity_( NSDate? date1, NSDate? date2, int unit) { - return _lib._objc_msgSend_718( + return _lib._objc_msgSend_722( _id, _lib._sel_compareDate_toDate_toUnitGranularity_1, date1?._id ?? ffi.nullptr, @@ -54857,7 +55030,7 @@ class NSCalendar extends NSObject { bool isDate_equalToDate_toUnitGranularity_( NSDate? date1, NSDate? date2, int unit) { - return _lib._objc_msgSend_719( + return _lib._objc_msgSend_723( _id, _lib._sel_isDate_equalToDate_toUnitGranularity_1, date1?._id ?? ffi.nullptr, @@ -54866,7 +55039,7 @@ class NSCalendar extends NSObject { } bool isDate_inSameDayAsDate_(NSDate? date1, NSDate? date2) { - return _lib._objc_msgSend_720(_id, _lib._sel_isDate_inSameDayAsDate_1, + return _lib._objc_msgSend_724(_id, _lib._sel_isDate_inSameDayAsDate_1, date1?._id ?? ffi.nullptr, date2?._id ?? ffi.nullptr); } @@ -54894,7 +55067,7 @@ class NSCalendar extends NSObject { ffi.Pointer> datep, ffi.Pointer tip, NSDate? date) { - return _lib._objc_msgSend_721( + return _lib._objc_msgSend_725( _id, _lib._sel_rangeOfWeekendStartDate_interval_containingDate_1, datep, @@ -54907,7 +55080,7 @@ class NSCalendar extends NSObject { ffi.Pointer tip, int options, NSDate? date) { - return _lib._objc_msgSend_722( + return _lib._objc_msgSend_726( _id, _lib._sel_nextWeekendStartDate_interval_options_afterDate_1, datep, @@ -54921,7 +55094,7 @@ class NSCalendar extends NSObject { NSDateComponents? startingDateComp, NSDateComponents? resultDateComp, int options) { - final _ret = _lib._objc_msgSend_723( + final _ret = _lib._objc_msgSend_727( _id, _lib._sel_components_fromDateComponents_toDateComponents_options_1, unitFlags, @@ -54933,7 +55106,7 @@ class NSCalendar extends NSObject { NSDate dateByAddingUnit_value_toDate_options_( int unit, int value, NSDate? date, int options) { - final _ret = _lib._objc_msgSend_724( + final _ret = _lib._objc_msgSend_728( _id, _lib._sel_dateByAddingUnit_value_toDate_options_1, unit, @@ -54948,7 +55121,7 @@ class NSCalendar extends NSObject { NSDateComponents? comps, int opts, ObjCBlock_ffiVoid_NSDate_bool_bool block) { - _lib._objc_msgSend_725( + _lib._objc_msgSend_729( _id, _lib._sel_enumerateDatesStartingAfterDate_matchingComponents_options_usingBlock_1, start?._id ?? ffi.nullptr, @@ -54959,7 +55132,7 @@ class NSCalendar extends NSObject { NSDate nextDateAfterDate_matchingComponents_options_( NSDate? date, NSDateComponents? comps, int options) { - final _ret = _lib._objc_msgSend_726( + final _ret = _lib._objc_msgSend_730( _id, _lib._sel_nextDateAfterDate_matchingComponents_options_1, date?._id ?? ffi.nullptr, @@ -54970,7 +55143,7 @@ class NSCalendar extends NSObject { NSDate nextDateAfterDate_matchingUnit_value_options_( NSDate? date, int unit, int value, int options) { - final _ret = _lib._objc_msgSend_727( + final _ret = _lib._objc_msgSend_731( _id, _lib._sel_nextDateAfterDate_matchingUnit_value_options_1, date?._id ?? ffi.nullptr, @@ -54982,7 +55155,7 @@ class NSCalendar extends NSObject { NSDate nextDateAfterDate_matchingHour_minute_second_options_(NSDate? date, int hourValue, int minuteValue, int secondValue, int options) { - final _ret = _lib._objc_msgSend_728( + final _ret = _lib._objc_msgSend_732( _id, _lib._sel_nextDateAfterDate_matchingHour_minute_second_options_1, date?._id ?? ffi.nullptr, @@ -54995,7 +55168,7 @@ class NSCalendar extends NSObject { NSDate dateBySettingUnit_value_ofDate_options_( int unit, int v, NSDate? date, int opts) { - final _ret = _lib._objc_msgSend_724( + final _ret = _lib._objc_msgSend_728( _id, _lib._sel_dateBySettingUnit_value_ofDate_options_1, unit, @@ -55007,7 +55180,7 @@ class NSCalendar extends NSObject { NSDate dateBySettingHour_minute_second_ofDate_options_( int h, int m, int s, NSDate? date, int opts) { - final _ret = _lib._objc_msgSend_729( + final _ret = _lib._objc_msgSend_733( _id, _lib._sel_dateBySettingHour_minute_second_ofDate_options_1, h, @@ -55019,7 +55192,7 @@ class NSCalendar extends NSObject { } bool date_matchesComponents_(NSDate? date, NSDateComponents? components) { - return _lib._objc_msgSend_730(_id, _lib._sel_date_matchesComponents_1, + return _lib._objc_msgSend_734(_id, _lib._sel_date_matchesComponents_1, date?._id ?? ffi.nullptr, components?._id ?? ffi.nullptr); } @@ -55169,14 +55342,14 @@ class NSDateComponents extends NSObject { } NSCalendar? get calendar { - final _ret = _lib._objc_msgSend_700(_id, _lib._sel_calendar1); + final _ret = _lib._objc_msgSend_704(_id, _lib._sel_calendar1); return _ret.address == 0 ? null : NSCalendar._(_ret, _lib, retain: true, release: true); } set calendar(NSCalendar? value) { - return _lib._objc_msgSend_706( + return _lib._objc_msgSend_710( _id, _lib._sel_setCalendar_1, value?._id ?? ffi.nullptr); } @@ -55328,11 +55501,11 @@ class NSDateComponents extends NSObject { } void setValue_forComponent_(int value, int unit) { - _lib._objc_msgSend_707(_id, _lib._sel_setValue_forComponent_1, value, unit); + _lib._objc_msgSend_711(_id, _lib._sel_setValue_forComponent_1, value, unit); } int valueForComponent_(int unit) { - return _lib._objc_msgSend_708(_id, _lib._sel_valueForComponent_1, unit); + return _lib._objc_msgSend_712(_id, _lib._sel_valueForComponent_1, unit); } bool get validDate { @@ -55340,7 +55513,7 @@ class NSDateComponents extends NSObject { } bool isValidDateInCalendar_(NSCalendar? calendar) { - return _lib._objc_msgSend_709( + return _lib._objc_msgSend_713( _id, _lib._sel_isValidDateInCalendar_1, calendar?._id ?? ffi.nullptr); } @@ -55573,11 +55746,11 @@ class NSNumberFormatter extends NSFormatter { } int get formattingContext { - return _lib._objc_msgSend_690(_id, _lib._sel_formattingContext1); + return _lib._objc_msgSend_694(_id, _lib._sel_formattingContext1); } set formattingContext(int value) { - return _lib._objc_msgSend_691(_id, _lib._sel_setFormattingContext_1, value); + return _lib._objc_msgSend_695(_id, _lib._sel_setFormattingContext_1, value); } bool getObjectValue_forString_range_error_( @@ -55585,7 +55758,7 @@ class NSNumberFormatter extends NSFormatter { NSString? string, ffi.Pointer<_NSRange> rangep, ffi.Pointer> error) { - return _lib._objc_msgSend_692( + return _lib._objc_msgSend_696( _id, _lib._sel_getObjectValue_forString_range_error_1, obj, @@ -55595,20 +55768,20 @@ class NSNumberFormatter extends NSFormatter { } NSString stringFromNumber_(NSNumber? number) { - final _ret = _lib._objc_msgSend_732( + final _ret = _lib._objc_msgSend_736( _id, _lib._sel_stringFromNumber_1, number?._id ?? ffi.nullptr); return NSString._(_ret, _lib, retain: true, release: true); } NSNumber numberFromString_(NSString? string) { - final _ret = _lib._objc_msgSend_733( + final _ret = _lib._objc_msgSend_737( _id, _lib._sel_numberFromString_1, string?._id ?? ffi.nullptr); return NSNumber._(_ret, _lib, retain: true, release: true); } static NSString localizedStringFromNumber_numberStyle_( SentryCocoa _lib, NSNumber? num, int nstyle) { - final _ret = _lib._objc_msgSend_734( + final _ret = _lib._objc_msgSend_738( _lib._class_NSNumberFormatter1, _lib._sel_localizedStringFromNumber_numberStyle_1, num?._id ?? ffi.nullptr, @@ -55617,21 +55790,21 @@ class NSNumberFormatter extends NSFormatter { } static int defaultFormatterBehavior(SentryCocoa _lib) { - return _lib._objc_msgSend_735( + return _lib._objc_msgSend_739( _lib._class_NSNumberFormatter1, _lib._sel_defaultFormatterBehavior1); } static void setDefaultFormatterBehavior_(SentryCocoa _lib, int behavior) { - _lib._objc_msgSend_736(_lib._class_NSNumberFormatter1, + _lib._objc_msgSend_740(_lib._class_NSNumberFormatter1, _lib._sel_setDefaultFormatterBehavior_1, behavior); } int get numberStyle { - return _lib._objc_msgSend_737(_id, _lib._sel_numberStyle1); + return _lib._objc_msgSend_741(_id, _lib._sel_numberStyle1); } set numberStyle(int value) { - return _lib._objc_msgSend_738(_id, _lib._sel_setNumberStyle_1, value); + return _lib._objc_msgSend_742(_id, _lib._sel_setNumberStyle_1, value); } NSLocale? get locale { @@ -55642,7 +55815,7 @@ class NSNumberFormatter extends NSFormatter { } set locale(NSLocale? value) { - return _lib._objc_msgSend_699( + return _lib._objc_msgSend_703( _id, _lib._sel_setLocale_1, value?._id ?? ffi.nullptr); } @@ -55656,11 +55829,11 @@ class NSNumberFormatter extends NSFormatter { } int get formatterBehavior { - return _lib._objc_msgSend_735(_id, _lib._sel_formatterBehavior1); + return _lib._objc_msgSend_739(_id, _lib._sel_formatterBehavior1); } set formatterBehavior(int value) { - return _lib._objc_msgSend_739(_id, _lib._sel_setFormatterBehavior_1, value); + return _lib._objc_msgSend_743(_id, _lib._sel_setFormatterBehavior_1, value); } NSString? get negativeFormat { @@ -56102,19 +56275,19 @@ class NSNumberFormatter extends NSFormatter { } int get paddingPosition { - return _lib._objc_msgSend_740(_id, _lib._sel_paddingPosition1); + return _lib._objc_msgSend_744(_id, _lib._sel_paddingPosition1); } set paddingPosition(int value) { - return _lib._objc_msgSend_741(_id, _lib._sel_setPaddingPosition_1, value); + return _lib._objc_msgSend_745(_id, _lib._sel_setPaddingPosition_1, value); } int get roundingMode { - return _lib._objc_msgSend_742(_id, _lib._sel_roundingMode1); + return _lib._objc_msgSend_746(_id, _lib._sel_roundingMode1); } set roundingMode(int value) { - return _lib._objc_msgSend_743(_id, _lib._sel_setRoundingMode_1, value); + return _lib._objc_msgSend_747(_id, _lib._sel_setRoundingMode_1, value); } NSNumber? get roundingIncrement { @@ -56290,53 +56463,53 @@ class NSNumberFormatter extends NSFormatter { NSAttributedString? get attributedStringForZero { final _ret = - _lib._objc_msgSend_675(_id, _lib._sel_attributedStringForZero1); + _lib._objc_msgSend_679(_id, _lib._sel_attributedStringForZero1); return _ret.address == 0 ? null : NSAttributedString._(_ret, _lib, retain: true, release: true); } set attributedStringForZero(NSAttributedString? value) { - return _lib._objc_msgSend_744( + return _lib._objc_msgSend_748( _id, _lib._sel_setAttributedStringForZero_1, value?._id ?? ffi.nullptr); } NSAttributedString? get attributedStringForNil { - final _ret = _lib._objc_msgSend_675(_id, _lib._sel_attributedStringForNil1); + final _ret = _lib._objc_msgSend_679(_id, _lib._sel_attributedStringForNil1); return _ret.address == 0 ? null : NSAttributedString._(_ret, _lib, retain: true, release: true); } set attributedStringForNil(NSAttributedString? value) { - return _lib._objc_msgSend_744( + return _lib._objc_msgSend_748( _id, _lib._sel_setAttributedStringForNil_1, value?._id ?? ffi.nullptr); } NSAttributedString? get attributedStringForNotANumber { final _ret = - _lib._objc_msgSend_675(_id, _lib._sel_attributedStringForNotANumber1); + _lib._objc_msgSend_679(_id, _lib._sel_attributedStringForNotANumber1); return _ret.address == 0 ? null : NSAttributedString._(_ret, _lib, retain: true, release: true); } set attributedStringForNotANumber(NSAttributedString? value) { - return _lib._objc_msgSend_744( + return _lib._objc_msgSend_748( _id, _lib._sel_setAttributedStringForNotANumber_1, value?._id ?? ffi.nullptr); } NSDecimalNumberHandler? get roundingBehavior { - final _ret = _lib._objc_msgSend_745(_id, _lib._sel_roundingBehavior1); + final _ret = _lib._objc_msgSend_749(_id, _lib._sel_roundingBehavior1); return _ret.address == 0 ? null : NSDecimalNumberHandler._(_ret, _lib, retain: true, release: true); } set roundingBehavior(NSDecimalNumberHandler? value) { - return _lib._objc_msgSend_747( + return _lib._objc_msgSend_751( _id, _lib._sel_setRoundingBehavior_1, value?._id ?? ffi.nullptr); } @@ -56496,7 +56669,7 @@ class NSDecimalNumberHandler extends NSObject { static NSDecimalNumberHandler? getDefaultDecimalNumberHandler( SentryCocoa _lib) { - final _ret = _lib._objc_msgSend_745(_lib._class_NSDecimalNumberHandler1, + final _ret = _lib._objc_msgSend_749(_lib._class_NSDecimalNumberHandler1, _lib._sel_defaultDecimalNumberHandler1); return _ret.address == 0 ? null @@ -56511,7 +56684,7 @@ class NSDecimalNumberHandler extends NSObject { bool overflow, bool underflow, bool divideByZero) { - final _ret = _lib._objc_msgSend_746( + final _ret = _lib._objc_msgSend_750( _id, _lib._sel_initWithRoundingMode_scale_raiseOnExactness_raiseOnOverflow_raiseOnUnderflow_raiseOnDivideByZero_1, roundingMode, @@ -56532,7 +56705,7 @@ class NSDecimalNumberHandler extends NSObject { bool overflow, bool underflow, bool divideByZero) { - final _ret = _lib._objc_msgSend_746( + final _ret = _lib._objc_msgSend_750( _lib._class_NSDecimalNumberHandler1, _lib._sel_decimalNumberHandlerWithRoundingMode_scale_raiseOnExactness_raiseOnOverflow_raiseOnUnderflow_raiseOnDivideByZero_1, roundingMode, @@ -56690,7 +56863,7 @@ class NSScanner extends NSObject { } set charactersToBeSkipped(NSCharacterSet? value) { - return _lib._objc_msgSend_748( + return _lib._objc_msgSend_752( _id, _lib._sel_setCharactersToBeSkipped_1, value?._id ?? ffi.nullptr); } @@ -56718,55 +56891,55 @@ class NSScanner extends NSObject { } bool scanInt_(ffi.Pointer result) { - return _lib._objc_msgSend_749(_id, _lib._sel_scanInt_1, result); + return _lib._objc_msgSend_753(_id, _lib._sel_scanInt_1, result); } bool scanInteger_(ffi.Pointer result) { - return _lib._objc_msgSend_750(_id, _lib._sel_scanInteger_1, result); + return _lib._objc_msgSend_754(_id, _lib._sel_scanInteger_1, result); } bool scanLongLong_(ffi.Pointer result) { - return _lib._objc_msgSend_751(_id, _lib._sel_scanLongLong_1, result); + return _lib._objc_msgSend_755(_id, _lib._sel_scanLongLong_1, result); } bool scanUnsignedLongLong_(ffi.Pointer result) { - return _lib._objc_msgSend_752( + return _lib._objc_msgSend_756( _id, _lib._sel_scanUnsignedLongLong_1, result); } bool scanFloat_(ffi.Pointer result) { - return _lib._objc_msgSend_753(_id, _lib._sel_scanFloat_1, result); + return _lib._objc_msgSend_757(_id, _lib._sel_scanFloat_1, result); } bool scanDouble_(ffi.Pointer result) { - return _lib._objc_msgSend_754(_id, _lib._sel_scanDouble_1, result); + return _lib._objc_msgSend_758(_id, _lib._sel_scanDouble_1, result); } bool scanHexInt_(ffi.Pointer result) { - return _lib._objc_msgSend_755(_id, _lib._sel_scanHexInt_1, result); + return _lib._objc_msgSend_759(_id, _lib._sel_scanHexInt_1, result); } bool scanHexLongLong_(ffi.Pointer result) { - return _lib._objc_msgSend_752(_id, _lib._sel_scanHexLongLong_1, result); + return _lib._objc_msgSend_756(_id, _lib._sel_scanHexLongLong_1, result); } bool scanHexFloat_(ffi.Pointer result) { - return _lib._objc_msgSend_753(_id, _lib._sel_scanHexFloat_1, result); + return _lib._objc_msgSend_757(_id, _lib._sel_scanHexFloat_1, result); } bool scanHexDouble_(ffi.Pointer result) { - return _lib._objc_msgSend_754(_id, _lib._sel_scanHexDouble_1, result); + return _lib._objc_msgSend_758(_id, _lib._sel_scanHexDouble_1, result); } bool scanString_intoString_( NSString? string, ffi.Pointer> result) { - return _lib._objc_msgSend_756(_id, _lib._sel_scanString_intoString_1, + return _lib._objc_msgSend_760(_id, _lib._sel_scanString_intoString_1, string?._id ?? ffi.nullptr, result); } bool scanCharactersFromSet_intoString_( NSCharacterSet? set, ffi.Pointer> result) { - return _lib._objc_msgSend_757( + return _lib._objc_msgSend_761( _id, _lib._sel_scanCharactersFromSet_intoString_1, set?._id ?? ffi.nullptr, @@ -56775,13 +56948,13 @@ class NSScanner extends NSObject { bool scanUpToString_intoString_( NSString? string, ffi.Pointer> result) { - return _lib._objc_msgSend_756(_id, _lib._sel_scanUpToString_intoString_1, + return _lib._objc_msgSend_760(_id, _lib._sel_scanUpToString_intoString_1, string?._id ?? ffi.nullptr, result); } bool scanUpToCharactersFromSet_intoString_( NSCharacterSet? set, ffi.Pointer> result) { - return _lib._objc_msgSend_757( + return _lib._objc_msgSend_761( _id, _lib._sel_scanUpToCharactersFromSet_intoString_1, set?._id ?? ffi.nullptr, @@ -56806,7 +56979,7 @@ class NSScanner extends NSObject { } bool scanDecimal_(ffi.Pointer dcm) { - return _lib._objc_msgSend_758(_id, _lib._sel_scanDecimal_1, dcm); + return _lib._objc_msgSend_762(_id, _lib._sel_scanDecimal_1, dcm); } @override @@ -56926,7 +57099,7 @@ class NSException extends NSObject { static NSException exceptionWithName_reason_userInfo_(SentryCocoa _lib, NSString name, NSString? reason, NSDictionary? userInfo) { - final _ret = _lib._objc_msgSend_759( + final _ret = _lib._objc_msgSend_763( _lib._class_NSException1, _lib._sel_exceptionWithName_reason_userInfo_1, name._id, @@ -56990,8 +57163,8 @@ class NSException extends NSObject { } static void raise_format_arguments_(SentryCocoa _lib, NSString name, - NSString? format, ffi.Pointer<__va_list_tag> argList) { - _lib._objc_msgSend_760( + NSString? format, ffi.Pointer argList) { + _lib._objc_msgSend_764( _lib._class_NSException1, _lib._sel_raise_format_arguments_1, name._id, @@ -57122,7 +57295,7 @@ class NSFileHandle extends NSObject { } NSFileHandle initWithFileDescriptor_closeOnDealloc_(int fd, bool closeopt) { - final _ret = _lib._objc_msgSend_761( + final _ret = _lib._objc_msgSend_765( _id, _lib._sel_initWithFileDescriptor_closeOnDealloc_1, fd, closeopt); return NSFileHandle._(_ret, _lib, retain: true, release: true); } @@ -57135,60 +57308,60 @@ class NSFileHandle extends NSObject { NSData readDataToEndOfFileAndReturnError_( ffi.Pointer> error) { - final _ret = _lib._objc_msgSend_762( + final _ret = _lib._objc_msgSend_766( _id, _lib._sel_readDataToEndOfFileAndReturnError_1, error); return NSData._(_ret, _lib, retain: true, release: true); } NSData readDataUpToLength_error_( int length, ffi.Pointer> error) { - final _ret = _lib._objc_msgSend_763( + final _ret = _lib._objc_msgSend_767( _id, _lib._sel_readDataUpToLength_error_1, length, error); return NSData._(_ret, _lib, retain: true, release: true); } bool writeData_error_( NSData? data, ffi.Pointer> error) { - return _lib._objc_msgSend_764( + return _lib._objc_msgSend_768( _id, _lib._sel_writeData_error_1, data?._id ?? ffi.nullptr, error); } bool getOffset_error_(ffi.Pointer offsetInFile, ffi.Pointer> error) { - return _lib._objc_msgSend_765( + return _lib._objc_msgSend_769( _id, _lib._sel_getOffset_error_1, offsetInFile, error); } bool seekToEndReturningOffset_error_( ffi.Pointer offsetInFile, ffi.Pointer> error) { - return _lib._objc_msgSend_765( + return _lib._objc_msgSend_769( _id, _lib._sel_seekToEndReturningOffset_error_1, offsetInFile, error); } bool seekToOffset_error_( int offset, ffi.Pointer> error) { - return _lib._objc_msgSend_766( + return _lib._objc_msgSend_770( _id, _lib._sel_seekToOffset_error_1, offset, error); } bool truncateAtOffset_error_( int offset, ffi.Pointer> error) { - return _lib._objc_msgSend_766( + return _lib._objc_msgSend_770( _id, _lib._sel_truncateAtOffset_error_1, offset, error); } bool synchronizeAndReturnError_(ffi.Pointer> error) { - return _lib._objc_msgSend_225( + return _lib._objc_msgSend_236( _id, _lib._sel_synchronizeAndReturnError_1, error); } bool closeAndReturnError_(ffi.Pointer> error) { - return _lib._objc_msgSend_225(_id, _lib._sel_closeAndReturnError_1, error); + return _lib._objc_msgSend_236(_id, _lib._sel_closeAndReturnError_1, error); } static NSFileHandle? getFileHandleWithStandardInput(SentryCocoa _lib) { - final _ret = _lib._objc_msgSend_767( + final _ret = _lib._objc_msgSend_771( _lib._class_NSFileHandle1, _lib._sel_fileHandleWithStandardInput1); return _ret.address == 0 ? null @@ -57196,7 +57369,7 @@ class NSFileHandle extends NSObject { } static NSFileHandle? getFileHandleWithStandardOutput(SentryCocoa _lib) { - final _ret = _lib._objc_msgSend_767( + final _ret = _lib._objc_msgSend_771( _lib._class_NSFileHandle1, _lib._sel_fileHandleWithStandardOutput1); return _ret.address == 0 ? null @@ -57204,7 +57377,7 @@ class NSFileHandle extends NSObject { } static NSFileHandle? getFileHandleWithStandardError(SentryCocoa _lib) { - final _ret = _lib._objc_msgSend_767( + final _ret = _lib._objc_msgSend_771( _lib._class_NSFileHandle1, _lib._sel_fileHandleWithStandardError1); return _ret.address == 0 ? null @@ -57212,7 +57385,7 @@ class NSFileHandle extends NSObject { } static NSFileHandle? getFileHandleWithNullDevice(SentryCocoa _lib) { - final _ret = _lib._objc_msgSend_767( + final _ret = _lib._objc_msgSend_771( _lib._class_NSFileHandle1, _lib._sel_fileHandleWithNullDevice1); return _ret.address == 0 ? null @@ -57242,7 +57415,7 @@ class NSFileHandle extends NSObject { static NSFileHandle fileHandleForReadingFromURL_error_(SentryCocoa _lib, NSURL? url, ffi.Pointer> error) { - final _ret = _lib._objc_msgSend_768( + final _ret = _lib._objc_msgSend_772( _lib._class_NSFileHandle1, _lib._sel_fileHandleForReadingFromURL_error_1, url?._id ?? ffi.nullptr, @@ -57252,7 +57425,7 @@ class NSFileHandle extends NSObject { static NSFileHandle fileHandleForWritingToURL_error_(SentryCocoa _lib, NSURL? url, ffi.Pointer> error) { - final _ret = _lib._objc_msgSend_768( + final _ret = _lib._objc_msgSend_772( _lib._class_NSFileHandle1, _lib._sel_fileHandleForWritingToURL_error_1, url?._id ?? ffi.nullptr, @@ -57262,7 +57435,7 @@ class NSFileHandle extends NSObject { static NSFileHandle fileHandleForUpdatingURL_error_(SentryCocoa _lib, NSURL? url, ffi.Pointer> error) { - final _ret = _lib._objc_msgSend_768( + final _ret = _lib._objc_msgSend_772( _lib._class_NSFileHandle1, _lib._sel_fileHandleForUpdatingURL_error_1, url?._id ?? ffi.nullptr, @@ -57313,28 +57486,28 @@ class NSFileHandle extends NSObject { } ObjCBlock_ffiVoid_NSFileHandle get readabilityHandler { - final _ret = _lib._objc_msgSend_769(_id, _lib._sel_readabilityHandler1); + final _ret = _lib._objc_msgSend_773(_id, _lib._sel_readabilityHandler1); return ObjCBlock_ffiVoid_NSFileHandle._(_ret, _lib); } set readabilityHandler(ObjCBlock_ffiVoid_NSFileHandle value) { - return _lib._objc_msgSend_770( + return _lib._objc_msgSend_774( _id, _lib._sel_setReadabilityHandler_1, value._id); } ObjCBlock_ffiVoid_NSFileHandle get writeabilityHandler { - final _ret = _lib._objc_msgSend_769(_id, _lib._sel_writeabilityHandler1); + final _ret = _lib._objc_msgSend_773(_id, _lib._sel_writeabilityHandler1); return ObjCBlock_ffiVoid_NSFileHandle._(_ret, _lib); } set writeabilityHandler(ObjCBlock_ffiVoid_NSFileHandle value) { - return _lib._objc_msgSend_770( + return _lib._objc_msgSend_774( _id, _lib._sel_setWriteabilityHandler_1, value._id); } NSFileHandle initWithFileDescriptor_(int fd) { final _ret = - _lib._objc_msgSend_771(_id, _lib._sel_initWithFileDescriptor_1, fd); + _lib._objc_msgSend_775(_id, _lib._sel_initWithFileDescriptor_1, fd); return NSFileHandle._(_ret, _lib, retain: true, release: true); } @@ -57367,11 +57540,11 @@ class NSFileHandle extends NSObject { } void seekToFileOffset_(int offset) { - _lib._objc_msgSend_772(_id, _lib._sel_seekToFileOffset_1, offset); + _lib._objc_msgSend_776(_id, _lib._sel_seekToFileOffset_1, offset); } void truncateFileAtOffset_(int offset) { - _lib._objc_msgSend_772(_id, _lib._sel_truncateFileAtOffset_1, offset); + _lib._objc_msgSend_776(_id, _lib._sel_truncateFileAtOffset_1, offset); } void synchronizeFile() { @@ -57570,7 +57743,7 @@ class NSHTTPCookieStorage extends NSObject { } static NSHTTPCookieStorage? getSharedHTTPCookieStorage(SentryCocoa _lib) { - final _ret = _lib._objc_msgSend_773( + final _ret = _lib._objc_msgSend_777( _lib._class_NSHTTPCookieStorage1, _lib._sel_sharedHTTPCookieStorage1); return _ret.address == 0 ? null @@ -57579,7 +57752,7 @@ class NSHTTPCookieStorage extends NSObject { static NSHTTPCookieStorage sharedCookieStorageForGroupContainerIdentifier_( SentryCocoa _lib, NSString? identifier) { - final _ret = _lib._objc_msgSend_774( + final _ret = _lib._objc_msgSend_778( _lib._class_NSHTTPCookieStorage1, _lib._sel_sharedCookieStorageForGroupContainerIdentifier_1, identifier?._id ?? ffi.nullptr); @@ -57594,12 +57767,12 @@ class NSHTTPCookieStorage extends NSObject { } void setCookie_(NSHTTPCookie? cookie) { - _lib._objc_msgSend_777( + _lib._objc_msgSend_781( _id, _lib._sel_setCookie_1, cookie?._id ?? ffi.nullptr); } void deleteCookie_(NSHTTPCookie? cookie) { - _lib._objc_msgSend_777( + _lib._objc_msgSend_781( _id, _lib._sel_deleteCookie_1, cookie?._id ?? ffi.nullptr); } @@ -57616,7 +57789,7 @@ class NSHTTPCookieStorage extends NSObject { void setCookies_forURL_mainDocumentURL_( NSArray? cookies, NSURL? URL, NSURL? mainDocumentURL) { - _lib._objc_msgSend_778( + _lib._objc_msgSend_782( _id, _lib._sel_setCookies_forURL_mainDocumentURL_1, cookies?._id ?? ffi.nullptr, @@ -57625,11 +57798,11 @@ class NSHTTPCookieStorage extends NSObject { } int get cookieAcceptPolicy { - return _lib._objc_msgSend_779(_id, _lib._sel_cookieAcceptPolicy1); + return _lib._objc_msgSend_783(_id, _lib._sel_cookieAcceptPolicy1); } set cookieAcceptPolicy(int value) { - return _lib._objc_msgSend_780( + return _lib._objc_msgSend_784( _id, _lib._sel_setCookieAcceptPolicy_1, value); } @@ -57642,13 +57815,13 @@ class NSHTTPCookieStorage extends NSObject { } void storeCookies_forTask_(NSArray? cookies, NSURLSessionTask? task) { - _lib._objc_msgSend_800(_id, _lib._sel_storeCookies_forTask_1, + _lib._objc_msgSend_804(_id, _lib._sel_storeCookies_forTask_1, cookies?._id ?? ffi.nullptr, task?._id ?? ffi.nullptr); } void getCookiesForTask_completionHandler_( NSURLSessionTask? task, ObjCBlock_ffiVoid_NSArray completionHandler) { - _lib._objc_msgSend_801(_id, _lib._sel_getCookiesForTask_completionHandler_1, + _lib._objc_msgSend_805(_id, _lib._sel_getCookiesForTask_completionHandler_1, task?._id ?? ffi.nullptr, completionHandler._id); } @@ -57776,7 +57949,7 @@ class NSHTTPCookie extends NSObject { static NSHTTPCookie cookieWithProperties_( SentryCocoa _lib, NSDictionary? properties) { - final _ret = _lib._objc_msgSend_775(_lib._class_NSHTTPCookie1, + final _ret = _lib._objc_msgSend_779(_lib._class_NSHTTPCookie1, _lib._sel_cookieWithProperties_1, properties?._id ?? ffi.nullptr); return NSHTTPCookie._(_ret, _lib, retain: true, release: true); } @@ -57792,7 +57965,7 @@ class NSHTTPCookie extends NSObject { static NSArray cookiesWithResponseHeaderFields_forURL_( SentryCocoa _lib, NSDictionary? headerFields, NSURL? URL) { - final _ret = _lib._objc_msgSend_776( + final _ret = _lib._objc_msgSend_780( _lib._class_NSHTTPCookie1, _lib._sel_cookiesWithResponseHeaderFields_forURL_1, headerFields?._id ?? ffi.nullptr, @@ -58012,21 +58185,21 @@ class NSURLSessionTask extends NSObject { } NSURLRequest? get originalRequest { - final _ret = _lib._objc_msgSend_795(_id, _lib._sel_originalRequest1); + final _ret = _lib._objc_msgSend_799(_id, _lib._sel_originalRequest1); return _ret.address == 0 ? null : NSURLRequest._(_ret, _lib, retain: true, release: true); } NSURLRequest? get currentRequest { - final _ret = _lib._objc_msgSend_795(_id, _lib._sel_currentRequest1); + final _ret = _lib._objc_msgSend_799(_id, _lib._sel_currentRequest1); return _ret.address == 0 ? null : NSURLRequest._(_ret, _lib, retain: true, release: true); } NSURLResponse? get response { - final _ret = _lib._objc_msgSend_797(_id, _lib._sel_response1); + final _ret = _lib._objc_msgSend_801(_id, _lib._sel_response1); return _ret.address == 0 ? null : NSURLResponse._(_ret, _lib, retain: true, release: true); @@ -58117,7 +58290,7 @@ class NSURLSessionTask extends NSObject { } int get state { - return _lib._objc_msgSend_798(_id, _lib._sel_state1); + return _lib._objc_msgSend_802(_id, _lib._sel_state1); } NSError? get error { @@ -58140,7 +58313,7 @@ class NSURLSessionTask extends NSObject { } set priority(double value) { - return _lib._objc_msgSend_799(_id, _lib._sel_setPriority_1, value); + return _lib._objc_msgSend_803(_id, _lib._sel_setPriority_1, value); } bool get prefersIncrementalDelivery { @@ -58281,7 +58454,7 @@ class NSURLRequest extends NSObject { static NSURLRequest requestWithURL_cachePolicy_timeoutInterval_( SentryCocoa _lib, NSURL? URL, int cachePolicy, double timeoutInterval) { - final _ret = _lib._objc_msgSend_781( + final _ret = _lib._objc_msgSend_785( _lib._class_NSURLRequest1, _lib._sel_requestWithURL_cachePolicy_timeoutInterval_1, URL?._id ?? ffi.nullptr, @@ -58298,7 +58471,7 @@ class NSURLRequest extends NSObject { NSURLRequest initWithURL_cachePolicy_timeoutInterval_( NSURL? URL, int cachePolicy, double timeoutInterval) { - final _ret = _lib._objc_msgSend_781( + final _ret = _lib._objc_msgSend_785( _id, _lib._sel_initWithURL_cachePolicy_timeoutInterval_1, URL?._id ?? ffi.nullptr, @@ -58315,7 +58488,7 @@ class NSURLRequest extends NSObject { } int get cachePolicy { - return _lib._objc_msgSend_782(_id, _lib._sel_cachePolicy1); + return _lib._objc_msgSend_786(_id, _lib._sel_cachePolicy1); } double get timeoutInterval { @@ -58330,7 +58503,7 @@ class NSURLRequest extends NSObject { } int get networkServiceType { - return _lib._objc_msgSend_783(_id, _lib._sel_networkServiceType1); + return _lib._objc_msgSend_787(_id, _lib._sel_networkServiceType1); } bool get allowsCellularAccess { @@ -58351,7 +58524,7 @@ class NSURLRequest extends NSObject { } int get attribution { - return _lib._objc_msgSend_784(_id, _lib._sel_attribution1); + return _lib._objc_msgSend_788(_id, _lib._sel_attribution1); } bool get requiresDNSSECValidation { @@ -58386,7 +58559,7 @@ class NSURLRequest extends NSObject { } NSInputStream? get HTTPBodyStream { - final _ret = _lib._objc_msgSend_794(_id, _lib._sel_HTTPBodyStream1); + final _ret = _lib._objc_msgSend_798(_id, _lib._sel_HTTPBodyStream1); return _ret.address == 0 ? null : NSInputStream._(_ret, _lib, retain: true, release: true); @@ -58544,12 +58717,12 @@ class NSInputStream extends NSStream { } int read_maxLength_(ffi.Pointer buffer, int len) { - return _lib._objc_msgSend_786(_id, _lib._sel_read_maxLength_1, buffer, len); + return _lib._objc_msgSend_790(_id, _lib._sel_read_maxLength_1, buffer, len); } bool getBuffer_length_(ffi.Pointer> buffer, ffi.Pointer len) { - return _lib._objc_msgSend_793( + return _lib._objc_msgSend_797( _id, _lib._sel_getBuffer_length_1, buffer, len); } @@ -58600,7 +58773,7 @@ class NSInputStream extends NSStream { int port, ffi.Pointer> inputStream, ffi.Pointer> outputStream) { - _lib._objc_msgSend_788( + _lib._objc_msgSend_792( _lib._class_NSInputStream1, _lib._sel_getStreamsToHostWithName_port_inputStream_outputStream_1, hostname?._id ?? ffi.nullptr, @@ -58615,7 +58788,7 @@ class NSInputStream extends NSStream { int port, ffi.Pointer> inputStream, ffi.Pointer> outputStream) { - _lib._objc_msgSend_791( + _lib._objc_msgSend_795( _lib._class_NSInputStream1, _lib._sel_getStreamsToHost_port_inputStream_outputStream_1, host?._id ?? ffi.nullptr, @@ -58629,7 +58802,7 @@ class NSInputStream extends NSStream { int bufferSize, ffi.Pointer> inputStream, ffi.Pointer> outputStream) { - _lib._objc_msgSend_792( + _lib._objc_msgSend_796( _lib._class_NSInputStream1, _lib._sel_getBoundStreamsWithBufferSize_inputStream_outputStream_1, bufferSize, @@ -58795,7 +58968,7 @@ class NSStream extends NSObject { } int get streamStatus { - return _lib._objc_msgSend_785(_id, _lib._sel_streamStatus1); + return _lib._objc_msgSend_789(_id, _lib._sel_streamStatus1); } NSError? get streamError { @@ -58811,7 +58984,7 @@ class NSStream extends NSObject { int port, ffi.Pointer> inputStream, ffi.Pointer> outputStream) { - _lib._objc_msgSend_788( + _lib._objc_msgSend_792( _lib._class_NSStream1, _lib._sel_getStreamsToHostWithName_port_inputStream_outputStream_1, hostname?._id ?? ffi.nullptr, @@ -58826,7 +58999,7 @@ class NSStream extends NSObject { int port, ffi.Pointer> inputStream, ffi.Pointer> outputStream) { - _lib._objc_msgSend_791( + _lib._objc_msgSend_795( _lib._class_NSStream1, _lib._sel_getStreamsToHost_port_inputStream_outputStream_1, host?._id ?? ffi.nullptr, @@ -58840,7 +59013,7 @@ class NSStream extends NSObject { int bufferSize, ffi.Pointer> inputStream, ffi.Pointer> outputStream) { - _lib._objc_msgSend_792( + _lib._objc_msgSend_796( _lib._class_NSStream1, _lib._sel_getBoundStreamsWithBufferSize_inputStream_outputStream_1, bufferSize, @@ -58973,7 +59146,7 @@ class NSOutputStream extends NSStream { } int write_maxLength_(ffi.Pointer buffer, int len) { - return _lib._objc_msgSend_786( + return _lib._objc_msgSend_790( _id, _lib._sel_write_maxLength_1, buffer, len); } @@ -58988,7 +59161,7 @@ class NSOutputStream extends NSStream { NSOutputStream initToBuffer_capacity_( ffi.Pointer buffer, int capacity) { - final _ret = _lib._objc_msgSend_787( + final _ret = _lib._objc_msgSend_791( _id, _lib._sel_initToBuffer_capacity_1, buffer, capacity); return NSOutputStream._(_ret, _lib, retain: true, release: true); } @@ -59013,7 +59186,7 @@ class NSOutputStream extends NSStream { static NSOutputStream outputStreamToBuffer_capacity_( SentryCocoa _lib, ffi.Pointer buffer, int capacity) { - final _ret = _lib._objc_msgSend_787(_lib._class_NSOutputStream1, + final _ret = _lib._objc_msgSend_791(_lib._class_NSOutputStream1, _lib._sel_outputStreamToBuffer_capacity_1, buffer, capacity); return NSOutputStream._(_ret, _lib, retain: true, release: true); } @@ -59044,7 +59217,7 @@ class NSOutputStream extends NSStream { int port, ffi.Pointer> inputStream, ffi.Pointer> outputStream) { - _lib._objc_msgSend_788( + _lib._objc_msgSend_792( _lib._class_NSOutputStream1, _lib._sel_getStreamsToHostWithName_port_inputStream_outputStream_1, hostname?._id ?? ffi.nullptr, @@ -59059,7 +59232,7 @@ class NSOutputStream extends NSStream { int port, ffi.Pointer> inputStream, ffi.Pointer> outputStream) { - _lib._objc_msgSend_791( + _lib._objc_msgSend_795( _lib._class_NSOutputStream1, _lib._sel_getStreamsToHost_port_inputStream_outputStream_1, host?._id ?? ffi.nullptr, @@ -59073,7 +59246,7 @@ class NSOutputStream extends NSStream { int bufferSize, ffi.Pointer> inputStream, ffi.Pointer> outputStream) { - _lib._objc_msgSend_792( + _lib._objc_msgSend_796( _lib._class_NSOutputStream1, _lib._sel_getBoundStreamsWithBufferSize_inputStream_outputStream_1, bufferSize, @@ -59215,7 +59388,7 @@ class NSHost extends NSObject { } bool isEqualToHost_(NSHost? aHost) { - return _lib._objc_msgSend_789( + return _lib._objc_msgSend_793( _id, _lib._sel_isEqualToHost_1, aHost?._id ?? ffi.nullptr); } @@ -59255,7 +59428,7 @@ class NSHost extends NSObject { } static void setHostCacheEnabled_(SentryCocoa _lib, bool flag) { - _lib._objc_msgSend_790( + _lib._objc_msgSend_794( _lib._class_NSHost1, _lib._sel_setHostCacheEnabled_1, flag); } @@ -59383,7 +59556,7 @@ class NSURLResponse extends NSObject { NSURLResponse initWithURL_MIMEType_expectedContentLength_textEncodingName_( NSURL? URL, NSString? MIMEType, int length, NSString? name) { - final _ret = _lib._objc_msgSend_796( + final _ret = _lib._objc_msgSend_800( _id, _lib._sel_initWithURL_MIMEType_expectedContentLength_textEncodingName_1, URL?._id ?? ffi.nullptr, @@ -59625,14 +59798,14 @@ class NSIndexPath extends NSObject { static NSIndexPath indexPathWithIndexes_length_( SentryCocoa _lib, ffi.Pointer indexes, int length) { - final _ret = _lib._objc_msgSend_802(_lib._class_NSIndexPath1, + final _ret = _lib._objc_msgSend_806(_lib._class_NSIndexPath1, _lib._sel_indexPathWithIndexes_length_1, indexes, length); return NSIndexPath._(_ret, _lib, retain: true, release: true); } NSIndexPath initWithIndexes_length_( ffi.Pointer indexes, int length) { - final _ret = _lib._objc_msgSend_802( + final _ret = _lib._objc_msgSend_806( _id, _lib._sel_initWithIndexes_length_1, indexes, length); return NSIndexPath._(_ret, _lib, retain: true, release: true); } @@ -59644,13 +59817,13 @@ class NSIndexPath extends NSObject { NSIndexPath indexPathByAddingIndex_(int index) { final _ret = - _lib._objc_msgSend_803(_id, _lib._sel_indexPathByAddingIndex_1, index); + _lib._objc_msgSend_807(_id, _lib._sel_indexPathByAddingIndex_1, index); return NSIndexPath._(_ret, _lib, retain: true, release: true); } NSIndexPath indexPathByRemovingLastIndex() { final _ret = - _lib._objc_msgSend_804(_id, _lib._sel_indexPathByRemovingLastIndex1); + _lib._objc_msgSend_808(_id, _lib._sel_indexPathByRemovingLastIndex1); return NSIndexPath._(_ret, _lib, retain: true, release: true); } @@ -59664,17 +59837,17 @@ class NSIndexPath extends NSObject { void getIndexes_range_( ffi.Pointer indexes, _NSRange positionRange) { - _lib._objc_msgSend_805( + _lib._objc_msgSend_809( _id, _lib._sel_getIndexes_range_1, indexes, positionRange); } int compare_(NSIndexPath? otherObject) { - return _lib._objc_msgSend_806( + return _lib._objc_msgSend_810( _id, _lib._sel_compare_1, otherObject?._id ?? ffi.nullptr); } void getIndexes_(ffi.Pointer indexes) { - _lib._objc_msgSend_807(_id, _lib._sel_getIndexes_1, indexes); + _lib._objc_msgSend_811(_id, _lib._sel_getIndexes_1, indexes); } @override @@ -59800,7 +59973,7 @@ class NSInflectionRule extends NSObject { } static NSInflectionRule? getAutomaticRule(SentryCocoa _lib) { - final _ret = _lib._objc_msgSend_808( + final _ret = _lib._objc_msgSend_812( _lib._class_NSInflectionRule1, _lib._sel_automaticRule1); return _ret.address == 0 ? null @@ -59928,38 +60101,78 @@ class NSMorphology extends NSObject { } int get grammaticalGender { - return _lib._objc_msgSend_809(_id, _lib._sel_grammaticalGender1); + return _lib._objc_msgSend_813(_id, _lib._sel_grammaticalGender1); } set grammaticalGender(int value) { - return _lib._objc_msgSend_810(_id, _lib._sel_setGrammaticalGender_1, value); + return _lib._objc_msgSend_814(_id, _lib._sel_setGrammaticalGender_1, value); } int get partOfSpeech { - return _lib._objc_msgSend_811(_id, _lib._sel_partOfSpeech1); + return _lib._objc_msgSend_815(_id, _lib._sel_partOfSpeech1); } set partOfSpeech(int value) { - return _lib._objc_msgSend_812(_id, _lib._sel_setPartOfSpeech_1, value); + return _lib._objc_msgSend_816(_id, _lib._sel_setPartOfSpeech_1, value); } int get number { - return _lib._objc_msgSend_813(_id, _lib._sel_number1); + return _lib._objc_msgSend_817(_id, _lib._sel_number1); } set number(int value) { - return _lib._objc_msgSend_814(_id, _lib._sel_setNumber_1, value); + return _lib._objc_msgSend_818(_id, _lib._sel_setNumber_1, value); + } + + int get grammaticalCase { + return _lib._objc_msgSend_819(_id, _lib._sel_grammaticalCase1); + } + + set grammaticalCase(int value) { + return _lib._objc_msgSend_820(_id, _lib._sel_setGrammaticalCase_1, value); + } + + int get determination { + return _lib._objc_msgSend_821(_id, _lib._sel_determination1); + } + + set determination(int value) { + return _lib._objc_msgSend_822(_id, _lib._sel_setDetermination_1, value); + } + + int get grammaticalPerson { + return _lib._objc_msgSend_823(_id, _lib._sel_grammaticalPerson1); + } + + set grammaticalPerson(int value) { + return _lib._objc_msgSend_824(_id, _lib._sel_setGrammaticalPerson_1, value); + } + + int get pronounType { + return _lib._objc_msgSend_825(_id, _lib._sel_pronounType1); + } + + set pronounType(int value) { + return _lib._objc_msgSend_826(_id, _lib._sel_setPronounType_1, value); + } + + int get definiteness { + return _lib._objc_msgSend_827(_id, _lib._sel_definiteness1); + } + + set definiteness(int value) { + return _lib._objc_msgSend_828(_id, _lib._sel_setDefiniteness_1, value); } NSMorphologyCustomPronoun customPronounForLanguage_(NSString? language) { - final _ret = _lib._objc_msgSend_815(_id, + final _ret = _lib._objc_msgSend_829(_id, _lib._sel_customPronounForLanguage_1, language?._id ?? ffi.nullptr); return NSMorphologyCustomPronoun._(_ret, _lib, retain: true, release: true); } bool setCustomPronoun_forLanguage_error_(NSMorphologyCustomPronoun? features, NSString? language, ffi.Pointer> error) { - return _lib._objc_msgSend_816( + return _lib._objc_msgSend_830( _id, _lib._sel_setCustomPronoun_forLanguage_error_1, features?._id ?? ffi.nullptr, @@ -59972,7 +60185,7 @@ class NSMorphology extends NSObject { } static NSMorphology? getUserMorphology(SentryCocoa _lib) { - final _ret = _lib._objc_msgSend_817( + final _ret = _lib._objc_msgSend_831( _lib._class_NSMorphology1, _lib._sel_userMorphology1); return _ret.address == 0 ? null @@ -60107,6 +60320,50 @@ abstract class NSGrammaticalNumber { static const int NSGrammaticalNumberPluralMany = 6; } +abstract class NSGrammaticalCase { + static const int NSGrammaticalCaseNotSet = 0; + static const int NSGrammaticalCaseNominative = 1; + static const int NSGrammaticalCaseAccusative = 2; + static const int NSGrammaticalCaseDative = 3; + static const int NSGrammaticalCaseGenitive = 4; + static const int NSGrammaticalCasePrepositional = 5; + static const int NSGrammaticalCaseAblative = 6; + static const int NSGrammaticalCaseAdessive = 7; + static const int NSGrammaticalCaseAllative = 8; + static const int NSGrammaticalCaseElative = 9; + static const int NSGrammaticalCaseIllative = 10; + static const int NSGrammaticalCaseEssive = 11; + static const int NSGrammaticalCaseInessive = 12; + static const int NSGrammaticalCaseLocative = 13; + static const int NSGrammaticalCaseTranslative = 14; +} + +abstract class NSGrammaticalDetermination { + static const int NSGrammaticalDeterminationNotSet = 0; + static const int NSGrammaticalDeterminationIndependent = 1; + static const int NSGrammaticalDeterminationDependent = 2; +} + +abstract class NSGrammaticalPerson { + static const int NSGrammaticalPersonNotSet = 0; + static const int NSGrammaticalPersonFirst = 1; + static const int NSGrammaticalPersonSecond = 2; + static const int NSGrammaticalPersonThird = 3; +} + +abstract class NSGrammaticalPronounType { + static const int NSGrammaticalPronounTypeNotSet = 0; + static const int NSGrammaticalPronounTypePersonal = 1; + static const int NSGrammaticalPronounTypeReflexive = 2; + static const int NSGrammaticalPronounTypePossessive = 3; +} + +abstract class NSGrammaticalDefiniteness { + static const int NSGrammaticalDefinitenessNotSet = 0; + static const int NSGrammaticalDefinitenessIndefinite = 1; + static const int NSGrammaticalDefinitenessDefinite = 2; +} + class NSMorphologyCustomPronoun extends NSObject { NSMorphologyCustomPronoun._(ffi.Pointer id, SentryCocoa lib, {bool retain = false, bool release = false}) @@ -60332,12 +60589,12 @@ class NSOperationQueue extends NSObject { } void addOperation_(NSOperation? op) { - _lib._objc_msgSend_818( + _lib._objc_msgSend_832( _id, _lib._sel_addOperation_1, op?._id ?? ffi.nullptr); } void addOperations_waitUntilFinished_(NSArray? ops, bool wait) { - _lib._objc_msgSend_821(_id, _lib._sel_addOperations_waitUntilFinished_1, + _lib._objc_msgSend_835(_id, _lib._sel_addOperations_waitUntilFinished_1, ops?._id ?? ffi.nullptr, wait); } @@ -60387,12 +60644,12 @@ class NSOperationQueue extends NSObject { } NSObject get underlyingQueue { - final _ret = _lib._objc_msgSend_822(_id, _lib._sel_underlyingQueue1); + final _ret = _lib._objc_msgSend_836(_id, _lib._sel_underlyingQueue1); return NSObject._(_ret, _lib, retain: true, release: true); } set underlyingQueue(NSObject value) { - return _lib._objc_msgSend_823( + return _lib._objc_msgSend_837( _id, _lib._sel_setUnderlyingQueue_1, value._id); } @@ -60405,7 +60662,7 @@ class NSOperationQueue extends NSObject { } static NSOperationQueue? getCurrentQueue(SentryCocoa _lib) { - final _ret = _lib._objc_msgSend_824( + final _ret = _lib._objc_msgSend_838( _lib._class_NSOperationQueue1, _lib._sel_currentQueue1); return _ret.address == 0 ? null @@ -60413,7 +60670,7 @@ class NSOperationQueue extends NSObject { } static NSOperationQueue? getMainQueue(SentryCocoa _lib) { - final _ret = _lib._objc_msgSend_824( + final _ret = _lib._objc_msgSend_838( _lib._class_NSOperationQueue1, _lib._sel_mainQueue1); return _ret.address == 0 ? null @@ -60584,12 +60841,12 @@ class NSOperation extends NSObject { } void addDependency_(NSOperation? op) { - _lib._objc_msgSend_818( + _lib._objc_msgSend_832( _id, _lib._sel_addDependency_1, op?._id ?? ffi.nullptr); } void removeDependency_(NSOperation? op) { - _lib._objc_msgSend_818( + _lib._objc_msgSend_832( _id, _lib._sel_removeDependency_1, op?._id ?? ffi.nullptr); } @@ -60601,11 +60858,11 @@ class NSOperation extends NSObject { } int get queuePriority { - return _lib._objc_msgSend_819(_id, _lib._sel_queuePriority1); + return _lib._objc_msgSend_833(_id, _lib._sel_queuePriority1); } set queuePriority(int value) { - return _lib._objc_msgSend_820(_id, _lib._sel_setQueuePriority_1, value); + return _lib._objc_msgSend_834(_id, _lib._sel_setQueuePriority_1, value); } ObjCBlock_ffiVoid get completionBlock { @@ -60775,26 +61032,26 @@ class NSPointerArray extends NSObject { NSPointerArray initWithOptions_(int options) { final _ret = - _lib._objc_msgSend_825(_id, _lib._sel_initWithOptions_1, options); + _lib._objc_msgSend_839(_id, _lib._sel_initWithOptions_1, options); return NSPointerArray._(_ret, _lib, retain: true, release: true); } NSPointerArray initWithPointerFunctions_(NSPointerFunctions? functions) { - final _ret = _lib._objc_msgSend_839(_id, + final _ret = _lib._objc_msgSend_853(_id, _lib._sel_initWithPointerFunctions_1, functions?._id ?? ffi.nullptr); return NSPointerArray._(_ret, _lib, retain: true, release: true); } static NSPointerArray pointerArrayWithOptions_( SentryCocoa _lib, int options) { - final _ret = _lib._objc_msgSend_840(_lib._class_NSPointerArray1, + final _ret = _lib._objc_msgSend_854(_lib._class_NSPointerArray1, _lib._sel_pointerArrayWithOptions_1, options); return NSPointerArray._(_ret, _lib, retain: true, release: true); } static NSPointerArray pointerArrayWithPointerFunctions_( SentryCocoa _lib, NSPointerFunctions? functions) { - final _ret = _lib._objc_msgSend_841( + final _ret = _lib._objc_msgSend_855( _lib._class_NSPointerArray1, _lib._sel_pointerArrayWithPointerFunctions_1, functions?._id ?? ffi.nullptr); @@ -60802,14 +61059,14 @@ class NSPointerArray extends NSObject { } NSPointerFunctions? get pointerFunctions { - final _ret = _lib._objc_msgSend_842(_id, _lib._sel_pointerFunctions1); + final _ret = _lib._objc_msgSend_856(_id, _lib._sel_pointerFunctions1); return _ret.address == 0 ? null : NSPointerFunctions._(_ret, _lib, retain: true, release: true); } ffi.Pointer pointerAtIndex_(int index) { - return _lib._objc_msgSend_843(_id, _lib._sel_pointerAtIndex_1, index); + return _lib._objc_msgSend_857(_id, _lib._sel_pointerAtIndex_1, index); } void addPointer_(ffi.Pointer pointer) { @@ -60826,7 +61083,7 @@ class NSPointerArray extends NSObject { void replacePointerAtIndex_withPointer_( int index, ffi.Pointer item) { - _lib._objc_msgSend_844( + _lib._objc_msgSend_858( _id, _lib._sel_replacePointerAtIndex_withPointer_1, index, item); } @@ -60855,13 +61112,13 @@ class NSPointerArray extends NSObject { } static NSPointerArray strongObjectsPointerArray(SentryCocoa _lib) { - final _ret = _lib._objc_msgSend_845( + final _ret = _lib._objc_msgSend_859( _lib._class_NSPointerArray1, _lib._sel_strongObjectsPointerArray1); return NSPointerArray._(_ret, _lib, retain: true, release: true); } static NSPointerArray weakObjectsPointerArray(SentryCocoa _lib) { - final _ret = _lib._objc_msgSend_845( + final _ret = _lib._objc_msgSend_859( _lib._class_NSPointerArray1, _lib._sel_weakObjectsPointerArray1); return NSPointerArray._(_ret, _lib, retain: true, release: true); } @@ -61008,13 +61265,13 @@ class NSPointerFunctions extends NSObject { NSPointerFunctions initWithOptions_(int options) { final _ret = - _lib._objc_msgSend_825(_id, _lib._sel_initWithOptions_1, options); + _lib._objc_msgSend_839(_id, _lib._sel_initWithOptions_1, options); return NSPointerFunctions._(_ret, _lib, retain: true, release: true); } static NSPointerFunctions pointerFunctionsWithOptions_( SentryCocoa _lib, int options) { - final _ret = _lib._objc_msgSend_826(_lib._class_NSPointerFunctions1, + final _ret = _lib._objc_msgSend_840(_lib._class_NSPointerFunctions1, _lib._sel_pointerFunctionsWithOptions_1, options); return NSPointerFunctions._(_ret, _lib, retain: true, release: true); } @@ -61027,7 +61284,7 @@ class NSPointerFunctions extends NSObject { ffi.NativeFunction< ffi.UnsignedLong Function(ffi.Pointer)>>)>> get hashFunction { - return _lib._objc_msgSend_827(_id, _lib._sel_hashFunction1); + return _lib._objc_msgSend_841(_id, _lib._sel_hashFunction1); } set hashFunction( @@ -61040,7 +61297,7 @@ class NSPointerFunctions extends NSObject { ffi.UnsignedLong Function( ffi.Pointer)>>)>> value) { - return _lib._objc_msgSend_828(_id, _lib._sel_setHashFunction_1, value); + return _lib._objc_msgSend_842(_id, _lib._sel_setHashFunction_1, value); } ffi.Pointer< @@ -61052,7 +61309,7 @@ class NSPointerFunctions extends NSObject { ffi.NativeFunction< ffi.UnsignedLong Function(ffi.Pointer)>>)>> get isEqualFunction { - return _lib._objc_msgSend_829(_id, _lib._sel_isEqualFunction1); + return _lib._objc_msgSend_843(_id, _lib._sel_isEqualFunction1); } set isEqualFunction( @@ -61066,13 +61323,13 @@ class NSPointerFunctions extends NSObject { ffi.UnsignedLong Function( ffi.Pointer)>>)>> value) { - return _lib._objc_msgSend_830(_id, _lib._sel_setIsEqualFunction_1, value); + return _lib._objc_msgSend_844(_id, _lib._sel_setIsEqualFunction_1, value); } ffi.Pointer< ffi.NativeFunction)>> get sizeFunction { - return _lib._objc_msgSend_831(_id, _lib._sel_sizeFunction1); + return _lib._objc_msgSend_845(_id, _lib._sel_sizeFunction1); } set sizeFunction( @@ -61080,14 +61337,14 @@ class NSPointerFunctions extends NSObject { ffi .NativeFunction)>> value) { - return _lib._objc_msgSend_832(_id, _lib._sel_setSizeFunction_1, value); + return _lib._objc_msgSend_846(_id, _lib._sel_setSizeFunction_1, value); } ffi.Pointer< ffi.NativeFunction< ffi.Pointer Function(ffi.Pointer)>> get descriptionFunction { - return _lib._objc_msgSend_833(_id, _lib._sel_descriptionFunction1); + return _lib._objc_msgSend_847(_id, _lib._sel_descriptionFunction1); } set descriptionFunction( @@ -61095,7 +61352,7 @@ class NSPointerFunctions extends NSObject { ffi.NativeFunction< ffi.Pointer Function(ffi.Pointer)>> value) { - return _lib._objc_msgSend_834( + return _lib._objc_msgSend_848( _id, _lib._sel_setDescriptionFunction_1, value); } @@ -61107,7 +61364,7 @@ class NSPointerFunctions extends NSObject { ffi.NativeFunction< ffi.UnsignedLong Function(ffi.Pointer)>>)>> get relinquishFunction { - return _lib._objc_msgSend_835(_id, _lib._sel_relinquishFunction1); + return _lib._objc_msgSend_849(_id, _lib._sel_relinquishFunction1); } set relinquishFunction( @@ -61120,7 +61377,7 @@ class NSPointerFunctions extends NSObject { ffi.UnsignedLong Function( ffi.Pointer)>>)>> value) { - return _lib._objc_msgSend_836( + return _lib._objc_msgSend_850( _id, _lib._sel_setRelinquishFunction_1, value); } @@ -61132,7 +61389,7 @@ class NSPointerFunctions extends NSObject { ffi.NativeFunction< ffi.UnsignedLong Function(ffi.Pointer)>>, ffi.Bool)>> get acquireFunction { - return _lib._objc_msgSend_837(_id, _lib._sel_acquireFunction1); + return _lib._objc_msgSend_851(_id, _lib._sel_acquireFunction1); } set acquireFunction( @@ -61146,7 +61403,7 @@ class NSPointerFunctions extends NSObject { ffi.Pointer)>>, ffi.Bool)>> value) { - return _lib._objc_msgSend_838(_id, _lib._sel_setAcquireFunction_1, value); + return _lib._objc_msgSend_852(_id, _lib._sel_setAcquireFunction_1, value); } bool get usesStrongWriteBarrier { @@ -61284,7 +61541,7 @@ class NSProcessInfo extends NSObject { } static NSProcessInfo? getProcessInfo(SentryCocoa _lib) { - final _ret = _lib._objc_msgSend_846( + final _ret = _lib._objc_msgSend_860( _lib._class_NSProcessInfo1, _lib._sel_processInfo1); return _ret.address == 0 ? null @@ -61353,7 +61610,7 @@ class NSProcessInfo extends NSObject { } void getOperatingSystemVersion(ffi.Pointer stret) { - _lib._objc_msgSend_847(stret, _id, _lib._sel_operatingSystemVersion1); + _lib._objc_msgSend_861(stret, _id, _lib._sel_operatingSystemVersion1); } int get processorCount { @@ -61369,7 +61626,7 @@ class NSProcessInfo extends NSObject { } bool isOperatingSystemAtLeastVersion_(NSOperatingSystemVersion version) { - return _lib._objc_msgSend_848( + return _lib._objc_msgSend_862( _id, _lib._sel_isOperatingSystemAtLeastVersion_1, version); } @@ -61406,7 +61663,7 @@ class NSProcessInfo extends NSObject { } NSObject beginActivityWithOptions_reason_(int options, NSString? reason) { - final _ret = _lib._objc_msgSend_849( + final _ret = _lib._objc_msgSend_863( _id, _lib._sel_beginActivityWithOptions_reason_1, options, @@ -61421,7 +61678,7 @@ class NSProcessInfo extends NSObject { void performActivityWithOptions_reason_usingBlock_( int options, NSString? reason, ObjCBlock_ffiVoid block) { - _lib._objc_msgSend_850( + _lib._objc_msgSend_864( _id, _lib._sel_performActivityWithOptions_reason_usingBlock_1, options, @@ -61431,7 +61688,7 @@ class NSProcessInfo extends NSObject { void performExpiringActivityWithReason_usingBlock_( NSString? reason, ObjCBlock_ffiVoid_bool block) { - _lib._objc_msgSend_851( + _lib._objc_msgSend_865( _id, _lib._sel_performExpiringActivityWithReason_usingBlock_1, reason?._id ?? ffi.nullptr, @@ -61453,7 +61710,7 @@ class NSProcessInfo extends NSObject { } int get thermalState { - return _lib._objc_msgSend_852(_id, _lib._sel_thermalState1); + return _lib._objc_msgSend_866(_id, _lib._sel_thermalState1); } bool get lowPowerModeEnabled { @@ -61682,7 +61939,7 @@ class NSTextCheckingResult extends NSObject { } int get resultType { - return _lib._objc_msgSend_853(_id, _lib._sel_resultType1); + return _lib._objc_msgSend_867(_id, _lib._sel_resultType1); } void getRange(ffi.Pointer<_NSRange> stret) { @@ -61690,7 +61947,7 @@ class NSTextCheckingResult extends NSObject { } NSOrthography? get orthography { - final _ret = _lib._objc_msgSend_854(_id, _lib._sel_orthography1); + final _ret = _lib._objc_msgSend_868(_id, _lib._sel_orthography1); return _ret.address == 0 ? null : NSOrthography._(_ret, _lib, retain: true, release: true); @@ -61750,7 +62007,7 @@ class NSTextCheckingResult extends NSObject { } NSRegularExpression? get regularExpression { - final _ret = _lib._objc_msgSend_866(_id, _lib._sel_regularExpression1); + final _ret = _lib._objc_msgSend_880(_id, _lib._sel_regularExpression1); return _ret.address == 0 ? null : NSRegularExpression._(_ret, _lib, retain: true, release: true); @@ -61777,7 +62034,7 @@ class NSTextCheckingResult extends NSObject { } NSTextCheckingResult resultByAdjustingRangesWithOffset_(int offset) { - final _ret = _lib._objc_msgSend_867( + final _ret = _lib._objc_msgSend_881( _id, _lib._sel_resultByAdjustingRangesWithOffset_1, offset); return NSTextCheckingResult._(_ret, _lib, retain: true, release: true); } @@ -61791,7 +62048,7 @@ class NSTextCheckingResult extends NSObject { static NSTextCheckingResult orthographyCheckingResultWithRange_orthography_( SentryCocoa _lib, _NSRange range, NSOrthography? orthography) { - final _ret = _lib._objc_msgSend_868( + final _ret = _lib._objc_msgSend_882( _lib._class_NSTextCheckingResult1, _lib._sel_orthographyCheckingResultWithRange_orthography_1, range, @@ -61801,14 +62058,14 @@ class NSTextCheckingResult extends NSObject { static NSTextCheckingResult spellCheckingResultWithRange_( SentryCocoa _lib, _NSRange range) { - final _ret = _lib._objc_msgSend_869(_lib._class_NSTextCheckingResult1, + final _ret = _lib._objc_msgSend_883(_lib._class_NSTextCheckingResult1, _lib._sel_spellCheckingResultWithRange_1, range); return NSTextCheckingResult._(_ret, _lib, retain: true, release: true); } static NSTextCheckingResult grammarCheckingResultWithRange_details_( SentryCocoa _lib, _NSRange range, NSArray? details) { - final _ret = _lib._objc_msgSend_870( + final _ret = _lib._objc_msgSend_884( _lib._class_NSTextCheckingResult1, _lib._sel_grammarCheckingResultWithRange_details_1, range, @@ -61818,7 +62075,7 @@ class NSTextCheckingResult extends NSObject { static NSTextCheckingResult dateCheckingResultWithRange_date_( SentryCocoa _lib, _NSRange range, NSDate? date) { - final _ret = _lib._objc_msgSend_871( + final _ret = _lib._objc_msgSend_885( _lib._class_NSTextCheckingResult1, _lib._sel_dateCheckingResultWithRange_date_1, range, @@ -61829,7 +62086,7 @@ class NSTextCheckingResult extends NSObject { static NSTextCheckingResult dateCheckingResultWithRange_date_timeZone_duration_(SentryCocoa _lib, _NSRange range, NSDate? date, NSTimeZone? timeZone, double duration) { - final _ret = _lib._objc_msgSend_872( + final _ret = _lib._objc_msgSend_886( _lib._class_NSTextCheckingResult1, _lib._sel_dateCheckingResultWithRange_date_timeZone_duration_1, range, @@ -61841,7 +62098,7 @@ class NSTextCheckingResult extends NSObject { static NSTextCheckingResult addressCheckingResultWithRange_components_( SentryCocoa _lib, _NSRange range, NSDictionary? components) { - final _ret = _lib._objc_msgSend_873( + final _ret = _lib._objc_msgSend_887( _lib._class_NSTextCheckingResult1, _lib._sel_addressCheckingResultWithRange_components_1, range, @@ -61851,7 +62108,7 @@ class NSTextCheckingResult extends NSObject { static NSTextCheckingResult linkCheckingResultWithRange_URL_( SentryCocoa _lib, _NSRange range, NSURL? url) { - final _ret = _lib._objc_msgSend_874( + final _ret = _lib._objc_msgSend_888( _lib._class_NSTextCheckingResult1, _lib._sel_linkCheckingResultWithRange_URL_1, range, @@ -61861,7 +62118,7 @@ class NSTextCheckingResult extends NSObject { static NSTextCheckingResult quoteCheckingResultWithRange_replacementString_( SentryCocoa _lib, _NSRange range, NSString? replacementString) { - final _ret = _lib._objc_msgSend_875( + final _ret = _lib._objc_msgSend_889( _lib._class_NSTextCheckingResult1, _lib._sel_quoteCheckingResultWithRange_replacementString_1, range, @@ -61871,7 +62128,7 @@ class NSTextCheckingResult extends NSObject { static NSTextCheckingResult dashCheckingResultWithRange_replacementString_( SentryCocoa _lib, _NSRange range, NSString? replacementString) { - final _ret = _lib._objc_msgSend_875( + final _ret = _lib._objc_msgSend_889( _lib._class_NSTextCheckingResult1, _lib._sel_dashCheckingResultWithRange_replacementString_1, range, @@ -61882,7 +62139,7 @@ class NSTextCheckingResult extends NSObject { static NSTextCheckingResult replacementCheckingResultWithRange_replacementString_( SentryCocoa _lib, _NSRange range, NSString? replacementString) { - final _ret = _lib._objc_msgSend_875( + final _ret = _lib._objc_msgSend_889( _lib._class_NSTextCheckingResult1, _lib._sel_replacementCheckingResultWithRange_replacementString_1, range, @@ -61893,7 +62150,7 @@ class NSTextCheckingResult extends NSObject { static NSTextCheckingResult correctionCheckingResultWithRange_replacementString_( SentryCocoa _lib, _NSRange range, NSString? replacementString) { - final _ret = _lib._objc_msgSend_875( + final _ret = _lib._objc_msgSend_889( _lib._class_NSTextCheckingResult1, _lib._sel_correctionCheckingResultWithRange_replacementString_1, range, @@ -61907,7 +62164,7 @@ class NSTextCheckingResult extends NSObject { _NSRange range, NSString? replacementString, NSArray? alternativeStrings) { - final _ret = _lib._objc_msgSend_876( + final _ret = _lib._objc_msgSend_890( _lib._class_NSTextCheckingResult1, _lib._sel_correctionCheckingResultWithRange_replacementString_alternativeStrings_1, range, @@ -61922,7 +62179,7 @@ class NSTextCheckingResult extends NSObject { ffi.Pointer<_NSRange> ranges, int count, NSRegularExpression? regularExpression) { - final _ret = _lib._objc_msgSend_877( + final _ret = _lib._objc_msgSend_891( _lib._class_NSTextCheckingResult1, _lib._sel_regularExpressionCheckingResultWithRanges_count_regularExpression_1, ranges, @@ -61933,7 +62190,7 @@ class NSTextCheckingResult extends NSObject { static NSTextCheckingResult phoneNumberCheckingResultWithRange_phoneNumber_( SentryCocoa _lib, _NSRange range, NSString? phoneNumber) { - final _ret = _lib._objc_msgSend_875( + final _ret = _lib._objc_msgSend_889( _lib._class_NSTextCheckingResult1, _lib._sel_phoneNumberCheckingResultWithRange_phoneNumber_1, range, @@ -61944,7 +62201,7 @@ class NSTextCheckingResult extends NSObject { static NSTextCheckingResult transitInformationCheckingResultWithRange_components_( SentryCocoa _lib, _NSRange range, NSDictionary? components) { - final _ret = _lib._objc_msgSend_873( + final _ret = _lib._objc_msgSend_887( _lib._class_NSTextCheckingResult1, _lib._sel_transitInformationCheckingResultWithRange_components_1, range, @@ -62090,7 +62347,7 @@ class NSRegularExpression extends NSObject { NSString? pattern, int options, ffi.Pointer> error) { - final _ret = _lib._objc_msgSend_855( + final _ret = _lib._objc_msgSend_869( _lib._class_NSRegularExpression1, _lib._sel_regularExpressionWithPattern_options_error_1, pattern?._id ?? ffi.nullptr, @@ -62101,7 +62358,7 @@ class NSRegularExpression extends NSObject { NSRegularExpression initWithPattern_options_error_(NSString? pattern, int options, ffi.Pointer> error) { - final _ret = _lib._objc_msgSend_856( + final _ret = _lib._objc_msgSend_870( _id, _lib._sel_initWithPattern_options_error_1, pattern?._id ?? ffi.nullptr, @@ -62118,7 +62375,7 @@ class NSRegularExpression extends NSObject { } int get options { - return _lib._objc_msgSend_857(_id, _lib._sel_options1); + return _lib._objc_msgSend_871(_id, _lib._sel_options1); } int get numberOfCaptureGroups { @@ -62136,7 +62393,7 @@ class NSRegularExpression extends NSObject { int options, _NSRange range, ObjCBlock_ffiVoid_NSTextCheckingResult_NSMatchingFlags_bool block) { - _lib._objc_msgSend_858( + _lib._objc_msgSend_872( _id, _lib._sel_enumerateMatchesInString_options_range_usingBlock_1, string?._id ?? ffi.nullptr, @@ -62147,7 +62404,7 @@ class NSRegularExpression extends NSObject { NSArray matchesInString_options_range_( NSString? string, int options, _NSRange range) { - final _ret = _lib._objc_msgSend_859( + final _ret = _lib._objc_msgSend_873( _id, _lib._sel_matchesInString_options_range_1, string?._id ?? ffi.nullptr, @@ -62158,7 +62415,7 @@ class NSRegularExpression extends NSObject { int numberOfMatchesInString_options_range_( NSString? string, int options, _NSRange range) { - return _lib._objc_msgSend_860( + return _lib._objc_msgSend_874( _id, _lib._sel_numberOfMatchesInString_options_range_1, string?._id ?? ffi.nullptr, @@ -62168,7 +62425,7 @@ class NSRegularExpression extends NSObject { NSTextCheckingResult firstMatchInString_options_range_( NSString? string, int options, _NSRange range) { - final _ret = _lib._objc_msgSend_861( + final _ret = _lib._objc_msgSend_875( _id, _lib._sel_firstMatchInString_options_range_1, string?._id ?? ffi.nullptr, @@ -62179,7 +62436,7 @@ class NSRegularExpression extends NSObject { void rangeOfFirstMatchInString_options_range_(ffi.Pointer<_NSRange> stret, NSString? string, int options, _NSRange range) { - _lib._objc_msgSend_862( + _lib._objc_msgSend_876( stret, _id, _lib._sel_rangeOfFirstMatchInString_options_range_1, @@ -62190,7 +62447,7 @@ class NSRegularExpression extends NSObject { NSString stringByReplacingMatchesInString_options_range_withTemplate_( NSString? string, int options, _NSRange range, NSString? templ) { - final _ret = _lib._objc_msgSend_863( + final _ret = _lib._objc_msgSend_877( _id, _lib._sel_stringByReplacingMatchesInString_options_range_withTemplate_1, string?._id ?? ffi.nullptr, @@ -62202,7 +62459,7 @@ class NSRegularExpression extends NSObject { int replaceMatchesInString_options_range_withTemplate_( NSMutableString? string, int options, _NSRange range, NSString? templ) { - return _lib._objc_msgSend_864( + return _lib._objc_msgSend_878( _id, _lib._sel_replaceMatchesInString_options_range_withTemplate_1, string?._id ?? ffi.nullptr, @@ -62216,7 +62473,7 @@ class NSRegularExpression extends NSObject { NSString? string, int offset, NSString? templ) { - final _ret = _lib._objc_msgSend_865( + final _ret = _lib._objc_msgSend_879( _id, _lib._sel_replacementStringForResult_inString_offset_template_1, result?._id ?? ffi.nullptr, @@ -62485,7 +62742,7 @@ class NSURLCache extends NSObject { } static NSURLCache? getSharedURLCache(SentryCocoa _lib) { - final _ret = _lib._objc_msgSend_878( + final _ret = _lib._objc_msgSend_892( _lib._class_NSURLCache1, _lib._sel_sharedURLCache1); return _ret.address == 0 ? null @@ -62493,13 +62750,13 @@ class NSURLCache extends NSObject { } static void setSharedURLCache(SentryCocoa _lib, NSURLCache? value) { - return _lib._objc_msgSend_879(_lib._class_NSURLCache1, + return _lib._objc_msgSend_893(_lib._class_NSURLCache1, _lib._sel_setSharedURLCache_1, value?._id ?? ffi.nullptr); } NSURLCache initWithMemoryCapacity_diskCapacity_diskPath_( int memoryCapacity, int diskCapacity, NSString? path) { - final _ret = _lib._objc_msgSend_880( + final _ret = _lib._objc_msgSend_894( _id, _lib._sel_initWithMemoryCapacity_diskCapacity_diskPath_1, memoryCapacity, @@ -62510,7 +62767,7 @@ class NSURLCache extends NSObject { NSURLCache initWithMemoryCapacity_diskCapacity_directoryURL_( int memoryCapacity, int diskCapacity, NSURL? directoryURL) { - final _ret = _lib._objc_msgSend_881( + final _ret = _lib._objc_msgSend_895( _id, _lib._sel_initWithMemoryCapacity_diskCapacity_directoryURL_1, memoryCapacity, @@ -62520,19 +62777,19 @@ class NSURLCache extends NSObject { } NSCachedURLResponse cachedResponseForRequest_(NSURLRequest? request) { - final _ret = _lib._objc_msgSend_885( + final _ret = _lib._objc_msgSend_899( _id, _lib._sel_cachedResponseForRequest_1, request?._id ?? ffi.nullptr); return NSCachedURLResponse._(_ret, _lib, retain: true, release: true); } void storeCachedResponse_forRequest_( NSCachedURLResponse? cachedResponse, NSURLRequest? request) { - _lib._objc_msgSend_886(_id, _lib._sel_storeCachedResponse_forRequest_1, + _lib._objc_msgSend_900(_id, _lib._sel_storeCachedResponse_forRequest_1, cachedResponse?._id ?? ffi.nullptr, request?._id ?? ffi.nullptr); } void removeCachedResponseForRequest_(NSURLRequest? request) { - _lib._objc_msgSend_887(_id, _lib._sel_removeCachedResponseForRequest_1, + _lib._objc_msgSend_901(_id, _lib._sel_removeCachedResponseForRequest_1, request?._id ?? ffi.nullptr); } @@ -62571,14 +62828,14 @@ class NSURLCache extends NSObject { void storeCachedResponse_forDataTask_( NSCachedURLResponse? cachedResponse, NSURLSessionDataTask? dataTask) { - _lib._objc_msgSend_888(_id, _lib._sel_storeCachedResponse_forDataTask_1, + _lib._objc_msgSend_902(_id, _lib._sel_storeCachedResponse_forDataTask_1, cachedResponse?._id ?? ffi.nullptr, dataTask?._id ?? ffi.nullptr); } void getCachedResponseForDataTask_completionHandler_( NSURLSessionDataTask? dataTask, ObjCBlock_ffiVoid_NSCachedURLResponse completionHandler) { - _lib._objc_msgSend_889( + _lib._objc_msgSend_903( _id, _lib._sel_getCachedResponseForDataTask_completionHandler_1, dataTask?._id ?? ffi.nullptr, @@ -62586,7 +62843,7 @@ class NSURLCache extends NSObject { } void removeCachedResponseForDataTask_(NSURLSessionDataTask? dataTask) { - _lib._objc_msgSend_890(_id, _lib._sel_removeCachedResponseForDataTask_1, + _lib._objc_msgSend_904(_id, _lib._sel_removeCachedResponseForDataTask_1, dataTask?._id ?? ffi.nullptr); } @@ -62708,7 +62965,7 @@ class NSCachedURLResponse extends NSObject { NSCachedURLResponse initWithResponse_data_( NSURLResponse? response, NSData? data) { - final _ret = _lib._objc_msgSend_882(_id, _lib._sel_initWithResponse_data_1, + final _ret = _lib._objc_msgSend_896(_id, _lib._sel_initWithResponse_data_1, response?._id ?? ffi.nullptr, data?._id ?? ffi.nullptr); return NSCachedURLResponse._(_ret, _lib, retain: true, release: true); } @@ -62718,7 +62975,7 @@ class NSCachedURLResponse extends NSObject { NSData? data, NSDictionary? userInfo, int storagePolicy) { - final _ret = _lib._objc_msgSend_883( + final _ret = _lib._objc_msgSend_897( _id, _lib._sel_initWithResponse_data_userInfo_storagePolicy_1, response?._id ?? ffi.nullptr, @@ -62729,7 +62986,7 @@ class NSCachedURLResponse extends NSObject { } NSURLResponse? get response { - final _ret = _lib._objc_msgSend_797(_id, _lib._sel_response1); + final _ret = _lib._objc_msgSend_801(_id, _lib._sel_response1); return _ret.address == 0 ? null : NSURLResponse._(_ret, _lib, retain: true, release: true); @@ -62750,7 +63007,7 @@ class NSCachedURLResponse extends NSObject { } int get storagePolicy { - return _lib._objc_msgSend_884(_id, _lib._sel_storagePolicy1); + return _lib._objc_msgSend_898(_id, _lib._sel_storagePolicy1); } @override @@ -63067,7 +63324,7 @@ class NSURLConnection extends NSObject { NSURLConnection initWithRequest_delegate_startImmediately_( NSURLRequest? request, NSObject delegate, bool startImmediately) { - final _ret = _lib._objc_msgSend_891( + final _ret = _lib._objc_msgSend_905( _id, _lib._sel_initWithRequest_delegate_startImmediately_1, request?._id ?? ffi.nullptr, @@ -63078,7 +63335,7 @@ class NSURLConnection extends NSObject { NSURLConnection initWithRequest_delegate_( NSURLRequest? request, NSObject delegate) { - final _ret = _lib._objc_msgSend_892( + final _ret = _lib._objc_msgSend_906( _id, _lib._sel_initWithRequest_delegate_1, request?._id ?? ffi.nullptr, @@ -63088,7 +63345,7 @@ class NSURLConnection extends NSObject { static NSURLConnection connectionWithRequest_delegate_( SentryCocoa _lib, NSURLRequest? request, NSObject delegate) { - final _ret = _lib._objc_msgSend_893( + final _ret = _lib._objc_msgSend_907( _lib._class_NSURLConnection1, _lib._sel_connectionWithRequest_delegate_1, request?._id ?? ffi.nullptr, @@ -63097,14 +63354,14 @@ class NSURLConnection extends NSObject { } NSURLRequest? get originalRequest { - final _ret = _lib._objc_msgSend_795(_id, _lib._sel_originalRequest1); + final _ret = _lib._objc_msgSend_799(_id, _lib._sel_originalRequest1); return _ret.address == 0 ? null : NSURLRequest._(_ret, _lib, retain: true, release: true); } NSURLRequest? get currentRequest { - final _ret = _lib._objc_msgSend_795(_id, _lib._sel_currentRequest1); + final _ret = _lib._objc_msgSend_799(_id, _lib._sel_currentRequest1); return _ret.address == 0 ? null : NSURLRequest._(_ret, _lib, retain: true, release: true); @@ -63129,12 +63386,12 @@ class NSURLConnection extends NSObject { } void setDelegateQueue_(NSOperationQueue? queue) { - _lib._objc_msgSend_894( + _lib._objc_msgSend_908( _id, _lib._sel_setDelegateQueue_1, queue?._id ?? ffi.nullptr); } static bool canHandleRequest_(SentryCocoa _lib, NSURLRequest? request) { - return _lib._objc_msgSend_895(_lib._class_NSURLConnection1, + return _lib._objc_msgSend_909(_lib._class_NSURLConnection1, _lib._sel_canHandleRequest_1, request?._id ?? ffi.nullptr); } @@ -63143,7 +63400,7 @@ class NSURLConnection extends NSObject { NSURLRequest? request, ffi.Pointer> response, ffi.Pointer> error) { - final _ret = _lib._objc_msgSend_896( + final _ret = _lib._objc_msgSend_910( _lib._class_NSURLConnection1, _lib._sel_sendSynchronousRequest_returningResponse_error_1, request?._id ?? ffi.nullptr, @@ -63157,7 +63414,7 @@ class NSURLConnection extends NSObject { NSURLRequest? request, NSOperationQueue? queue, ObjCBlock_ffiVoid_NSURLResponse_NSData_NSError handler) { - _lib._objc_msgSend_897( + _lib._objc_msgSend_911( _lib._class_NSURLConnection1, _lib._sel_sendAsynchronousRequest_queue_completionHandler_1, request?._id ?? ffi.nullptr, @@ -63393,12 +63650,12 @@ class NSURLCredential extends NSObject { } int get persistence { - return _lib._objc_msgSend_898(_id, _lib._sel_persistence1); + return _lib._objc_msgSend_912(_id, _lib._sel_persistence1); } NSURLCredential initWithUser_password_persistence_( NSString? user, NSString? password, int persistence) { - final _ret = _lib._objc_msgSend_899( + final _ret = _lib._objc_msgSend_913( _id, _lib._sel_initWithUser_password_persistence_1, user?._id ?? ffi.nullptr, @@ -63409,7 +63666,7 @@ class NSURLCredential extends NSObject { static NSURLCredential credentialWithUser_password_persistence_( SentryCocoa _lib, NSString? user, NSString? password, int persistence) { - final _ret = _lib._objc_msgSend_900( + final _ret = _lib._objc_msgSend_914( _lib._class_NSURLCredential1, _lib._sel_credentialWithUser_password_persistence_1, user?._id ?? ffi.nullptr, @@ -63440,7 +63697,7 @@ class NSURLCredential extends NSObject { ffi.Pointer<__SecIdentity> identity, NSArray? certArray, int persistence) { - final _ret = _lib._objc_msgSend_901( + final _ret = _lib._objc_msgSend_915( _id, _lib._sel_initWithIdentity_certificates_persistence_1, identity, @@ -63454,7 +63711,7 @@ class NSURLCredential extends NSObject { ffi.Pointer<__SecIdentity> identity, NSArray? certArray, int persistence) { - final _ret = _lib._objc_msgSend_902( + final _ret = _lib._objc_msgSend_916( _lib._class_NSURLCredential1, _lib._sel_credentialWithIdentity_certificates_persistence_1, identity, @@ -63464,7 +63721,7 @@ class NSURLCredential extends NSObject { } ffi.Pointer<__SecIdentity> get identity { - return _lib._objc_msgSend_903(_id, _lib._sel_identity1); + return _lib._objc_msgSend_917(_id, _lib._sel_identity1); } NSArray? get certificates { @@ -63475,13 +63732,13 @@ class NSURLCredential extends NSObject { } NSURLCredential initWithTrust_(ffi.Pointer<__SecTrust> trust) { - final _ret = _lib._objc_msgSend_904(_id, _lib._sel_initWithTrust_1, trust); + final _ret = _lib._objc_msgSend_918(_id, _lib._sel_initWithTrust_1, trust); return NSURLCredential._(_ret, _lib, retain: true, release: true); } static NSURLCredential credentialForTrust_( SentryCocoa _lib, ffi.Pointer<__SecTrust> trust) { - final _ret = _lib._objc_msgSend_905( + final _ret = _lib._objc_msgSend_919( _lib._class_NSURLCredential1, _lib._sel_credentialForTrust_1, trust); return NSURLCredential._(_ret, _lib, retain: true, release: true); } @@ -63620,7 +63877,7 @@ class NSURLProtectionSpace extends NSObject { NSString? protocol, NSString? realm, NSString? authenticationMethod) { - final _ret = _lib._objc_msgSend_906( + final _ret = _lib._objc_msgSend_920( _id, _lib._sel_initWithHost_port_protocol_realm_authenticationMethod_1, host?._id ?? ffi.nullptr, @@ -63637,7 +63894,7 @@ class NSURLProtectionSpace extends NSObject { NSString? type, NSString? realm, NSString? authenticationMethod) { - final _ret = _lib._objc_msgSend_906( + final _ret = _lib._objc_msgSend_920( _id, _lib._sel_initWithProxyHost_port_type_realm_authenticationMethod_1, host?._id ?? ffi.nullptr, @@ -63703,7 +63960,7 @@ class NSURLProtectionSpace extends NSObject { } ffi.Pointer<__SecTrust> get serverTrust { - return _lib._objc_msgSend_907(_id, _lib._sel_serverTrust1); + return _lib._objc_msgSend_921(_id, _lib._sel_serverTrust1); } @override @@ -63825,7 +64082,7 @@ class NSURLCredentialStorage extends NSObject { } static NSURLCredentialStorage? getSharedCredentialStorage(SentryCocoa _lib) { - final _ret = _lib._objc_msgSend_908(_lib._class_NSURLCredentialStorage1, + final _ret = _lib._objc_msgSend_922(_lib._class_NSURLCredentialStorage1, _lib._sel_sharedCredentialStorage1); return _ret.address == 0 ? null @@ -63833,7 +64090,7 @@ class NSURLCredentialStorage extends NSObject { } NSDictionary credentialsForProtectionSpace_(NSURLProtectionSpace? space) { - final _ret = _lib._objc_msgSend_909(_id, + final _ret = _lib._objc_msgSend_923(_id, _lib._sel_credentialsForProtectionSpace_1, space?._id ?? ffi.nullptr); return NSDictionary._(_ret, _lib, retain: true, release: true); } @@ -63847,19 +64104,19 @@ class NSURLCredentialStorage extends NSObject { void setCredential_forProtectionSpace_( NSURLCredential? credential, NSURLProtectionSpace? space) { - _lib._objc_msgSend_910(_id, _lib._sel_setCredential_forProtectionSpace_1, + _lib._objc_msgSend_924(_id, _lib._sel_setCredential_forProtectionSpace_1, credential?._id ?? ffi.nullptr, space?._id ?? ffi.nullptr); } void removeCredential_forProtectionSpace_( NSURLCredential? credential, NSURLProtectionSpace? space) { - _lib._objc_msgSend_910(_id, _lib._sel_removeCredential_forProtectionSpace_1, + _lib._objc_msgSend_924(_id, _lib._sel_removeCredential_forProtectionSpace_1, credential?._id ?? ffi.nullptr, space?._id ?? ffi.nullptr); } void removeCredential_forProtectionSpace_options_(NSURLCredential? credential, NSURLProtectionSpace? space, NSDictionary? options) { - _lib._objc_msgSend_911( + _lib._objc_msgSend_925( _id, _lib._sel_removeCredential_forProtectionSpace_options_1, credential?._id ?? ffi.nullptr, @@ -63869,7 +64126,7 @@ class NSURLCredentialStorage extends NSObject { NSURLCredential defaultCredentialForProtectionSpace_( NSURLProtectionSpace? space) { - final _ret = _lib._objc_msgSend_912( + final _ret = _lib._objc_msgSend_926( _id, _lib._sel_defaultCredentialForProtectionSpace_1, space?._id ?? ffi.nullptr); @@ -63878,7 +64135,7 @@ class NSURLCredentialStorage extends NSObject { void setDefaultCredential_forProtectionSpace_( NSURLCredential? credential, NSURLProtectionSpace? space) { - _lib._objc_msgSend_910( + _lib._objc_msgSend_924( _id, _lib._sel_setDefaultCredential_forProtectionSpace_1, credential?._id ?? ffi.nullptr, @@ -63889,7 +64146,7 @@ class NSURLCredentialStorage extends NSObject { NSURLProtectionSpace? protectionSpace, NSURLSessionTask? task, ObjCBlock_ffiVoid_NSDictionary completionHandler) { - _lib._objc_msgSend_913( + _lib._objc_msgSend_927( _id, _lib._sel_getCredentialsForProtectionSpace_task_completionHandler_1, protectionSpace?._id ?? ffi.nullptr, @@ -63899,7 +64156,7 @@ class NSURLCredentialStorage extends NSObject { void setCredential_forProtectionSpace_task_(NSURLCredential? credential, NSURLProtectionSpace? protectionSpace, NSURLSessionTask? task) { - _lib._objc_msgSend_914( + _lib._objc_msgSend_928( _id, _lib._sel_setCredential_forProtectionSpace_task_1, credential?._id ?? ffi.nullptr, @@ -63912,7 +64169,7 @@ class NSURLCredentialStorage extends NSObject { NSURLProtectionSpace? protectionSpace, NSDictionary? options, NSURLSessionTask? task) { - _lib._objc_msgSend_915( + _lib._objc_msgSend_929( _id, _lib._sel_removeCredential_forProtectionSpace_options_task_1, credential?._id ?? ffi.nullptr, @@ -63925,7 +64182,7 @@ class NSURLCredentialStorage extends NSObject { NSURLProtectionSpace? space, NSURLSessionTask? task, ObjCBlock_ffiVoid_NSURLCredential completionHandler) { - _lib._objc_msgSend_916( + _lib._objc_msgSend_930( _id, _lib._sel_getDefaultCredentialForProtectionSpace_task_completionHandler_1, space?._id ?? ffi.nullptr, @@ -63937,7 +64194,7 @@ class NSURLCredentialStorage extends NSObject { NSURLCredential? credential, NSURLProtectionSpace? protectionSpace, NSURLSessionTask? task) { - _lib._objc_msgSend_914( + _lib._objc_msgSend_928( _id, _lib._sel_setDefaultCredential_forProtectionSpace_task_1, credential?._id ?? ffi.nullptr, @@ -64204,7 +64461,7 @@ class NSURLProtocol extends NSObject { NSURLProtocol initWithRequest_cachedResponse_client_(NSURLRequest? request, NSCachedURLResponse? cachedResponse, NSObject? client) { - final _ret = _lib._objc_msgSend_917( + final _ret = _lib._objc_msgSend_931( _id, _lib._sel_initWithRequest_cachedResponse_client_1, request?._id ?? ffi.nullptr, @@ -64221,34 +64478,34 @@ class NSURLProtocol extends NSObject { } NSURLRequest? get request { - final _ret = _lib._objc_msgSend_795(_id, _lib._sel_request1); + final _ret = _lib._objc_msgSend_799(_id, _lib._sel_request1); return _ret.address == 0 ? null : NSURLRequest._(_ret, _lib, retain: true, release: true); } NSCachedURLResponse? get cachedResponse { - final _ret = _lib._objc_msgSend_918(_id, _lib._sel_cachedResponse1); + final _ret = _lib._objc_msgSend_932(_id, _lib._sel_cachedResponse1); return _ret.address == 0 ? null : NSCachedURLResponse._(_ret, _lib, retain: true, release: true); } static bool canInitWithRequest_(SentryCocoa _lib, NSURLRequest? request) { - return _lib._objc_msgSend_895(_lib._class_NSURLProtocol1, + return _lib._objc_msgSend_909(_lib._class_NSURLProtocol1, _lib._sel_canInitWithRequest_1, request?._id ?? ffi.nullptr); } static NSURLRequest canonicalRequestForRequest_( SentryCocoa _lib, NSURLRequest? request) { - final _ret = _lib._objc_msgSend_919(_lib._class_NSURLProtocol1, + final _ret = _lib._objc_msgSend_933(_lib._class_NSURLProtocol1, _lib._sel_canonicalRequestForRequest_1, request?._id ?? ffi.nullptr); return NSURLRequest._(_ret, _lib, retain: true, release: true); } static bool requestIsCacheEquivalent_toRequest_( SentryCocoa _lib, NSURLRequest? a, NSURLRequest? b) { - return _lib._objc_msgSend_920( + return _lib._objc_msgSend_934( _lib._class_NSURLProtocol1, _lib._sel_requestIsCacheEquivalent_toRequest_1, a?._id ?? ffi.nullptr, @@ -64265,7 +64522,7 @@ class NSURLProtocol extends NSObject { static NSObject propertyForKey_inRequest_( SentryCocoa _lib, NSString? key, NSURLRequest? request) { - final _ret = _lib._objc_msgSend_921( + final _ret = _lib._objc_msgSend_935( _lib._class_NSURLProtocol1, _lib._sel_propertyForKey_inRequest_1, key?._id ?? ffi.nullptr, @@ -64275,7 +64532,7 @@ class NSURLProtocol extends NSObject { static void setProperty_forKey_inRequest_(SentryCocoa _lib, NSObject value, NSString? key, NSMutableURLRequest? request) { - _lib._objc_msgSend_927( + _lib._objc_msgSend_941( _lib._class_NSURLProtocol1, _lib._sel_setProperty_forKey_inRequest_1, value._id, @@ -64285,7 +64542,7 @@ class NSURLProtocol extends NSObject { static void removePropertyForKey_inRequest_( SentryCocoa _lib, NSString? key, NSMutableURLRequest? request) { - _lib._objc_msgSend_928( + _lib._objc_msgSend_942( _lib._class_NSURLProtocol1, _lib._sel_removePropertyForKey_inRequest_1, key?._id ?? ffi.nullptr, @@ -64303,13 +64560,13 @@ class NSURLProtocol extends NSObject { } static bool canInitWithTask_(SentryCocoa _lib, NSURLSessionTask? task) { - return _lib._objc_msgSend_929(_lib._class_NSURLProtocol1, + return _lib._objc_msgSend_943(_lib._class_NSURLProtocol1, _lib._sel_canInitWithTask_1, task?._id ?? ffi.nullptr); } NSURLProtocol initWithTask_cachedResponse_client_(NSURLSessionTask? task, NSCachedURLResponse? cachedResponse, NSObject? client) { - final _ret = _lib._objc_msgSend_930( + final _ret = _lib._objc_msgSend_944( _id, _lib._sel_initWithTask_cachedResponse_client_1, task?._id ?? ffi.nullptr, @@ -64319,7 +64576,7 @@ class NSURLProtocol extends NSObject { } NSURLSessionTask? get task { - final _ret = _lib._objc_msgSend_931(_id, _lib._sel_task1); + final _ret = _lib._objc_msgSend_945(_id, _lib._sel_task1); return _ret.address == 0 ? null : NSURLSessionTask._(_ret, _lib, retain: true, release: true); @@ -64457,11 +64714,11 @@ class NSMutableURLRequest extends NSURLRequest { @override int get cachePolicy { - return _lib._objc_msgSend_782(_id, _lib._sel_cachePolicy1); + return _lib._objc_msgSend_786(_id, _lib._sel_cachePolicy1); } set cachePolicy(int value) { - return _lib._objc_msgSend_922(_id, _lib._sel_setCachePolicy_1, value); + return _lib._objc_msgSend_936(_id, _lib._sel_setCachePolicy_1, value); } @override @@ -64488,11 +64745,11 @@ class NSMutableURLRequest extends NSURLRequest { @override int get networkServiceType { - return _lib._objc_msgSend_783(_id, _lib._sel_networkServiceType1); + return _lib._objc_msgSend_787(_id, _lib._sel_networkServiceType1); } set networkServiceType(int value) { - return _lib._objc_msgSend_923( + return _lib._objc_msgSend_937( _id, _lib._sel_setNetworkServiceType_1, value); } @@ -64539,11 +64796,11 @@ class NSMutableURLRequest extends NSURLRequest { @override int get attribution { - return _lib._objc_msgSend_784(_id, _lib._sel_attribution1); + return _lib._objc_msgSend_788(_id, _lib._sel_attribution1); } set attribution(int value) { - return _lib._objc_msgSend_924(_id, _lib._sel_setAttribution_1, value); + return _lib._objc_msgSend_938(_id, _lib._sel_setAttribution_1, value); } @override @@ -64601,20 +64858,20 @@ class NSMutableURLRequest extends NSURLRequest { } set HTTPBody(NSData? value) { - return _lib._objc_msgSend_925( + return _lib._objc_msgSend_939( _id, _lib._sel_setHTTPBody_1, value?._id ?? ffi.nullptr); } @override NSInputStream? get HTTPBodyStream { - final _ret = _lib._objc_msgSend_794(_id, _lib._sel_HTTPBodyStream1); + final _ret = _lib._objc_msgSend_798(_id, _lib._sel_HTTPBodyStream1); return _ret.address == 0 ? null : NSInputStream._(_ret, _lib, retain: true, release: true); } set HTTPBodyStream(NSInputStream? value) { - return _lib._objc_msgSend_926( + return _lib._objc_msgSend_940( _id, _lib._sel_setHTTPBodyStream_1, value?._id ?? ffi.nullptr); } @@ -64651,7 +64908,7 @@ class NSMutableURLRequest extends NSURLRequest { static NSMutableURLRequest requestWithURL_cachePolicy_timeoutInterval_( SentryCocoa _lib, NSURL? URL, int cachePolicy, double timeoutInterval) { - final _ret = _lib._objc_msgSend_781( + final _ret = _lib._objc_msgSend_785( _lib._class_NSMutableURLRequest1, _lib._sel_requestWithURL_cachePolicy_timeoutInterval_1, URL?._id ?? ffi.nullptr, @@ -64670,7 +64927,7 @@ class NSMutableURLRequest extends NSURLRequest { @override NSMutableURLRequest initWithURL_cachePolicy_timeoutInterval_( NSURL? URL, int cachePolicy, double timeoutInterval) { - final _ret = _lib._objc_msgSend_781( + final _ret = _lib._objc_msgSend_785( _id, _lib._sel_initWithURL_cachePolicy_timeoutInterval_1, URL?._id ?? ffi.nullptr, @@ -64808,7 +65065,7 @@ class NSXMLParser extends NSObject { } NSXMLParser initWithStream_(NSInputStream? stream) { - final _ret = _lib._objc_msgSend_932( + final _ret = _lib._objc_msgSend_946( _id, _lib._sel_initWithStream_1, stream?._id ?? ffi.nullptr); return NSXMLParser._(_ret, _lib, retain: true, release: true); } @@ -64844,12 +65101,12 @@ class NSXMLParser extends NSObject { } int get externalEntityResolvingPolicy { - return _lib._objc_msgSend_933( + return _lib._objc_msgSend_947( _id, _lib._sel_externalEntityResolvingPolicy1); } set externalEntityResolvingPolicy(int value) { - return _lib._objc_msgSend_934( + return _lib._objc_msgSend_948( _id, _lib._sel_setExternalEntityResolvingPolicy_1, value); } @@ -64862,7 +65119,7 @@ class NSXMLParser extends NSObject { } set allowedExternalEntityURLs(NSSet? value) { - return _lib._objc_msgSend_935(_id, _lib._sel_setAllowedExternalEntityURLs_1, + return _lib._objc_msgSend_949(_id, _lib._sel_setAllowedExternalEntityURLs_1, value?._id ?? ffi.nullptr); } @@ -65036,7 +65293,7 @@ class NSFileWrapper extends NSObject { NSFileWrapper initWithURL_options_error_( NSURL? url, int options, ffi.Pointer> outError) { - final _ret = _lib._objc_msgSend_936( + final _ret = _lib._objc_msgSend_950( _id, _lib._sel_initWithURL_options_error_1, url?._id ?? ffi.nullptr, @@ -65138,7 +65395,7 @@ class NSFileWrapper extends NSObject { bool readFromURL_options_error_( NSURL? url, int options, ffi.Pointer> outError) { - return _lib._objc_msgSend_937(_id, _lib._sel_readFromURL_options_error_1, + return _lib._objc_msgSend_951(_id, _lib._sel_readFromURL_options_error_1, url?._id ?? ffi.nullptr, options, outError); } @@ -65147,7 +65404,7 @@ class NSFileWrapper extends NSObject { int options, NSURL? originalContentsURL, ffi.Pointer> outError) { - return _lib._objc_msgSend_938( + return _lib._objc_msgSend_952( _id, _lib._sel_writeToURL_options_originalContentsURL_error_1, url?._id ?? ffi.nullptr, @@ -65165,14 +65422,14 @@ class NSFileWrapper extends NSObject { } NSString addFileWrapper_(NSFileWrapper? child) { - final _ret = _lib._objc_msgSend_939( + final _ret = _lib._objc_msgSend_953( _id, _lib._sel_addFileWrapper_1, child?._id ?? ffi.nullptr); return NSString._(_ret, _lib, retain: true, release: true); } NSString addRegularFileWithContents_preferredFilename_( NSData? data, NSString? fileName) { - final _ret = _lib._objc_msgSend_940( + final _ret = _lib._objc_msgSend_954( _id, _lib._sel_addRegularFileWithContents_preferredFilename_1, data?._id ?? ffi.nullptr, @@ -65181,7 +65438,7 @@ class NSFileWrapper extends NSObject { } void removeFileWrapper_(NSFileWrapper? child) { - _lib._objc_msgSend_941( + _lib._objc_msgSend_955( _id, _lib._sel_removeFileWrapper_1, child?._id ?? ffi.nullptr); } @@ -65193,7 +65450,7 @@ class NSFileWrapper extends NSObject { } NSString keyForFileWrapper_(NSFileWrapper? child) { - final _ret = _lib._objc_msgSend_939( + final _ret = _lib._objc_msgSend_953( _id, _lib._sel_keyForFileWrapper_1, child?._id ?? ffi.nullptr); return NSString._(_ret, _lib, retain: true, release: true); } @@ -65237,7 +65494,7 @@ class NSFileWrapper extends NSObject { bool writeToFile_atomically_updateFilenames_( NSString? path, bool atomicFlag, bool updateFilenamesFlag) { - return _lib._objc_msgSend_942( + return _lib._objc_msgSend_956( _id, _lib._sel_writeToFile_atomically_updateFilenames_1, path?._id ?? ffi.nullptr, @@ -65393,7 +65650,7 @@ class NSURLSession extends NSObject { } static NSURLSession? getSharedSession(SentryCocoa _lib) { - final _ret = _lib._objc_msgSend_943( + final _ret = _lib._objc_msgSend_957( _lib._class_NSURLSession1, _lib._sel_sharedSession1); return _ret.address == 0 ? null @@ -65402,7 +65659,7 @@ class NSURLSession extends NSObject { static NSURLSession sessionWithConfiguration_( SentryCocoa _lib, NSURLSessionConfiguration? configuration) { - final _ret = _lib._objc_msgSend_954( + final _ret = _lib._objc_msgSend_968( _lib._class_NSURLSession1, _lib._sel_sessionWithConfiguration_1, configuration?._id ?? ffi.nullptr); @@ -65414,7 +65671,7 @@ class NSURLSession extends NSObject { NSURLSessionConfiguration? configuration, NSObject? delegate, NSOperationQueue? queue) { - final _ret = _lib._objc_msgSend_955( + final _ret = _lib._objc_msgSend_969( _lib._class_NSURLSession1, _lib._sel_sessionWithConfiguration_delegate_delegateQueue_1, configuration?._id ?? ffi.nullptr, @@ -65424,7 +65681,7 @@ class NSURLSession extends NSObject { } NSOperationQueue? get delegateQueue { - final _ret = _lib._objc_msgSend_824(_id, _lib._sel_delegateQueue1); + final _ret = _lib._objc_msgSend_838(_id, _lib._sel_delegateQueue1); return _ret.address == 0 ? null : NSOperationQueue._(_ret, _lib, retain: true, release: true); @@ -65438,7 +65695,7 @@ class NSURLSession extends NSObject { } NSURLSessionConfiguration? get configuration { - final _ret = _lib._objc_msgSend_944(_id, _lib._sel_configuration1); + final _ret = _lib._objc_msgSend_958(_id, _lib._sel_configuration1); return _ret.address == 0 ? null : NSURLSessionConfiguration._(_ret, _lib, retain: true, release: true); @@ -65476,31 +65733,31 @@ class NSURLSession extends NSObject { void getTasksWithCompletionHandler_( ObjCBlock_ffiVoid_NSArray_NSArray_NSArray completionHandler) { - _lib._objc_msgSend_956( + _lib._objc_msgSend_970( _id, _lib._sel_getTasksWithCompletionHandler_1, completionHandler._id); } void getAllTasksWithCompletionHandler_( ObjCBlock_ffiVoid_NSArray completionHandler) { - _lib._objc_msgSend_957(_id, _lib._sel_getAllTasksWithCompletionHandler_1, + _lib._objc_msgSend_971(_id, _lib._sel_getAllTasksWithCompletionHandler_1, completionHandler._id); } NSURLSessionDataTask dataTaskWithRequest_(NSURLRequest? request) { - final _ret = _lib._objc_msgSend_958( + final _ret = _lib._objc_msgSend_972( _id, _lib._sel_dataTaskWithRequest_1, request?._id ?? ffi.nullptr); return NSURLSessionDataTask._(_ret, _lib, retain: true, release: true); } NSURLSessionDataTask dataTaskWithURL_(NSURL? url) { - final _ret = _lib._objc_msgSend_959( + final _ret = _lib._objc_msgSend_973( _id, _lib._sel_dataTaskWithURL_1, url?._id ?? ffi.nullptr); return NSURLSessionDataTask._(_ret, _lib, retain: true, release: true); } NSURLSessionUploadTask uploadTaskWithRequest_fromFile_( NSURLRequest? request, NSURL? fileURL) { - final _ret = _lib._objc_msgSend_960( + final _ret = _lib._objc_msgSend_975( _id, _lib._sel_uploadTaskWithRequest_fromFile_1, request?._id ?? ffi.nullptr, @@ -65510,7 +65767,7 @@ class NSURLSession extends NSObject { NSURLSessionUploadTask uploadTaskWithRequest_fromData_( NSURLRequest? request, NSData? bodyData) { - final _ret = _lib._objc_msgSend_961( + final _ret = _lib._objc_msgSend_976( _id, _lib._sel_uploadTaskWithRequest_fromData_1, request?._id ?? ffi.nullptr, @@ -65518,33 +65775,39 @@ class NSURLSession extends NSObject { return NSURLSessionUploadTask._(_ret, _lib, retain: true, release: true); } + NSURLSessionUploadTask uploadTaskWithResumeData_(NSData? resumeData) { + final _ret = _lib._objc_msgSend_977(_id, + _lib._sel_uploadTaskWithResumeData_1, resumeData?._id ?? ffi.nullptr); + return NSURLSessionUploadTask._(_ret, _lib, retain: true, release: true); + } + NSURLSessionUploadTask uploadTaskWithStreamedRequest_(NSURLRequest? request) { - final _ret = _lib._objc_msgSend_962(_id, + final _ret = _lib._objc_msgSend_978(_id, _lib._sel_uploadTaskWithStreamedRequest_1, request?._id ?? ffi.nullptr); return NSURLSessionUploadTask._(_ret, _lib, retain: true, release: true); } NSURLSessionDownloadTask downloadTaskWithRequest_(NSURLRequest? request) { - final _ret = _lib._objc_msgSend_964( + final _ret = _lib._objc_msgSend_979( _id, _lib._sel_downloadTaskWithRequest_1, request?._id ?? ffi.nullptr); return NSURLSessionDownloadTask._(_ret, _lib, retain: true, release: true); } NSURLSessionDownloadTask downloadTaskWithURL_(NSURL? url) { - final _ret = _lib._objc_msgSend_965( + final _ret = _lib._objc_msgSend_980( _id, _lib._sel_downloadTaskWithURL_1, url?._id ?? ffi.nullptr); return NSURLSessionDownloadTask._(_ret, _lib, retain: true, release: true); } NSURLSessionDownloadTask downloadTaskWithResumeData_(NSData? resumeData) { - final _ret = _lib._objc_msgSend_966(_id, + final _ret = _lib._objc_msgSend_981(_id, _lib._sel_downloadTaskWithResumeData_1, resumeData?._id ?? ffi.nullptr); return NSURLSessionDownloadTask._(_ret, _lib, retain: true, release: true); } NSURLSessionStreamTask streamTaskWithHostName_port_( NSString? hostname, int port) { - final _ret = _lib._objc_msgSend_969( + final _ret = _lib._objc_msgSend_984( _id, _lib._sel_streamTaskWithHostName_port_1, hostname?._id ?? ffi.nullptr, @@ -65553,20 +65816,20 @@ class NSURLSession extends NSObject { } NSURLSessionStreamTask streamTaskWithNetService_(NSNetService? service) { - final _ret = _lib._objc_msgSend_975( + final _ret = _lib._objc_msgSend_990( _id, _lib._sel_streamTaskWithNetService_1, service?._id ?? ffi.nullptr); return NSURLSessionStreamTask._(_ret, _lib, retain: true, release: true); } NSURLSessionWebSocketTask webSocketTaskWithURL_(NSURL? url) { - final _ret = _lib._objc_msgSend_982( + final _ret = _lib._objc_msgSend_997( _id, _lib._sel_webSocketTaskWithURL_1, url?._id ?? ffi.nullptr); return NSURLSessionWebSocketTask._(_ret, _lib, retain: true, release: true); } NSURLSessionWebSocketTask webSocketTaskWithURL_protocols_( NSURL? url, NSArray? protocols) { - final _ret = _lib._objc_msgSend_983( + final _ret = _lib._objc_msgSend_998( _id, _lib._sel_webSocketTaskWithURL_protocols_1, url?._id ?? ffi.nullptr, @@ -65575,7 +65838,7 @@ class NSURLSession extends NSObject { } NSURLSessionWebSocketTask webSocketTaskWithRequest_(NSURLRequest? request) { - final _ret = _lib._objc_msgSend_984( + final _ret = _lib._objc_msgSend_999( _id, _lib._sel_webSocketTaskWithRequest_1, request?._id ?? ffi.nullptr); return NSURLSessionWebSocketTask._(_ret, _lib, retain: true, release: true); } @@ -65595,7 +65858,7 @@ class NSURLSession extends NSObject { NSURLSessionDataTask dataTaskWithRequest_completionHandler_( NSURLRequest? request, ObjCBlock_ffiVoid_NSData_NSURLResponse_NSError completionHandler) { - final _ret = _lib._objc_msgSend_985( + final _ret = _lib._objc_msgSend_1000( _id, _lib._sel_dataTaskWithRequest_completionHandler_1, request?._id ?? ffi.nullptr, @@ -65605,7 +65868,7 @@ class NSURLSession extends NSObject { NSURLSessionDataTask dataTaskWithURL_completionHandler_(NSURL? url, ObjCBlock_ffiVoid_NSData_NSURLResponse_NSError completionHandler) { - final _ret = _lib._objc_msgSend_986( + final _ret = _lib._objc_msgSend_1001( _id, _lib._sel_dataTaskWithURL_completionHandler_1, url?._id ?? ffi.nullptr, @@ -65617,7 +65880,7 @@ class NSURLSession extends NSObject { NSURLRequest? request, NSURL? fileURL, ObjCBlock_ffiVoid_NSData_NSURLResponse_NSError completionHandler) { - final _ret = _lib._objc_msgSend_987( + final _ret = _lib._objc_msgSend_1002( _id, _lib._sel_uploadTaskWithRequest_fromFile_completionHandler_1, request?._id ?? ffi.nullptr, @@ -65630,7 +65893,7 @@ class NSURLSession extends NSObject { NSURLRequest? request, NSData? bodyData, ObjCBlock_ffiVoid_NSData_NSURLResponse_NSError completionHandler) { - final _ret = _lib._objc_msgSend_988( + final _ret = _lib._objc_msgSend_1003( _id, _lib._sel_uploadTaskWithRequest_fromData_completionHandler_1, request?._id ?? ffi.nullptr, @@ -65639,10 +65902,21 @@ class NSURLSession extends NSObject { return NSURLSessionUploadTask._(_ret, _lib, retain: true, release: true); } + NSURLSessionUploadTask uploadTaskWithResumeData_completionHandler_( + NSData? resumeData, + ObjCBlock_ffiVoid_NSData_NSURLResponse_NSError completionHandler) { + final _ret = _lib._objc_msgSend_1004( + _id, + _lib._sel_uploadTaskWithResumeData_completionHandler_1, + resumeData?._id ?? ffi.nullptr, + completionHandler._id); + return NSURLSessionUploadTask._(_ret, _lib, retain: true, release: true); + } + NSURLSessionDownloadTask downloadTaskWithRequest_completionHandler_( NSURLRequest? request, ObjCBlock_ffiVoid_NSURL_NSURLResponse_NSError completionHandler) { - final _ret = _lib._objc_msgSend_989( + final _ret = _lib._objc_msgSend_1005( _id, _lib._sel_downloadTaskWithRequest_completionHandler_1, request?._id ?? ffi.nullptr, @@ -65652,7 +65926,7 @@ class NSURLSession extends NSObject { NSURLSessionDownloadTask downloadTaskWithURL_completionHandler_(NSURL? url, ObjCBlock_ffiVoid_NSURL_NSURLResponse_NSError completionHandler) { - final _ret = _lib._objc_msgSend_990( + final _ret = _lib._objc_msgSend_1006( _id, _lib._sel_downloadTaskWithURL_completionHandler_1, url?._id ?? ffi.nullptr, @@ -65663,7 +65937,7 @@ class NSURLSession extends NSObject { NSURLSessionDownloadTask downloadTaskWithResumeData_completionHandler_( NSData? resumeData, ObjCBlock_ffiVoid_NSURL_NSURLResponse_NSError completionHandler) { - final _ret = _lib._objc_msgSend_991( + final _ret = _lib._objc_msgSend_1007( _id, _lib._sel_downloadTaskWithResumeData_completionHandler_1, resumeData?._id ?? ffi.nullptr, @@ -65779,7 +66053,7 @@ class NSURLSessionConfiguration extends NSObject { static NSURLSessionConfiguration? getDefaultSessionConfiguration( SentryCocoa _lib) { - final _ret = _lib._objc_msgSend_944(_lib._class_NSURLSessionConfiguration1, + final _ret = _lib._objc_msgSend_958(_lib._class_NSURLSessionConfiguration1, _lib._sel_defaultSessionConfiguration1); return _ret.address == 0 ? null @@ -65788,7 +66062,7 @@ class NSURLSessionConfiguration extends NSObject { static NSURLSessionConfiguration? getEphemeralSessionConfiguration( SentryCocoa _lib) { - final _ret = _lib._objc_msgSend_944(_lib._class_NSURLSessionConfiguration1, + final _ret = _lib._objc_msgSend_958(_lib._class_NSURLSessionConfiguration1, _lib._sel_ephemeralSessionConfiguration1); return _ret.address == 0 ? null @@ -65798,7 +66072,7 @@ class NSURLSessionConfiguration extends NSObject { static NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier_( SentryCocoa _lib, NSString? identifier) { - final _ret = _lib._objc_msgSend_945( + final _ret = _lib._objc_msgSend_959( _lib._class_NSURLSessionConfiguration1, _lib._sel_backgroundSessionConfigurationWithIdentifier_1, identifier?._id ?? ffi.nullptr); @@ -65813,11 +66087,11 @@ class NSURLSessionConfiguration extends NSObject { } int get requestCachePolicy { - return _lib._objc_msgSend_782(_id, _lib._sel_requestCachePolicy1); + return _lib._objc_msgSend_786(_id, _lib._sel_requestCachePolicy1); } set requestCachePolicy(int value) { - return _lib._objc_msgSend_922( + return _lib._objc_msgSend_936( _id, _lib._sel_setRequestCachePolicy_1, value); } @@ -65840,11 +66114,11 @@ class NSURLSessionConfiguration extends NSObject { } int get networkServiceType { - return _lib._objc_msgSend_783(_id, _lib._sel_networkServiceType1); + return _lib._objc_msgSend_787(_id, _lib._sel_networkServiceType1); } set networkServiceType(int value) { - return _lib._objc_msgSend_923( + return _lib._objc_msgSend_937( _id, _lib._sel_setNetworkServiceType_1, value); } @@ -65938,40 +66212,40 @@ class NSURLSessionConfiguration extends NSObject { } int get TLSMinimumSupportedProtocol { - return _lib._objc_msgSend_946(_id, _lib._sel_TLSMinimumSupportedProtocol1); + return _lib._objc_msgSend_960(_id, _lib._sel_TLSMinimumSupportedProtocol1); } set TLSMinimumSupportedProtocol(int value) { - return _lib._objc_msgSend_947( + return _lib._objc_msgSend_961( _id, _lib._sel_setTLSMinimumSupportedProtocol_1, value); } int get TLSMaximumSupportedProtocol { - return _lib._objc_msgSend_946(_id, _lib._sel_TLSMaximumSupportedProtocol1); + return _lib._objc_msgSend_960(_id, _lib._sel_TLSMaximumSupportedProtocol1); } set TLSMaximumSupportedProtocol(int value) { - return _lib._objc_msgSend_947( + return _lib._objc_msgSend_961( _id, _lib._sel_setTLSMaximumSupportedProtocol_1, value); } int get TLSMinimumSupportedProtocolVersion { - return _lib._objc_msgSend_948( + return _lib._objc_msgSend_962( _id, _lib._sel_TLSMinimumSupportedProtocolVersion1); } set TLSMinimumSupportedProtocolVersion(int value) { - return _lib._objc_msgSend_949( + return _lib._objc_msgSend_963( _id, _lib._sel_setTLSMinimumSupportedProtocolVersion_1, value); } int get TLSMaximumSupportedProtocolVersion { - return _lib._objc_msgSend_948( + return _lib._objc_msgSend_962( _id, _lib._sel_TLSMaximumSupportedProtocolVersion1); } set TLSMaximumSupportedProtocolVersion(int value) { - return _lib._objc_msgSend_949( + return _lib._objc_msgSend_963( _id, _lib._sel_setTLSMaximumSupportedProtocolVersion_1, value); } @@ -65994,11 +66268,11 @@ class NSURLSessionConfiguration extends NSObject { } int get HTTPCookieAcceptPolicy { - return _lib._objc_msgSend_779(_id, _lib._sel_HTTPCookieAcceptPolicy1); + return _lib._objc_msgSend_783(_id, _lib._sel_HTTPCookieAcceptPolicy1); } set HTTPCookieAcceptPolicy(int value) { - return _lib._objc_msgSend_780( + return _lib._objc_msgSend_784( _id, _lib._sel_setHTTPCookieAcceptPolicy_1, value); } @@ -66024,38 +66298,38 @@ class NSURLSessionConfiguration extends NSObject { } NSHTTPCookieStorage? get HTTPCookieStorage { - final _ret = _lib._objc_msgSend_773(_id, _lib._sel_HTTPCookieStorage1); + final _ret = _lib._objc_msgSend_777(_id, _lib._sel_HTTPCookieStorage1); return _ret.address == 0 ? null : NSHTTPCookieStorage._(_ret, _lib, retain: true, release: true); } set HTTPCookieStorage(NSHTTPCookieStorage? value) { - return _lib._objc_msgSend_950( + return _lib._objc_msgSend_964( _id, _lib._sel_setHTTPCookieStorage_1, value?._id ?? ffi.nullptr); } NSURLCredentialStorage? get URLCredentialStorage { - final _ret = _lib._objc_msgSend_908(_id, _lib._sel_URLCredentialStorage1); + final _ret = _lib._objc_msgSend_922(_id, _lib._sel_URLCredentialStorage1); return _ret.address == 0 ? null : NSURLCredentialStorage._(_ret, _lib, retain: true, release: true); } set URLCredentialStorage(NSURLCredentialStorage? value) { - return _lib._objc_msgSend_951( + return _lib._objc_msgSend_965( _id, _lib._sel_setURLCredentialStorage_1, value?._id ?? ffi.nullptr); } NSURLCache? get URLCache { - final _ret = _lib._objc_msgSend_878(_id, _lib._sel_URLCache1); + final _ret = _lib._objc_msgSend_892(_id, _lib._sel_URLCache1); return _ret.address == 0 ? null : NSURLCache._(_ret, _lib, retain: true, release: true); } set URLCache(NSURLCache? value) { - return _lib._objc_msgSend_879( + return _lib._objc_msgSend_893( _id, _lib._sel_setURLCache_1, value?._id ?? ffi.nullptr); } @@ -66077,16 +66351,16 @@ class NSURLSessionConfiguration extends NSObject { } set protocolClasses(NSArray? value) { - return _lib._objc_msgSend_731( + return _lib._objc_msgSend_735( _id, _lib._sel_setProtocolClasses_1, value?._id ?? ffi.nullptr); } int get multipathServiceType { - return _lib._objc_msgSend_952(_id, _lib._sel_multipathServiceType1); + return _lib._objc_msgSend_966(_id, _lib._sel_multipathServiceType1); } set multipathServiceType(int value) { - return _lib._objc_msgSend_953( + return _lib._objc_msgSend_967( _id, _lib._sel_setMultipathServiceType_1, value); } @@ -66105,7 +66379,7 @@ class NSURLSessionConfiguration extends NSObject { static NSURLSessionConfiguration backgroundSessionConfiguration_( SentryCocoa _lib, NSString? identifier) { - final _ret = _lib._objc_msgSend_945( + final _ret = _lib._objc_msgSend_959( _lib._class_NSURLSessionConfiguration1, _lib._sel_backgroundSessionConfiguration_1, identifier?._id ?? ffi.nullptr); @@ -66371,6 +66645,12 @@ class NSURLSessionUploadTask extends NSURLSessionDataTask { return NSURLSessionUploadTask._(_ret, _lib, retain: false, release: true); } + void cancelByProducingResumeData_( + ObjCBlock_ffiVoid_NSData completionHandler) { + _lib._objc_msgSend_974( + _id, _lib._sel_cancelByProducingResumeData_1, completionHandler._id); + } + static NSURLSessionUploadTask allocWithZone_( SentryCocoa _lib, ffi.Pointer<_NSZone> zone) { final _ret = _lib._objc_msgSend_3( @@ -66452,6 +66732,75 @@ class NSURLSessionUploadTask extends NSURLSessionDataTask { } } +void _ObjCBlock_ffiVoid_NSData_fnPtrTrampoline( + ffi.Pointer<_ObjCBlock> block, ffi.Pointer arg0) { + return block.ref.target + .cast< + ffi.NativeFunction arg0)>>() + .asFunction arg0)>()(arg0); +} + +final _ObjCBlock_ffiVoid_NSData_closureRegistry = {}; +int _ObjCBlock_ffiVoid_NSData_closureRegistryIndex = 0; +ffi.Pointer _ObjCBlock_ffiVoid_NSData_registerClosure(Function fn) { + final id = ++_ObjCBlock_ffiVoid_NSData_closureRegistryIndex; + _ObjCBlock_ffiVoid_NSData_closureRegistry[id] = fn; + return ffi.Pointer.fromAddress(id); +} + +void _ObjCBlock_ffiVoid_NSData_closureTrampoline( + ffi.Pointer<_ObjCBlock> block, ffi.Pointer arg0) { + return (_ObjCBlock_ffiVoid_NSData_closureRegistry[block.ref.target.address] + as void Function(ffi.Pointer))(arg0); +} + +class ObjCBlock_ffiVoid_NSData extends _ObjCBlockBase { + ObjCBlock_ffiVoid_NSData._(ffi.Pointer<_ObjCBlock> id, SentryCocoa lib) + : super._(id, lib, retain: false, release: true); + + /// Creates a block from a C function pointer. + ObjCBlock_ffiVoid_NSData.fromFunctionPointer( + SentryCocoa lib, + ffi.Pointer< + ffi + .NativeFunction arg0)>> + ptr) + : this._( + lib._newBlock1( + _cFuncTrampoline ??= ffi.Pointer.fromFunction< + ffi.Void Function(ffi.Pointer<_ObjCBlock> block, + ffi.Pointer arg0)>( + _ObjCBlock_ffiVoid_NSData_fnPtrTrampoline) + .cast(), + ptr.cast()), + lib); + static ffi.Pointer? _cFuncTrampoline; + + /// Creates a block from a Dart function. + ObjCBlock_ffiVoid_NSData.fromFunction( + SentryCocoa lib, void Function(ffi.Pointer arg0) fn) + : this._( + lib._newBlock1( + _dartFuncTrampoline ??= ffi.Pointer.fromFunction< + ffi.Void Function(ffi.Pointer<_ObjCBlock> block, + ffi.Pointer arg0)>( + _ObjCBlock_ffiVoid_NSData_closureTrampoline) + .cast(), + _ObjCBlock_ffiVoid_NSData_registerClosure(fn)), + lib); + static ffi.Pointer? _dartFuncTrampoline; + void call(ffi.Pointer arg0) { + return _id.ref.invoke + .cast< + ffi.NativeFunction< + ffi.Void Function(ffi.Pointer<_ObjCBlock> block, + ffi.Pointer arg0)>>() + .asFunction< + void Function(ffi.Pointer<_ObjCBlock> block, + ffi.Pointer arg0)>()(_id, arg0); + } +} + class NSURLSessionDownloadTask extends NSURLSessionTask { NSURLSessionDownloadTask._(ffi.Pointer id, SentryCocoa lib, {bool retain = false, bool release = false}) @@ -66479,7 +66828,7 @@ class NSURLSessionDownloadTask extends NSURLSessionTask { void cancelByProducingResumeData_( ObjCBlock_ffiVoid_NSData completionHandler) { - _lib._objc_msgSend_963( + _lib._objc_msgSend_974( _id, _lib._sel_cancelByProducingResumeData_1, completionHandler._id); } @@ -66576,75 +66925,6 @@ class NSURLSessionDownloadTask extends NSURLSessionTask { } } -void _ObjCBlock_ffiVoid_NSData_fnPtrTrampoline( - ffi.Pointer<_ObjCBlock> block, ffi.Pointer arg0) { - return block.ref.target - .cast< - ffi.NativeFunction arg0)>>() - .asFunction arg0)>()(arg0); -} - -final _ObjCBlock_ffiVoid_NSData_closureRegistry = {}; -int _ObjCBlock_ffiVoid_NSData_closureRegistryIndex = 0; -ffi.Pointer _ObjCBlock_ffiVoid_NSData_registerClosure(Function fn) { - final id = ++_ObjCBlock_ffiVoid_NSData_closureRegistryIndex; - _ObjCBlock_ffiVoid_NSData_closureRegistry[id] = fn; - return ffi.Pointer.fromAddress(id); -} - -void _ObjCBlock_ffiVoid_NSData_closureTrampoline( - ffi.Pointer<_ObjCBlock> block, ffi.Pointer arg0) { - return (_ObjCBlock_ffiVoid_NSData_closureRegistry[block.ref.target.address] - as void Function(ffi.Pointer))(arg0); -} - -class ObjCBlock_ffiVoid_NSData extends _ObjCBlockBase { - ObjCBlock_ffiVoid_NSData._(ffi.Pointer<_ObjCBlock> id, SentryCocoa lib) - : super._(id, lib, retain: false, release: true); - - /// Creates a block from a C function pointer. - ObjCBlock_ffiVoid_NSData.fromFunctionPointer( - SentryCocoa lib, - ffi.Pointer< - ffi - .NativeFunction arg0)>> - ptr) - : this._( - lib._newBlock1( - _cFuncTrampoline ??= ffi.Pointer.fromFunction< - ffi.Void Function(ffi.Pointer<_ObjCBlock> block, - ffi.Pointer arg0)>( - _ObjCBlock_ffiVoid_NSData_fnPtrTrampoline) - .cast(), - ptr.cast()), - lib); - static ffi.Pointer? _cFuncTrampoline; - - /// Creates a block from a Dart function. - ObjCBlock_ffiVoid_NSData.fromFunction( - SentryCocoa lib, void Function(ffi.Pointer arg0) fn) - : this._( - lib._newBlock1( - _dartFuncTrampoline ??= ffi.Pointer.fromFunction< - ffi.Void Function(ffi.Pointer<_ObjCBlock> block, - ffi.Pointer arg0)>( - _ObjCBlock_ffiVoid_NSData_closureTrampoline) - .cast(), - _ObjCBlock_ffiVoid_NSData_registerClosure(fn)), - lib); - static ffi.Pointer? _dartFuncTrampoline; - void call(ffi.Pointer arg0) { - return _id.ref.invoke - .cast< - ffi.NativeFunction< - ffi.Void Function(ffi.Pointer<_ObjCBlock> block, - ffi.Pointer arg0)>>() - .asFunction< - void Function(ffi.Pointer<_ObjCBlock> block, - ffi.Pointer arg0)>()(_id, arg0); - } -} - class NSURLSessionStreamTask extends NSURLSessionTask { NSURLSessionStreamTask._(ffi.Pointer id, SentryCocoa lib, {bool retain = false, bool release = false}) @@ -66675,7 +66955,7 @@ class NSURLSessionStreamTask extends NSURLSessionTask { int maxBytes, double timeout, ObjCBlock_ffiVoid_NSData_bool_NSError completionHandler) { - _lib._objc_msgSend_967( + _lib._objc_msgSend_982( _id, _lib._sel_readDataOfMinLength_maxLength_timeout_completionHandler_1, minBytes, @@ -66686,7 +66966,7 @@ class NSURLSessionStreamTask extends NSURLSessionTask { void writeData_timeout_completionHandler_(NSData? data, double timeout, ObjCBlock_ffiVoid_NSError completionHandler) { - _lib._objc_msgSend_968(_id, _lib._sel_writeData_timeout_completionHandler_1, + _lib._objc_msgSend_983(_id, _lib._sel_writeData_timeout_completionHandler_1, data?._id ?? ffi.nullptr, timeout, completionHandler._id); } @@ -66929,7 +67209,7 @@ class NSNetService extends NSObject { NSNetService initWithDomain_type_name_port_( NSString? domain, NSString? type, NSString? name, int port) { - final _ret = _lib._objc_msgSend_970( + final _ret = _lib._objc_msgSend_985( _id, _lib._sel_initWithDomain_type_name_port_1, domain?._id ?? ffi.nullptr, @@ -67025,7 +67305,7 @@ class NSNetService extends NSObject { } void publishWithOptions_(int options) { - _lib._objc_msgSend_971(_id, _lib._sel_publishWithOptions_1, options); + _lib._objc_msgSend_986(_id, _lib._sel_publishWithOptions_1, options); } void resolve() { @@ -67038,14 +67318,14 @@ class NSNetService extends NSObject { static NSDictionary dictionaryFromTXTRecordData_( SentryCocoa _lib, NSData? txtData) { - final _ret = _lib._objc_msgSend_972(_lib._class_NSNetService1, + final _ret = _lib._objc_msgSend_987(_lib._class_NSNetService1, _lib._sel_dictionaryFromTXTRecordData_1, txtData?._id ?? ffi.nullptr); return NSDictionary._(_ret, _lib, retain: true, release: true); } static NSData dataFromTXTRecordDictionary_( SentryCocoa _lib, NSDictionary? txtDictionary) { - final _ret = _lib._objc_msgSend_973( + final _ret = _lib._objc_msgSend_988( _lib._class_NSNetService1, _lib._sel_dataFromTXTRecordDictionary_1, txtDictionary?._id ?? ffi.nullptr); @@ -67059,7 +67339,7 @@ class NSNetService extends NSObject { bool getInputStream_outputStream_( ffi.Pointer> inputStream, ffi.Pointer> outputStream) { - return _lib._objc_msgSend_974(_id, _lib._sel_getInputStream_outputStream_1, + return _lib._objc_msgSend_989(_id, _lib._sel_getInputStream_outputStream_1, inputStream, outputStream); } @@ -67206,25 +67486,25 @@ class NSURLSessionWebSocketTask extends NSURLSessionTask { void sendMessage_completionHandler_(NSURLSessionWebSocketMessage? message, ObjCBlock_ffiVoid_NSError completionHandler) { - _lib._objc_msgSend_977(_id, _lib._sel_sendMessage_completionHandler_1, + _lib._objc_msgSend_992(_id, _lib._sel_sendMessage_completionHandler_1, message?._id ?? ffi.nullptr, completionHandler._id); } void receiveMessageWithCompletionHandler_( ObjCBlock_ffiVoid_NSURLSessionWebSocketMessage_NSError completionHandler) { - _lib._objc_msgSend_978(_id, _lib._sel_receiveMessageWithCompletionHandler_1, + _lib._objc_msgSend_993(_id, _lib._sel_receiveMessageWithCompletionHandler_1, completionHandler._id); } void sendPingWithPongReceiveHandler_( ObjCBlock_ffiVoid_NSError pongReceiveHandler) { - _lib._objc_msgSend_979(_id, _lib._sel_sendPingWithPongReceiveHandler_1, + _lib._objc_msgSend_994(_id, _lib._sel_sendPingWithPongReceiveHandler_1, pongReceiveHandler._id); } void cancelWithCloseCode_reason_(int closeCode, NSData? reason) { - _lib._objc_msgSend_980(_id, _lib._sel_cancelWithCloseCode_reason_1, + _lib._objc_msgSend_995(_id, _lib._sel_cancelWithCloseCode_reason_1, closeCode, reason?._id ?? ffi.nullptr); } @@ -67238,7 +67518,7 @@ class NSURLSessionWebSocketTask extends NSURLSessionTask { } int get closeCode { - return _lib._objc_msgSend_981(_id, _lib._sel_closeCode1); + return _lib._objc_msgSend_996(_id, _lib._sel_closeCode1); } NSData? get closeReason { @@ -67385,7 +67665,7 @@ class NSURLSessionWebSocketMessage extends NSObject { } int get type { - return _lib._objc_msgSend_976(_id, _lib._sel_type1); + return _lib._objc_msgSend_991(_id, _lib._sel_type1); } NSData? get data { @@ -67866,14 +68146,14 @@ class NSProtocolChecker extends NSProxy { } Protocol? get protocol { - final _ret = _lib._objc_msgSend_992(_id, _lib._sel_protocol1); + final _ret = _lib._objc_msgSend_1008(_id, _lib._sel_protocol1); return _ret.address == 0 ? null : Protocol._(_ret, _lib, retain: true, release: true); } NSObject? get target { - final _ret = _lib._objc_msgSend_822(_id, _lib._sel_target1); + final _ret = _lib._objc_msgSend_836(_id, _lib._sel_target1); return _ret.address == 0 ? null : NSObject._(_ret, _lib, retain: true, release: true); @@ -67881,7 +68161,7 @@ class NSProtocolChecker extends NSProxy { static NSProtocolChecker protocolCheckerWithTarget_protocol_( SentryCocoa _lib, NSObject? anObject, Protocol? aProtocol) { - final _ret = _lib._objc_msgSend_993( + final _ret = _lib._objc_msgSend_1009( _lib._class_NSProtocolChecker1, _lib._sel_protocolCheckerWithTarget_protocol_1, anObject?._id ?? ffi.nullptr, @@ -67891,7 +68171,7 @@ class NSProtocolChecker extends NSProxy { NSProtocolChecker initWithTarget_protocol_( NSObject? anObject, Protocol? aProtocol) { - final _ret = _lib._objc_msgSend_993( + final _ret = _lib._objc_msgSend_1009( _id, _lib._sel_initWithTarget_protocol_1, anObject?._id ?? ffi.nullptr, @@ -67960,7 +68240,7 @@ class NSTask extends NSObject { } set arguments(NSArray? value) { - return _lib._objc_msgSend_731( + return _lib._objc_msgSend_735( _id, _lib._sel_setArguments_1, value?._id ?? ffi.nullptr); } @@ -67988,6 +68268,18 @@ class NSTask extends NSObject { _id, _lib._sel_setCurrentDirectoryURL_1, value?._id ?? ffi.nullptr); } + NSData? get launchRequirementData { + final _ret = _lib._objc_msgSend_39(_id, _lib._sel_launchRequirementData1); + return _ret.address == 0 + ? null + : NSData._(_ret, _lib, retain: true, release: true); + } + + set launchRequirementData(NSData? value) { + return _lib._objc_msgSend_939( + _id, _lib._sel_setLaunchRequirementData_1, value?._id ?? ffi.nullptr); + } + NSObject get standardInput { final _ret = _lib._objc_msgSend_2(_id, _lib._sel_standardInput1); return NSObject._(_ret, _lib, retain: true, release: true); @@ -68017,7 +68309,7 @@ class NSTask extends NSObject { } bool launchAndReturnError_(ffi.Pointer> error) { - return _lib._objc_msgSend_225(_id, _lib._sel_launchAndReturnError_1, error); + return _lib._objc_msgSend_236(_id, _lib._sel_launchAndReturnError_1, error); } void interrupt() { @@ -68049,16 +68341,16 @@ class NSTask extends NSObject { } int get terminationReason { - return _lib._objc_msgSend_994(_id, _lib._sel_terminationReason1); + return _lib._objc_msgSend_1010(_id, _lib._sel_terminationReason1); } ObjCBlock_ffiVoid_NSTask get terminationHandler { - final _ret = _lib._objc_msgSend_995(_id, _lib._sel_terminationHandler1); + final _ret = _lib._objc_msgSend_1011(_id, _lib._sel_terminationHandler1); return ObjCBlock_ffiVoid_NSTask._(_ret, _lib); } set terminationHandler(ObjCBlock_ffiVoid_NSTask value) { - return _lib._objc_msgSend_996( + return _lib._objc_msgSend_1012( _id, _lib._sel_setTerminationHandler_1, value._id); } @@ -68077,7 +68369,7 @@ class NSTask extends NSObject { NSArray? arguments, ffi.Pointer> error, ObjCBlock_ffiVoid_NSTask terminationHandler) { - final _ret = _lib._objc_msgSend_997( + final _ret = _lib._objc_msgSend_1013( _lib._class_NSTask1, _lib._sel_launchedTaskWithExecutableURL_arguments_error_terminationHandler_1, url?._id ?? ffi.nullptr, @@ -68121,7 +68413,7 @@ class NSTask extends NSObject { static NSTask launchedTaskWithLaunchPath_arguments_( SentryCocoa _lib, NSString? path, NSArray? arguments) { - final _ret = _lib._objc_msgSend_998( + final _ret = _lib._objc_msgSend_1014( _lib._class_NSTask1, _lib._sel_launchedTaskWithLaunchPath_arguments_1, path?._id ?? ffi.nullptr, @@ -68340,7 +68632,7 @@ class NSXMLElement extends NSXMLNode { @override NSXMLElement initWithKind_options_(int kind, int options) { - final _ret = _lib._objc_msgSend_1000( + final _ret = _lib._objc_msgSend_1016( _id, _lib._sel_initWithKind_options_1, kind, options); return NSXMLElement._(_ret, _lib, retain: true, release: true); } @@ -68361,7 +68653,7 @@ class NSXMLElement extends NSXMLNode { } void addAttribute_(NSXMLNode? attribute) { - _lib._objc_msgSend_1012( + _lib._objc_msgSend_1028( _id, _lib._sel_addAttribute_1, attribute?._id ?? ffi.nullptr); } @@ -68378,7 +68670,7 @@ class NSXMLElement extends NSXMLNode { } set attributes(NSArray? value) { - return _lib._objc_msgSend_731( + return _lib._objc_msgSend_735( _id, _lib._sel_setAttributes_1, value?._id ?? ffi.nullptr); } @@ -68388,13 +68680,13 @@ class NSXMLElement extends NSXMLNode { } NSXMLNode attributeForName_(NSString? name) { - final _ret = _lib._objc_msgSend_1016( + final _ret = _lib._objc_msgSend_1032( _id, _lib._sel_attributeForName_1, name?._id ?? ffi.nullptr); return NSXMLNode._(_ret, _lib, retain: true, release: true); } NSXMLNode attributeForLocalName_URI_(NSString? localName, NSString? URI) { - final _ret = _lib._objc_msgSend_1033( + final _ret = _lib._objc_msgSend_1049( _id, _lib._sel_attributeForLocalName_URI_1, localName?._id ?? ffi.nullptr, @@ -68403,7 +68695,7 @@ class NSXMLElement extends NSXMLNode { } void addNamespace_(NSXMLNode? aNamespace) { - _lib._objc_msgSend_1012( + _lib._objc_msgSend_1028( _id, _lib._sel_addNamespace_1, aNamespace?._id ?? ffi.nullptr); } @@ -68420,18 +68712,18 @@ class NSXMLElement extends NSXMLNode { } set namespaces(NSArray? value) { - return _lib._objc_msgSend_731( + return _lib._objc_msgSend_735( _id, _lib._sel_setNamespaces_1, value?._id ?? ffi.nullptr); } NSXMLNode namespaceForPrefix_(NSString? name) { - final _ret = _lib._objc_msgSend_1016( + final _ret = _lib._objc_msgSend_1032( _id, _lib._sel_namespaceForPrefix_1, name?._id ?? ffi.nullptr); return NSXMLNode._(_ret, _lib, retain: true, release: true); } NSXMLNode resolveNamespaceForName_(NSString? name) { - final _ret = _lib._objc_msgSend_1016( + final _ret = _lib._objc_msgSend_1032( _id, _lib._sel_resolveNamespaceForName_1, name?._id ?? ffi.nullptr); return NSXMLNode._(_ret, _lib, retain: true, release: true); } @@ -68445,12 +68737,12 @@ class NSXMLElement extends NSXMLNode { } void insertChild_atIndex_(NSXMLNode? child, int index) { - _lib._objc_msgSend_1010( + _lib._objc_msgSend_1026( _id, _lib._sel_insertChild_atIndex_1, child?._id ?? ffi.nullptr, index); } void insertChildren_atIndex_(NSArray? children, int index) { - _lib._objc_msgSend_1011(_id, _lib._sel_insertChildren_atIndex_1, + _lib._objc_msgSend_1027(_id, _lib._sel_insertChildren_atIndex_1, children?._id ?? ffi.nullptr, index); } @@ -68464,17 +68756,17 @@ class NSXMLElement extends NSXMLNode { } void addChild_(NSXMLNode? child) { - _lib._objc_msgSend_1012( + _lib._objc_msgSend_1028( _id, _lib._sel_addChild_1, child?._id ?? ffi.nullptr); } void replaceChildAtIndex_withNode_(int index, NSXMLNode? node) { - _lib._objc_msgSend_1013(_id, _lib._sel_replaceChildAtIndex_withNode_1, + _lib._objc_msgSend_1029(_id, _lib._sel_replaceChildAtIndex_withNode_1, index, node?._id ?? ffi.nullptr); } void normalizeAdjacentTextNodesPreservingCDATA_(bool preserve) { - _lib._objc_msgSend_790( + _lib._objc_msgSend_794( _id, _lib._sel_normalizeAdjacentTextNodesPreservingCDATA_1, preserve); } @@ -68491,7 +68783,7 @@ class NSXMLElement extends NSXMLNode { @override NSXMLElement initWithKind_(int kind) { - final _ret = _lib._objc_msgSend_999(_id, _lib._sel_initWithKind_1, kind); + final _ret = _lib._objc_msgSend_1015(_id, _lib._sel_initWithKind_1, kind); return NSXMLElement._(_ret, _lib, retain: true, release: true); } @@ -68503,7 +68795,7 @@ class NSXMLElement extends NSXMLNode { static NSObject documentWithRootElement_( SentryCocoa _lib, NSXMLElement? element) { - final _ret = _lib._objc_msgSend_1001(_lib._class_NSXMLElement1, + final _ret = _lib._objc_msgSend_1017(_lib._class_NSXMLElement1, _lib._sel_documentWithRootElement_1, element?._id ?? ffi.nullptr); return NSObject._(_ret, _lib, retain: true, release: true); } @@ -68536,7 +68828,7 @@ class NSXMLElement extends NSXMLNode { static NSObject elementWithName_children_attributes_(SentryCocoa _lib, NSString? name, NSArray? children, NSArray? attributes) { - final _ret = _lib._objc_msgSend_1002( + final _ret = _lib._objc_msgSend_1018( _lib._class_NSXMLElement1, _lib._sel_elementWithName_children_attributes_1, name?._id ?? ffi.nullptr, @@ -68620,7 +68912,7 @@ class NSXMLElement extends NSXMLNode { static NSXMLNode predefinedNamespaceForPrefix_( SentryCocoa _lib, NSString? name) { - final _ret = _lib._objc_msgSend_1016(_lib._class_NSXMLElement1, + final _ret = _lib._objc_msgSend_1032(_lib._class_NSXMLElement1, _lib._sel_predefinedNamespaceForPrefix_1, name?._id ?? ffi.nullptr); return NSXMLNode._(_ret, _lib, retain: true, release: true); } @@ -68742,12 +69034,12 @@ class NSXMLNode extends NSObject { } NSXMLNode initWithKind_(int kind) { - final _ret = _lib._objc_msgSend_999(_id, _lib._sel_initWithKind_1, kind); + final _ret = _lib._objc_msgSend_1015(_id, _lib._sel_initWithKind_1, kind); return NSXMLNode._(_ret, _lib, retain: true, release: true); } NSXMLNode initWithKind_options_(int kind, int options) { - final _ret = _lib._objc_msgSend_1000( + final _ret = _lib._objc_msgSend_1016( _id, _lib._sel_initWithKind_options_1, kind, options); return NSXMLNode._(_ret, _lib, retain: true, release: true); } @@ -68760,7 +69052,7 @@ class NSXMLNode extends NSObject { static NSObject documentWithRootElement_( SentryCocoa _lib, NSXMLElement? element) { - final _ret = _lib._objc_msgSend_1001(_lib._class_NSXMLNode1, + final _ret = _lib._objc_msgSend_1017(_lib._class_NSXMLNode1, _lib._sel_documentWithRootElement_1, element?._id ?? ffi.nullptr); return NSObject._(_ret, _lib, retain: true, release: true); } @@ -68793,7 +69085,7 @@ class NSXMLNode extends NSObject { static NSObject elementWithName_children_attributes_(SentryCocoa _lib, NSString? name, NSArray? children, NSArray? attributes) { - final _ret = _lib._objc_msgSend_1002( + final _ret = _lib._objc_msgSend_1018( _lib._class_NSXMLNode1, _lib._sel_elementWithName_children_attributes_1, name?._id ?? ffi.nullptr, @@ -68864,7 +69156,7 @@ class NSXMLNode extends NSObject { } int get kind { - return _lib._objc_msgSend_1003(_id, _lib._sel_kind1); + return _lib._objc_msgSend_1019(_id, _lib._sel_kind1); } NSString? get name { @@ -68901,7 +69193,7 @@ class NSXMLNode extends NSObject { } void setStringValue_resolvingEntities_(NSString? string, bool resolve) { - _lib._objc_msgSend_1004(_id, _lib._sel_setStringValue_resolvingEntities_1, + _lib._objc_msgSend_1020(_id, _lib._sel_setStringValue_resolvingEntities_1, string?._id ?? ffi.nullptr, resolve); } @@ -68914,14 +69206,14 @@ class NSXMLNode extends NSObject { } NSXMLDocument? get rootDocument { - final _ret = _lib._objc_msgSend_1027(_id, _lib._sel_rootDocument1); + final _ret = _lib._objc_msgSend_1043(_id, _lib._sel_rootDocument1); return _ret.address == 0 ? null : NSXMLDocument._(_ret, _lib, retain: true, release: true); } NSXMLNode? get parent { - final _ret = _lib._objc_msgSend_1028(_id, _lib._sel_parent1); + final _ret = _lib._objc_msgSend_1044(_id, _lib._sel_parent1); return _ret.address == 0 ? null : NSXMLNode._(_ret, _lib, retain: true, release: true); @@ -68939,33 +69231,33 @@ class NSXMLNode extends NSObject { } NSXMLNode childAtIndex_(int index) { - final _ret = _lib._objc_msgSend_1029(_id, _lib._sel_childAtIndex_1, index); + final _ret = _lib._objc_msgSend_1045(_id, _lib._sel_childAtIndex_1, index); return NSXMLNode._(_ret, _lib, retain: true, release: true); } NSXMLNode? get previousSibling { - final _ret = _lib._objc_msgSend_1028(_id, _lib._sel_previousSibling1); + final _ret = _lib._objc_msgSend_1044(_id, _lib._sel_previousSibling1); return _ret.address == 0 ? null : NSXMLNode._(_ret, _lib, retain: true, release: true); } NSXMLNode? get nextSibling { - final _ret = _lib._objc_msgSend_1028(_id, _lib._sel_nextSibling1); + final _ret = _lib._objc_msgSend_1044(_id, _lib._sel_nextSibling1); return _ret.address == 0 ? null : NSXMLNode._(_ret, _lib, retain: true, release: true); } NSXMLNode? get previousNode { - final _ret = _lib._objc_msgSend_1028(_id, _lib._sel_previousNode1); + final _ret = _lib._objc_msgSend_1044(_id, _lib._sel_previousNode1); return _ret.address == 0 ? null : NSXMLNode._(_ret, _lib, retain: true, release: true); } NSXMLNode? get nextNode { - final _ret = _lib._objc_msgSend_1028(_id, _lib._sel_nextNode1); + final _ret = _lib._objc_msgSend_1044(_id, _lib._sel_nextNode1); return _ret.address == 0 ? null : NSXMLNode._(_ret, _lib, retain: true, release: true); @@ -69022,7 +69314,7 @@ class NSXMLNode extends NSObject { static NSXMLNode predefinedNamespaceForPrefix_( SentryCocoa _lib, NSString? name) { - final _ret = _lib._objc_msgSend_1016(_lib._class_NSXMLNode1, + final _ret = _lib._objc_msgSend_1032(_lib._class_NSXMLNode1, _lib._sel_predefinedNamespaceForPrefix_1, name?._id ?? ffi.nullptr); return NSXMLNode._(_ret, _lib, retain: true, release: true); } @@ -69043,12 +69335,12 @@ class NSXMLNode extends NSObject { NSString XMLStringWithOptions_(int options) { final _ret = - _lib._objc_msgSend_1030(_id, _lib._sel_XMLStringWithOptions_1, options); + _lib._objc_msgSend_1046(_id, _lib._sel_XMLStringWithOptions_1, options); return NSString._(_ret, _lib, retain: true, release: true); } NSString canonicalXMLStringPreservingComments_(bool comments) { - final _ret = _lib._objc_msgSend_1031( + final _ret = _lib._objc_msgSend_1047( _id, _lib._sel_canonicalXMLStringPreservingComments_1, comments); return NSString._(_ret, _lib, retain: true, release: true); } @@ -69062,7 +69354,7 @@ class NSXMLNode extends NSObject { NSArray objectsForXQuery_constants_error_(NSString? xquery, NSDictionary? constants, ffi.Pointer> error) { - final _ret = _lib._objc_msgSend_1032( + final _ret = _lib._objc_msgSend_1048( _id, _lib._sel_objectsForXQuery_constants_error_1, xquery?._id ?? ffi.nullptr, @@ -69240,7 +69532,7 @@ class NSXMLDocument extends NSXMLNode { NSXMLDocument initWithXMLString_options_error_( NSString? string, int mask, ffi.Pointer> error) { - final _ret = _lib._objc_msgSend_1005( + final _ret = _lib._objc_msgSend_1021( _id, _lib._sel_initWithXMLString_options_error_1, string?._id ?? ffi.nullptr, @@ -69251,7 +69543,7 @@ class NSXMLDocument extends NSXMLNode { NSXMLDocument initWithContentsOfURL_options_error_( NSURL? url, int mask, ffi.Pointer> error) { - final _ret = _lib._objc_msgSend_1006( + final _ret = _lib._objc_msgSend_1022( _id, _lib._sel_initWithContentsOfURL_options_error_1, url?._id ?? ffi.nullptr, @@ -69262,7 +69554,7 @@ class NSXMLDocument extends NSXMLNode { NSXMLDocument initWithData_options_error_( NSData? data, int mask, ffi.Pointer> error) { - final _ret = _lib._objc_msgSend_1007( + final _ret = _lib._objc_msgSend_1023( _id, _lib._sel_initWithData_options_error_1, data?._id ?? ffi.nullptr, @@ -69272,7 +69564,7 @@ class NSXMLDocument extends NSXMLNode { } NSXMLDocument initWithRootElement_(NSXMLElement? element) { - final _ret = _lib._objc_msgSend_1001( + final _ret = _lib._objc_msgSend_1017( _id, _lib._sel_initWithRootElement_1, element?._id ?? ffi.nullptr); return NSXMLDocument._(_ret, _lib, retain: true, release: true); } @@ -69316,11 +69608,11 @@ class NSXMLDocument extends NSXMLNode { } int get documentContentKind { - return _lib._objc_msgSend_1008(_id, _lib._sel_documentContentKind1); + return _lib._objc_msgSend_1024(_id, _lib._sel_documentContentKind1); } set documentContentKind(int value) { - return _lib._objc_msgSend_1009( + return _lib._objc_msgSend_1025( _id, _lib._sel_setDocumentContentKind_1, value); } @@ -69337,34 +69629,34 @@ class NSXMLDocument extends NSXMLNode { } NSXMLDTD? get DTD { - final _ret = _lib._objc_msgSend_1019(_id, _lib._sel_DTD1); + final _ret = _lib._objc_msgSend_1035(_id, _lib._sel_DTD1); return _ret.address == 0 ? null : NSXMLDTD._(_ret, _lib, retain: true, release: true); } set DTD(NSXMLDTD? value) { - return _lib._objc_msgSend_1020( + return _lib._objc_msgSend_1036( _id, _lib._sel_setDTD_1, value?._id ?? ffi.nullptr); } void setRootElement_(NSXMLElement? root) { - _lib._objc_msgSend_1021( + _lib._objc_msgSend_1037( _id, _lib._sel_setRootElement_1, root?._id ?? ffi.nullptr); } NSXMLElement rootElement() { - final _ret = _lib._objc_msgSend_1022(_id, _lib._sel_rootElement1); + final _ret = _lib._objc_msgSend_1038(_id, _lib._sel_rootElement1); return NSXMLElement._(_ret, _lib, retain: true, release: true); } void insertChild_atIndex_(NSXMLNode? child, int index) { - _lib._objc_msgSend_1010( + _lib._objc_msgSend_1026( _id, _lib._sel_insertChild_atIndex_1, child?._id ?? ffi.nullptr, index); } void insertChildren_atIndex_(NSArray? children, int index) { - _lib._objc_msgSend_1011(_id, _lib._sel_insertChildren_atIndex_1, + _lib._objc_msgSend_1027(_id, _lib._sel_insertChildren_atIndex_1, children?._id ?? ffi.nullptr, index); } @@ -69378,12 +69670,12 @@ class NSXMLDocument extends NSXMLNode { } void addChild_(NSXMLNode? child) { - _lib._objc_msgSend_1012( + _lib._objc_msgSend_1028( _id, _lib._sel_addChild_1, child?._id ?? ffi.nullptr); } void replaceChildAtIndex_withNode_(int index, NSXMLNode? node) { - _lib._objc_msgSend_1013(_id, _lib._sel_replaceChildAtIndex_withNode_1, + _lib._objc_msgSend_1029(_id, _lib._sel_replaceChildAtIndex_withNode_1, index, node?._id ?? ffi.nullptr); } @@ -69396,13 +69688,13 @@ class NSXMLDocument extends NSXMLNode { NSData XMLDataWithOptions_(int options) { final _ret = - _lib._objc_msgSend_1023(_id, _lib._sel_XMLDataWithOptions_1, options); + _lib._objc_msgSend_1039(_id, _lib._sel_XMLDataWithOptions_1, options); return NSData._(_ret, _lib, retain: true, release: true); } NSObject objectByApplyingXSLT_arguments_error_(NSData? xslt, NSDictionary? arguments, ffi.Pointer> error) { - final _ret = _lib._objc_msgSend_1024( + final _ret = _lib._objc_msgSend_1040( _id, _lib._sel_objectByApplyingXSLT_arguments_error_1, xslt?._id ?? ffi.nullptr, @@ -69413,7 +69705,7 @@ class NSXMLDocument extends NSXMLNode { NSObject objectByApplyingXSLTString_arguments_error_(NSString? xslt, NSDictionary? arguments, ffi.Pointer> error) { - final _ret = _lib._objc_msgSend_1025( + final _ret = _lib._objc_msgSend_1041( _id, _lib._sel_objectByApplyingXSLTString_arguments_error_1, xslt?._id ?? ffi.nullptr, @@ -69424,7 +69716,7 @@ class NSXMLDocument extends NSXMLNode { NSObject objectByApplyingXSLTAtURL_arguments_error_(NSURL? xsltURL, NSDictionary? argument, ffi.Pointer> error) { - final _ret = _lib._objc_msgSend_1026( + final _ret = _lib._objc_msgSend_1042( _id, _lib._sel_objectByApplyingXSLTAtURL_arguments_error_1, xsltURL?._id ?? ffi.nullptr, @@ -69434,19 +69726,19 @@ class NSXMLDocument extends NSXMLNode { } bool validateAndReturnError_(ffi.Pointer> error) { - return _lib._objc_msgSend_225( + return _lib._objc_msgSend_236( _id, _lib._sel_validateAndReturnError_1, error); } @override NSXMLDocument initWithKind_(int kind) { - final _ret = _lib._objc_msgSend_999(_id, _lib._sel_initWithKind_1, kind); + final _ret = _lib._objc_msgSend_1015(_id, _lib._sel_initWithKind_1, kind); return NSXMLDocument._(_ret, _lib, retain: true, release: true); } @override NSXMLDocument initWithKind_options_(int kind, int options) { - final _ret = _lib._objc_msgSend_1000( + final _ret = _lib._objc_msgSend_1016( _id, _lib._sel_initWithKind_options_1, kind, options); return NSXMLDocument._(_ret, _lib, retain: true, release: true); } @@ -69459,7 +69751,7 @@ class NSXMLDocument extends NSXMLNode { static NSObject documentWithRootElement_( SentryCocoa _lib, NSXMLElement? element) { - final _ret = _lib._objc_msgSend_1001(_lib._class_NSXMLDocument1, + final _ret = _lib._objc_msgSend_1017(_lib._class_NSXMLDocument1, _lib._sel_documentWithRootElement_1, element?._id ?? ffi.nullptr); return NSObject._(_ret, _lib, retain: true, release: true); } @@ -69492,7 +69784,7 @@ class NSXMLDocument extends NSXMLNode { static NSObject elementWithName_children_attributes_(SentryCocoa _lib, NSString? name, NSArray? children, NSArray? attributes) { - final _ret = _lib._objc_msgSend_1002( + final _ret = _lib._objc_msgSend_1018( _lib._class_NSXMLDocument1, _lib._sel_elementWithName_children_attributes_1, name?._id ?? ffi.nullptr, @@ -69576,7 +69868,7 @@ class NSXMLDocument extends NSXMLNode { static NSXMLNode predefinedNamespaceForPrefix_( SentryCocoa _lib, NSString? name) { - final _ret = _lib._objc_msgSend_1016(_lib._class_NSXMLDocument1, + final _ret = _lib._objc_msgSend_1032(_lib._class_NSXMLDocument1, _lib._sel_predefinedNamespaceForPrefix_1, name?._id ?? ffi.nullptr); return NSXMLNode._(_ret, _lib, retain: true, release: true); } @@ -69706,14 +69998,14 @@ class NSXMLDTD extends NSXMLNode { @override NSXMLDTD initWithKind_options_(int kind, int options) { - final _ret = _lib._objc_msgSend_1000( + final _ret = _lib._objc_msgSend_1016( _id, _lib._sel_initWithKind_options_1, kind, options); return NSXMLDTD._(_ret, _lib, retain: true, release: true); } NSXMLDTD initWithContentsOfURL_options_error_( NSURL? url, int mask, ffi.Pointer> error) { - final _ret = _lib._objc_msgSend_1006( + final _ret = _lib._objc_msgSend_1022( _id, _lib._sel_initWithContentsOfURL_options_error_1, url?._id ?? ffi.nullptr, @@ -69724,7 +70016,7 @@ class NSXMLDTD extends NSXMLNode { NSXMLDTD initWithData_options_error_( NSData? data, int mask, ffi.Pointer> error) { - final _ret = _lib._objc_msgSend_1007( + final _ret = _lib._objc_msgSend_1023( _id, _lib._sel_initWithData_options_error_1, data?._id ?? ffi.nullptr, @@ -69758,12 +70050,12 @@ class NSXMLDTD extends NSXMLNode { } void insertChild_atIndex_(NSXMLNode? child, int index) { - _lib._objc_msgSend_1010( + _lib._objc_msgSend_1026( _id, _lib._sel_insertChild_atIndex_1, child?._id ?? ffi.nullptr, index); } void insertChildren_atIndex_(NSArray? children, int index) { - _lib._objc_msgSend_1011(_id, _lib._sel_insertChildren_atIndex_1, + _lib._objc_msgSend_1027(_id, _lib._sel_insertChildren_atIndex_1, children?._id ?? ffi.nullptr, index); } @@ -69777,36 +70069,36 @@ class NSXMLDTD extends NSXMLNode { } void addChild_(NSXMLNode? child) { - _lib._objc_msgSend_1012( + _lib._objc_msgSend_1028( _id, _lib._sel_addChild_1, child?._id ?? ffi.nullptr); } void replaceChildAtIndex_withNode_(int index, NSXMLNode? node) { - _lib._objc_msgSend_1013(_id, _lib._sel_replaceChildAtIndex_withNode_1, + _lib._objc_msgSend_1029(_id, _lib._sel_replaceChildAtIndex_withNode_1, index, node?._id ?? ffi.nullptr); } NSXMLDTDNode entityDeclarationForName_(NSString? name) { - final _ret = _lib._objc_msgSend_1017( + final _ret = _lib._objc_msgSend_1033( _id, _lib._sel_entityDeclarationForName_1, name?._id ?? ffi.nullptr); return NSXMLDTDNode._(_ret, _lib, retain: true, release: true); } NSXMLDTDNode notationDeclarationForName_(NSString? name) { - final _ret = _lib._objc_msgSend_1017( + final _ret = _lib._objc_msgSend_1033( _id, _lib._sel_notationDeclarationForName_1, name?._id ?? ffi.nullptr); return NSXMLDTDNode._(_ret, _lib, retain: true, release: true); } NSXMLDTDNode elementDeclarationForName_(NSString? name) { - final _ret = _lib._objc_msgSend_1017( + final _ret = _lib._objc_msgSend_1033( _id, _lib._sel_elementDeclarationForName_1, name?._id ?? ffi.nullptr); return NSXMLDTDNode._(_ret, _lib, retain: true, release: true); } NSXMLDTDNode attributeDeclarationForName_elementName_( NSString? name, NSString? elementName) { - final _ret = _lib._objc_msgSend_1018( + final _ret = _lib._objc_msgSend_1034( _id, _lib._sel_attributeDeclarationForName_elementName_1, name?._id ?? ffi.nullptr, @@ -69816,7 +70108,7 @@ class NSXMLDTD extends NSXMLNode { static NSXMLDTDNode predefinedEntityDeclarationForName_( SentryCocoa _lib, NSString? name) { - final _ret = _lib._objc_msgSend_1017( + final _ret = _lib._objc_msgSend_1033( _lib._class_NSXMLDTD1, _lib._sel_predefinedEntityDeclarationForName_1, name?._id ?? ffi.nullptr); @@ -69825,7 +70117,7 @@ class NSXMLDTD extends NSXMLNode { @override NSXMLDTD initWithKind_(int kind) { - final _ret = _lib._objc_msgSend_999(_id, _lib._sel_initWithKind_1, kind); + final _ret = _lib._objc_msgSend_1015(_id, _lib._sel_initWithKind_1, kind); return NSXMLDTD._(_ret, _lib, retain: true, release: true); } @@ -69837,7 +70129,7 @@ class NSXMLDTD extends NSXMLNode { static NSObject documentWithRootElement_( SentryCocoa _lib, NSXMLElement? element) { - final _ret = _lib._objc_msgSend_1001(_lib._class_NSXMLDTD1, + final _ret = _lib._objc_msgSend_1017(_lib._class_NSXMLDTD1, _lib._sel_documentWithRootElement_1, element?._id ?? ffi.nullptr); return NSObject._(_ret, _lib, retain: true, release: true); } @@ -69870,318 +70162,8 @@ class NSXMLDTD extends NSXMLNode { static NSObject elementWithName_children_attributes_(SentryCocoa _lib, NSString? name, NSArray? children, NSArray? attributes) { - final _ret = _lib._objc_msgSend_1002( - _lib._class_NSXMLDTD1, - _lib._sel_elementWithName_children_attributes_1, - name?._id ?? ffi.nullptr, - children?._id ?? ffi.nullptr, - attributes?._id ?? ffi.nullptr); - return NSObject._(_ret, _lib, retain: true, release: true); - } - - static NSObject attributeWithName_stringValue_( - SentryCocoa _lib, NSString? name, NSString? stringValue) { - final _ret = _lib._objc_msgSend_165( - _lib._class_NSXMLDTD1, - _lib._sel_attributeWithName_stringValue_1, - name?._id ?? ffi.nullptr, - stringValue?._id ?? ffi.nullptr); - return NSObject._(_ret, _lib, retain: true, release: true); - } - - static NSObject attributeWithName_URI_stringValue_( - SentryCocoa _lib, NSString? name, NSString? URI, NSString? stringValue) { - final _ret = _lib._objc_msgSend_26( - _lib._class_NSXMLDTD1, - _lib._sel_attributeWithName_URI_stringValue_1, - name?._id ?? ffi.nullptr, - URI?._id ?? ffi.nullptr, - stringValue?._id ?? ffi.nullptr); - return NSObject._(_ret, _lib, retain: true, release: true); - } - - static NSObject namespaceWithName_stringValue_( - SentryCocoa _lib, NSString? name, NSString? stringValue) { - final _ret = _lib._objc_msgSend_165( - _lib._class_NSXMLDTD1, - _lib._sel_namespaceWithName_stringValue_1, - name?._id ?? ffi.nullptr, - stringValue?._id ?? ffi.nullptr); - return NSObject._(_ret, _lib, retain: true, release: true); - } - - static NSObject processingInstructionWithName_stringValue_( - SentryCocoa _lib, NSString? name, NSString? stringValue) { - final _ret = _lib._objc_msgSend_165( - _lib._class_NSXMLDTD1, - _lib._sel_processingInstructionWithName_stringValue_1, - name?._id ?? ffi.nullptr, - stringValue?._id ?? ffi.nullptr); - return NSObject._(_ret, _lib, retain: true, release: true); - } - - static NSObject commentWithStringValue_( - SentryCocoa _lib, NSString? stringValue) { - final _ret = _lib._objc_msgSend_30(_lib._class_NSXMLDTD1, - _lib._sel_commentWithStringValue_1, stringValue?._id ?? ffi.nullptr); - return NSObject._(_ret, _lib, retain: true, release: true); - } - - static NSObject textWithStringValue_( - SentryCocoa _lib, NSString? stringValue) { - final _ret = _lib._objc_msgSend_30(_lib._class_NSXMLDTD1, - _lib._sel_textWithStringValue_1, stringValue?._id ?? ffi.nullptr); - return NSObject._(_ret, _lib, retain: true, release: true); - } - - static NSObject DTDNodeWithXMLString_(SentryCocoa _lib, NSString? string) { - final _ret = _lib._objc_msgSend_30(_lib._class_NSXMLDTD1, - _lib._sel_DTDNodeWithXMLString_1, string?._id ?? ffi.nullptr); - return NSObject._(_ret, _lib, retain: true, release: true); - } - - static NSString localNameForName_(SentryCocoa _lib, NSString? name) { - final _ret = _lib._objc_msgSend_64(_lib._class_NSXMLDTD1, - _lib._sel_localNameForName_1, name?._id ?? ffi.nullptr); - return NSString._(_ret, _lib, retain: true, release: true); - } - - static NSString prefixForName_(SentryCocoa _lib, NSString? name) { - final _ret = _lib._objc_msgSend_64(_lib._class_NSXMLDTD1, - _lib._sel_prefixForName_1, name?._id ?? ffi.nullptr); - return NSString._(_ret, _lib, retain: true, release: true); - } - - static NSXMLNode predefinedNamespaceForPrefix_( - SentryCocoa _lib, NSString? name) { - final _ret = _lib._objc_msgSend_1016(_lib._class_NSXMLDTD1, - _lib._sel_predefinedNamespaceForPrefix_1, name?._id ?? ffi.nullptr); - return NSXMLNode._(_ret, _lib, retain: true, release: true); - } - - static NSXMLDTD new1(SentryCocoa _lib) { - final _ret = _lib._objc_msgSend_2(_lib._class_NSXMLDTD1, _lib._sel_new1); - return NSXMLDTD._(_ret, _lib, retain: false, release: true); - } - - static NSXMLDTD allocWithZone_(SentryCocoa _lib, ffi.Pointer<_NSZone> zone) { - final _ret = _lib._objc_msgSend_3( - _lib._class_NSXMLDTD1, _lib._sel_allocWithZone_1, zone); - return NSXMLDTD._(_ret, _lib, retain: false, release: true); - } - - static NSXMLDTD alloc(SentryCocoa _lib) { - final _ret = _lib._objc_msgSend_2(_lib._class_NSXMLDTD1, _lib._sel_alloc1); - return NSXMLDTD._(_ret, _lib, retain: false, release: true); - } - - static void cancelPreviousPerformRequestsWithTarget_selector_object_( - SentryCocoa _lib, - NSObject aTarget, - ffi.Pointer aSelector, - NSObject anArgument) { - _lib._objc_msgSend_14( - _lib._class_NSXMLDTD1, - _lib._sel_cancelPreviousPerformRequestsWithTarget_selector_object_1, - aTarget._id, - aSelector, - anArgument._id); - } - - static void cancelPreviousPerformRequestsWithTarget_( - SentryCocoa _lib, NSObject aTarget) { - _lib._objc_msgSend_15(_lib._class_NSXMLDTD1, - _lib._sel_cancelPreviousPerformRequestsWithTarget_1, aTarget._id); - } - - static bool getAccessInstanceVariablesDirectly(SentryCocoa _lib) { - return _lib._objc_msgSend_12( - _lib._class_NSXMLDTD1, _lib._sel_accessInstanceVariablesDirectly1); - } - - static bool useStoredAccessor(SentryCocoa _lib) { - return _lib._objc_msgSend_12( - _lib._class_NSXMLDTD1, _lib._sel_useStoredAccessor1); - } - - static NSSet keyPathsForValuesAffectingValueForKey_( - SentryCocoa _lib, NSString? key) { - final _ret = _lib._objc_msgSend_58( - _lib._class_NSXMLDTD1, - _lib._sel_keyPathsForValuesAffectingValueForKey_1, - key?._id ?? ffi.nullptr); - return NSSet._(_ret, _lib, retain: true, release: true); - } - - static bool automaticallyNotifiesObserversForKey_( - SentryCocoa _lib, NSString? key) { - return _lib._objc_msgSend_59( - _lib._class_NSXMLDTD1, - _lib._sel_automaticallyNotifiesObserversForKey_1, - key?._id ?? ffi.nullptr); - } - - static void setKeys_triggerChangeNotificationsForDependentKey_( - SentryCocoa _lib, NSArray? keys, NSString? dependentKey) { - _lib._objc_msgSend_82( + final _ret = _lib._objc_msgSend_1018( _lib._class_NSXMLDTD1, - _lib._sel_setKeys_triggerChangeNotificationsForDependentKey_1, - keys?._id ?? ffi.nullptr, - dependentKey?._id ?? ffi.nullptr); - } - - static NSArray classFallbacksForKeyedArchiver(SentryCocoa _lib) { - final _ret = _lib._objc_msgSend_79( - _lib._class_NSXMLDTD1, _lib._sel_classFallbacksForKeyedArchiver1); - return NSArray._(_ret, _lib, retain: true, release: true); - } - - static NSObject classForKeyedUnarchiver(SentryCocoa _lib) { - final _ret = _lib._objc_msgSend_2( - _lib._class_NSXMLDTD1, _lib._sel_classForKeyedUnarchiver1); - return NSObject._(_ret, _lib, retain: true, release: true); - } -} - -class NSXMLDTDNode extends NSXMLNode { - NSXMLDTDNode._(ffi.Pointer id, SentryCocoa lib, - {bool retain = false, bool release = false}) - : super._(id, lib, retain: retain, release: release); - - /// Returns a [NSXMLDTDNode] that points to the same underlying object as [other]. - static NSXMLDTDNode castFrom(T other) { - return NSXMLDTDNode._(other._id, other._lib, retain: true, release: true); - } - - /// Returns a [NSXMLDTDNode] that wraps the given raw object pointer. - static NSXMLDTDNode castFromPointer( - SentryCocoa lib, ffi.Pointer other, - {bool retain = false, bool release = false}) { - return NSXMLDTDNode._(other, lib, retain: retain, release: release); - } - - /// Returns whether [obj] is an instance of [NSXMLDTDNode]. - static bool isInstance(_ObjCWrapper obj) { - return obj._lib._objc_msgSend_0( - obj._id, obj._lib._sel_isKindOfClass_1, obj._lib._class_NSXMLDTDNode1); - } - - NSXMLDTDNode initWithXMLString_(NSString? string) { - final _ret = _lib._objc_msgSend_30( - _id, _lib._sel_initWithXMLString_1, string?._id ?? ffi.nullptr); - return NSXMLDTDNode._(_ret, _lib, retain: true, release: true); - } - - @override - NSXMLDTDNode initWithKind_options_(int kind, int options) { - final _ret = _lib._objc_msgSend_1000( - _id, _lib._sel_initWithKind_options_1, kind, options); - return NSXMLDTDNode._(_ret, _lib, retain: true, release: true); - } - - @override - NSXMLDTDNode init() { - final _ret = _lib._objc_msgSend_2(_id, _lib._sel_init1); - return NSXMLDTDNode._(_ret, _lib, retain: true, release: true); - } - - int get DTDKind { - return _lib._objc_msgSend_1014(_id, _lib._sel_DTDKind1); - } - - set DTDKind(int value) { - return _lib._objc_msgSend_1015(_id, _lib._sel_setDTDKind_1, value); - } - - bool get external1 { - return _lib._objc_msgSend_12(_id, _lib._sel_isExternal1); - } - - NSString? get publicID { - final _ret = _lib._objc_msgSend_20(_id, _lib._sel_publicID1); - return _ret.address == 0 - ? null - : NSString._(_ret, _lib, retain: true, release: true); - } - - set publicID(NSString? value) { - return _lib._objc_msgSend_509( - _id, _lib._sel_setPublicID_1, value?._id ?? ffi.nullptr); - } - - NSString? get systemID { - final _ret = _lib._objc_msgSend_20(_id, _lib._sel_systemID1); - return _ret.address == 0 - ? null - : NSString._(_ret, _lib, retain: true, release: true); - } - - set systemID(NSString? value) { - return _lib._objc_msgSend_509( - _id, _lib._sel_setSystemID_1, value?._id ?? ffi.nullptr); - } - - NSString? get notationName { - final _ret = _lib._objc_msgSend_20(_id, _lib._sel_notationName1); - return _ret.address == 0 - ? null - : NSString._(_ret, _lib, retain: true, release: true); - } - - set notationName(NSString? value) { - return _lib._objc_msgSend_509( - _id, _lib._sel_setNotationName_1, value?._id ?? ffi.nullptr); - } - - @override - NSXMLDTDNode initWithKind_(int kind) { - final _ret = _lib._objc_msgSend_999(_id, _lib._sel_initWithKind_1, kind); - return NSXMLDTDNode._(_ret, _lib, retain: true, release: true); - } - - static NSObject document(SentryCocoa _lib) { - final _ret = - _lib._objc_msgSend_2(_lib._class_NSXMLDTDNode1, _lib._sel_document1); - return NSObject._(_ret, _lib, retain: true, release: true); - } - - static NSObject documentWithRootElement_( - SentryCocoa _lib, NSXMLElement? element) { - final _ret = _lib._objc_msgSend_1001(_lib._class_NSXMLDTDNode1, - _lib._sel_documentWithRootElement_1, element?._id ?? ffi.nullptr); - return NSObject._(_ret, _lib, retain: true, release: true); - } - - static NSObject elementWithName_(SentryCocoa _lib, NSString? name) { - final _ret = _lib._objc_msgSend_30(_lib._class_NSXMLDTDNode1, - _lib._sel_elementWithName_1, name?._id ?? ffi.nullptr); - return NSObject._(_ret, _lib, retain: true, release: true); - } - - static NSObject elementWithName_URI_( - SentryCocoa _lib, NSString? name, NSString? URI) { - final _ret = _lib._objc_msgSend_165( - _lib._class_NSXMLDTDNode1, - _lib._sel_elementWithName_URI_1, - name?._id ?? ffi.nullptr, - URI?._id ?? ffi.nullptr); - return NSObject._(_ret, _lib, retain: true, release: true); - } - - static NSObject elementWithName_stringValue_( - SentryCocoa _lib, NSString? name, NSString? string) { - final _ret = _lib._objc_msgSend_165( - _lib._class_NSXMLDTDNode1, - _lib._sel_elementWithName_stringValue_1, - name?._id ?? ffi.nullptr, - string?._id ?? ffi.nullptr); - return NSObject._(_ret, _lib, retain: true, release: true); - } - - static NSObject elementWithName_children_attributes_(SentryCocoa _lib, - NSString? name, NSArray? children, NSArray? attributes) { - final _ret = _lib._objc_msgSend_1002( - _lib._class_NSXMLDTDNode1, _lib._sel_elementWithName_children_attributes_1, name?._id ?? ffi.nullptr, children?._id ?? ffi.nullptr, @@ -70192,770 +70174,97 @@ class NSXMLDTDNode extends NSXMLNode { static NSObject attributeWithName_stringValue_( SentryCocoa _lib, NSString? name, NSString? stringValue) { final _ret = _lib._objc_msgSend_165( - _lib._class_NSXMLDTDNode1, - _lib._sel_attributeWithName_stringValue_1, - name?._id ?? ffi.nullptr, - stringValue?._id ?? ffi.nullptr); - return NSObject._(_ret, _lib, retain: true, release: true); - } - - static NSObject attributeWithName_URI_stringValue_( - SentryCocoa _lib, NSString? name, NSString? URI, NSString? stringValue) { - final _ret = _lib._objc_msgSend_26( - _lib._class_NSXMLDTDNode1, - _lib._sel_attributeWithName_URI_stringValue_1, - name?._id ?? ffi.nullptr, - URI?._id ?? ffi.nullptr, - stringValue?._id ?? ffi.nullptr); - return NSObject._(_ret, _lib, retain: true, release: true); - } - - static NSObject namespaceWithName_stringValue_( - SentryCocoa _lib, NSString? name, NSString? stringValue) { - final _ret = _lib._objc_msgSend_165( - _lib._class_NSXMLDTDNode1, - _lib._sel_namespaceWithName_stringValue_1, - name?._id ?? ffi.nullptr, - stringValue?._id ?? ffi.nullptr); - return NSObject._(_ret, _lib, retain: true, release: true); - } - - static NSObject processingInstructionWithName_stringValue_( - SentryCocoa _lib, NSString? name, NSString? stringValue) { - final _ret = _lib._objc_msgSend_165( - _lib._class_NSXMLDTDNode1, - _lib._sel_processingInstructionWithName_stringValue_1, - name?._id ?? ffi.nullptr, - stringValue?._id ?? ffi.nullptr); - return NSObject._(_ret, _lib, retain: true, release: true); - } - - static NSObject commentWithStringValue_( - SentryCocoa _lib, NSString? stringValue) { - final _ret = _lib._objc_msgSend_30(_lib._class_NSXMLDTDNode1, - _lib._sel_commentWithStringValue_1, stringValue?._id ?? ffi.nullptr); - return NSObject._(_ret, _lib, retain: true, release: true); - } - - static NSObject textWithStringValue_( - SentryCocoa _lib, NSString? stringValue) { - final _ret = _lib._objc_msgSend_30(_lib._class_NSXMLDTDNode1, - _lib._sel_textWithStringValue_1, stringValue?._id ?? ffi.nullptr); - return NSObject._(_ret, _lib, retain: true, release: true); - } - - static NSObject DTDNodeWithXMLString_(SentryCocoa _lib, NSString? string) { - final _ret = _lib._objc_msgSend_30(_lib._class_NSXMLDTDNode1, - _lib._sel_DTDNodeWithXMLString_1, string?._id ?? ffi.nullptr); - return NSObject._(_ret, _lib, retain: true, release: true); - } - - static NSString localNameForName_(SentryCocoa _lib, NSString? name) { - final _ret = _lib._objc_msgSend_64(_lib._class_NSXMLDTDNode1, - _lib._sel_localNameForName_1, name?._id ?? ffi.nullptr); - return NSString._(_ret, _lib, retain: true, release: true); - } - - static NSString prefixForName_(SentryCocoa _lib, NSString? name) { - final _ret = _lib._objc_msgSend_64(_lib._class_NSXMLDTDNode1, - _lib._sel_prefixForName_1, name?._id ?? ffi.nullptr); - return NSString._(_ret, _lib, retain: true, release: true); - } - - static NSXMLNode predefinedNamespaceForPrefix_( - SentryCocoa _lib, NSString? name) { - final _ret = _lib._objc_msgSend_1016(_lib._class_NSXMLDTDNode1, - _lib._sel_predefinedNamespaceForPrefix_1, name?._id ?? ffi.nullptr); - return NSXMLNode._(_ret, _lib, retain: true, release: true); - } - - static NSXMLDTDNode new1(SentryCocoa _lib) { - final _ret = - _lib._objc_msgSend_2(_lib._class_NSXMLDTDNode1, _lib._sel_new1); - return NSXMLDTDNode._(_ret, _lib, retain: false, release: true); - } - - static NSXMLDTDNode allocWithZone_( - SentryCocoa _lib, ffi.Pointer<_NSZone> zone) { - final _ret = _lib._objc_msgSend_3( - _lib._class_NSXMLDTDNode1, _lib._sel_allocWithZone_1, zone); - return NSXMLDTDNode._(_ret, _lib, retain: false, release: true); - } - - static NSXMLDTDNode alloc(SentryCocoa _lib) { - final _ret = - _lib._objc_msgSend_2(_lib._class_NSXMLDTDNode1, _lib._sel_alloc1); - return NSXMLDTDNode._(_ret, _lib, retain: false, release: true); - } - - static void cancelPreviousPerformRequestsWithTarget_selector_object_( - SentryCocoa _lib, - NSObject aTarget, - ffi.Pointer aSelector, - NSObject anArgument) { - _lib._objc_msgSend_14( - _lib._class_NSXMLDTDNode1, - _lib._sel_cancelPreviousPerformRequestsWithTarget_selector_object_1, - aTarget._id, - aSelector, - anArgument._id); - } - - static void cancelPreviousPerformRequestsWithTarget_( - SentryCocoa _lib, NSObject aTarget) { - _lib._objc_msgSend_15(_lib._class_NSXMLDTDNode1, - _lib._sel_cancelPreviousPerformRequestsWithTarget_1, aTarget._id); - } - - static bool getAccessInstanceVariablesDirectly(SentryCocoa _lib) { - return _lib._objc_msgSend_12( - _lib._class_NSXMLDTDNode1, _lib._sel_accessInstanceVariablesDirectly1); - } - - static bool useStoredAccessor(SentryCocoa _lib) { - return _lib._objc_msgSend_12( - _lib._class_NSXMLDTDNode1, _lib._sel_useStoredAccessor1); - } - - static NSSet keyPathsForValuesAffectingValueForKey_( - SentryCocoa _lib, NSString? key) { - final _ret = _lib._objc_msgSend_58( - _lib._class_NSXMLDTDNode1, - _lib._sel_keyPathsForValuesAffectingValueForKey_1, - key?._id ?? ffi.nullptr); - return NSSet._(_ret, _lib, retain: true, release: true); - } - - static bool automaticallyNotifiesObserversForKey_( - SentryCocoa _lib, NSString? key) { - return _lib._objc_msgSend_59( - _lib._class_NSXMLDTDNode1, - _lib._sel_automaticallyNotifiesObserversForKey_1, - key?._id ?? ffi.nullptr); - } - - static void setKeys_triggerChangeNotificationsForDependentKey_( - SentryCocoa _lib, NSArray? keys, NSString? dependentKey) { - _lib._objc_msgSend_82( - _lib._class_NSXMLDTDNode1, - _lib._sel_setKeys_triggerChangeNotificationsForDependentKey_1, - keys?._id ?? ffi.nullptr, - dependentKey?._id ?? ffi.nullptr); - } - - static NSArray classFallbacksForKeyedArchiver(SentryCocoa _lib) { - final _ret = _lib._objc_msgSend_79( - _lib._class_NSXMLDTDNode1, _lib._sel_classFallbacksForKeyedArchiver1); - return NSArray._(_ret, _lib, retain: true, release: true); - } - - static NSObject classForKeyedUnarchiver(SentryCocoa _lib) { - final _ret = _lib._objc_msgSend_2( - _lib._class_NSXMLDTDNode1, _lib._sel_classForKeyedUnarchiver1); - return NSObject._(_ret, _lib, retain: true, release: true); - } -} - -abstract class NSXMLDTDNodeKind { - static const int NSXMLEntityGeneralKind = 1; - static const int NSXMLEntityParsedKind = 2; - static const int NSXMLEntityUnparsedKind = 3; - static const int NSXMLEntityParameterKind = 4; - static const int NSXMLEntityPredefined = 5; - static const int NSXMLAttributeCDATAKind = 6; - static const int NSXMLAttributeIDKind = 7; - static const int NSXMLAttributeIDRefKind = 8; - static const int NSXMLAttributeIDRefsKind = 9; - static const int NSXMLAttributeEntityKind = 10; - static const int NSXMLAttributeEntitiesKind = 11; - static const int NSXMLAttributeNMTokenKind = 12; - static const int NSXMLAttributeNMTokensKind = 13; - static const int NSXMLAttributeEnumerationKind = 14; - static const int NSXMLAttributeNotationKind = 15; - static const int NSXMLElementDeclarationUndefinedKind = 16; - static const int NSXMLElementDeclarationEmptyKind = 17; - static const int NSXMLElementDeclarationAnyKind = 18; - static const int NSXMLElementDeclarationMixedKind = 19; - static const int NSXMLElementDeclarationElementKind = 20; -} - -/// @warning This class is reserved for hybrid SDKs. Methods may be changed, renamed or removed -/// without notice. If you want to use one of these methods here please open up an issue and let us -/// know. -/// @note The name of this class is supposed to be a bit weird and ugly. The name starts with private -/// on purpose so users don't see it in code completion when typing Sentry. We also add only at the -/// end to make it more obvious you shouldn't use it. -class PrivateSentrySDKOnly extends NSObject { - PrivateSentrySDKOnly._(ffi.Pointer id, SentryCocoa lib, - {bool retain = false, bool release = false}) - : super._(id, lib, retain: retain, release: release); - - /// Returns a [PrivateSentrySDKOnly] that points to the same underlying object as [other]. - static PrivateSentrySDKOnly castFrom(T other) { - return PrivateSentrySDKOnly._(other._id, other._lib, - retain: true, release: true); - } - - /// Returns a [PrivateSentrySDKOnly] that wraps the given raw object pointer. - static PrivateSentrySDKOnly castFromPointer( - SentryCocoa lib, ffi.Pointer other, - {bool retain = false, bool release = false}) { - return PrivateSentrySDKOnly._(other, lib, retain: retain, release: release); - } - - /// Returns whether [obj] is an instance of [PrivateSentrySDKOnly]. - static bool isInstance(_ObjCWrapper obj) { - return obj._lib._objc_msgSend_0(obj._id, obj._lib._sel_isKindOfClass_1, - obj._lib._class_PrivateSentrySDKOnly1); - } - - /// For storing an envelope synchronously to disk. - static void storeEnvelope_(SentryCocoa _lib, SentryEnvelope? envelope) { - _lib._objc_msgSend_1055(_lib._class_PrivateSentrySDKOnly1, - _lib._sel_storeEnvelope_1, envelope?._id ?? ffi.nullptr); - } - - static void captureEnvelope_(SentryCocoa _lib, SentryEnvelope? envelope) { - _lib._objc_msgSend_1055(_lib._class_PrivateSentrySDKOnly1, - _lib._sel_captureEnvelope_1, envelope?._id ?? ffi.nullptr); - } - - /// Create an envelope from @c NSData. Needed for example by Flutter. - static SentryEnvelope envelopeWithData_(SentryCocoa _lib, NSData? data) { - final _ret = _lib._objc_msgSend_1056(_lib._class_PrivateSentrySDKOnly1, - _lib._sel_envelopeWithData_1, data?._id ?? ffi.nullptr); - return SentryEnvelope._(_ret, _lib, retain: true, release: true); - } - - /// Returns the current list of debug images. Be aware that the @c SentryDebugMeta is actually - /// describing a debug image. - /// @warning This assumes a crash has occurred and attempts to read the crash information from each - /// image's data segment, which may not be present or be invalid if a crash has not actually - /// occurred. To avoid this, use the new @c +[getDebugImagesCrashed:] instead. - static NSArray getDebugImages(SentryCocoa _lib) { - final _ret = _lib._objc_msgSend_79( - _lib._class_PrivateSentrySDKOnly1, _lib._sel_getDebugImages1); - return NSArray._(_ret, _lib, retain: true, release: true); - } - - /// Returns the current list of debug images. Be aware that the @c SentryDebugMeta is actually - /// describing a debug image. - /// @param isCrash @c YES if we're collecting binary images for a crash report, @c NO if we're - /// gathering them for other backtrace information, like a performance transaction. If this is for a - /// crash, each image's data section crash info is also included. - static NSArray getDebugImagesCrashed_(SentryCocoa _lib, bool isCrash) { - final _ret = _lib._objc_msgSend_1057(_lib._class_PrivateSentrySDKOnly1, - _lib._sel_getDebugImagesCrashed_1, isCrash); - return NSArray._(_ret, _lib, retain: true, release: true); - } - - /// Override SDK information. - static void setSdkName_andVersionString_( - SentryCocoa _lib, NSString? sdkName, NSString? versionString) { - _lib._objc_msgSend_515( - _lib._class_PrivateSentrySDKOnly1, - _lib._sel_setSdkName_andVersionString_1, - sdkName?._id ?? ffi.nullptr, - versionString?._id ?? ffi.nullptr); - } - - /// Override SDK information. - static void setSdkName_(SentryCocoa _lib, NSString? sdkName) { - _lib._objc_msgSend_192(_lib._class_PrivateSentrySDKOnly1, - _lib._sel_setSdkName_1, sdkName?._id ?? ffi.nullptr); - } - - /// Retrieves the SDK name - static NSString getSdkName(SentryCocoa _lib) { - final _ret = _lib._objc_msgSend_20( - _lib._class_PrivateSentrySDKOnly1, _lib._sel_getSdkName1); - return NSString._(_ret, _lib, retain: true, release: true); - } - - /// Retrieves the SDK version string - static NSString getSdkVersionString(SentryCocoa _lib) { - final _ret = _lib._objc_msgSend_20( - _lib._class_PrivateSentrySDKOnly1, _lib._sel_getSdkVersionString1); - return NSString._(_ret, _lib, retain: true, release: true); - } - - /// Retrieves extra context - static NSDictionary getExtraContext(SentryCocoa _lib) { - final _ret = _lib._objc_msgSend_170( - _lib._class_PrivateSentrySDKOnly1, _lib._sel_getExtraContext1); - return NSDictionary._(_ret, _lib, retain: true, release: true); - } - - /// Start a profiler session associated with the given @c SentryId. - /// @return The system time when the profiler session started. - static int startProfilerForTrace_(SentryCocoa _lib, SentryId? traceId) { - return _lib._objc_msgSend_1058(_lib._class_PrivateSentrySDKOnly1, - _lib._sel_startProfilerForTrace_1, traceId?._id ?? ffi.nullptr); - } - - /// Collect a profiler session data associated with the given @c SentryId. - /// This also discards the profiler. - static NSMutableDictionary collectProfileBetween_and_forTrace_( - SentryCocoa _lib, - int startSystemTime, - int endSystemTime, - SentryId? traceId) { - final _ret = _lib._objc_msgSend_1059( - _lib._class_PrivateSentrySDKOnly1, - _lib._sel_collectProfileBetween_and_forTrace_1, - startSystemTime, - endSystemTime, - traceId?._id ?? ffi.nullptr); - return NSMutableDictionary._(_ret, _lib, retain: true, release: true); - } - - /// Discard profiler session data associated with the given @c SentryId. - /// This only needs to be called in case you haven't collected the profile (and don't intend to). - static void discardProfilerForTrace_(SentryCocoa _lib, SentryId? traceId) { - _lib._objc_msgSend_1060(_lib._class_PrivateSentrySDKOnly1, - _lib._sel_discardProfilerForTrace_1, traceId?._id ?? ffi.nullptr); - } - - static ObjCBlock_ffiVoid_SentryAppStartMeasurement - getOnAppStartMeasurementAvailable(SentryCocoa _lib) { - final _ret = _lib._objc_msgSend_1061(_lib._class_PrivateSentrySDKOnly1, - _lib._sel_onAppStartMeasurementAvailable1); - return ObjCBlock_ffiVoid_SentryAppStartMeasurement._(_ret, _lib); - } - - static void setOnAppStartMeasurementAvailable( - SentryCocoa _lib, ObjCBlock_ffiVoid_SentryAppStartMeasurement value) { - return _lib._objc_msgSend_1062(_lib._class_PrivateSentrySDKOnly1, - _lib._sel_setOnAppStartMeasurementAvailable_1, value._id); - } - - static SentryAppStartMeasurement? getAppStartMeasurement(SentryCocoa _lib) { - final _ret = _lib._objc_msgSend_1063( - _lib._class_PrivateSentrySDKOnly1, _lib._sel_appStartMeasurement1); - return _ret.address == 0 - ? null - : SentryAppStartMeasurement._(_ret, _lib, retain: true, release: true); - } - - static NSString? getInstallationID(SentryCocoa _lib) { - final _ret = _lib._objc_msgSend_20( - _lib._class_PrivateSentrySDKOnly1, _lib._sel_installationID1); - return _ret.address == 0 - ? null - : NSString._(_ret, _lib, retain: true, release: true); - } - - static SentryOptions? getOptions(SentryCocoa _lib) { - final _ret = _lib._objc_msgSend_1064( - _lib._class_PrivateSentrySDKOnly1, _lib._sel_options1); - return _ret.address == 0 - ? null - : SentryOptions._(_ret, _lib, retain: true, release: true); - } - - /// If enabled, the SDK won't send the app start measurement with the first transaction. Instead, if - /// @c enableAutoPerformanceTracing is enabled, the SDK measures the app start and then calls - /// @c onAppStartMeasurementAvailable. Furthermore, the SDK doesn't set all values for the app start - /// measurement because the HybridSDKs initialize the Cocoa SDK too late to receive all - /// notifications. Instead, the SDK sets the @c appStartDuration to @c 0 and the - /// @c didFinishLaunchingTimestamp to @c timeIntervalSinceReferenceDate. - /// @note Default is @c NO. - static bool getAppStartMeasurementHybridSDKMode(SentryCocoa _lib) { - return _lib._objc_msgSend_12(_lib._class_PrivateSentrySDKOnly1, - _lib._sel_appStartMeasurementHybridSDKMode1); - } - - /// If enabled, the SDK won't send the app start measurement with the first transaction. Instead, if - /// @c enableAutoPerformanceTracing is enabled, the SDK measures the app start and then calls - /// @c onAppStartMeasurementAvailable. Furthermore, the SDK doesn't set all values for the app start - /// measurement because the HybridSDKs initialize the Cocoa SDK too late to receive all - /// notifications. Instead, the SDK sets the @c appStartDuration to @c 0 and the - /// @c didFinishLaunchingTimestamp to @c timeIntervalSinceReferenceDate. - /// @note Default is @c NO. - static void setAppStartMeasurementHybridSDKMode( - SentryCocoa _lib, bool value) { - return _lib._objc_msgSend_492(_lib._class_PrivateSentrySDKOnly1, - _lib._sel_setAppStartMeasurementHybridSDKMode_1, value); - } - - static SentryUser userWithDictionary_( - SentryCocoa _lib, NSDictionary? dictionary) { - final _ret = _lib._objc_msgSend_1065(_lib._class_PrivateSentrySDKOnly1, - _lib._sel_userWithDictionary_1, dictionary?._id ?? ffi.nullptr); - return SentryUser._(_ret, _lib, retain: true, release: true); - } - - static SentryBreadcrumb breadcrumbWithDictionary_( - SentryCocoa _lib, NSDictionary? dictionary) { - final _ret = _lib._objc_msgSend_1066(_lib._class_PrivateSentrySDKOnly1, - _lib._sel_breadcrumbWithDictionary_1, dictionary?._id ?? ffi.nullptr); - return SentryBreadcrumb._(_ret, _lib, retain: true, release: true); - } - - @override - PrivateSentrySDKOnly init() { - final _ret = _lib._objc_msgSend_2(_id, _lib._sel_init1); - return PrivateSentrySDKOnly._(_ret, _lib, retain: true, release: true); - } - - static PrivateSentrySDKOnly new1(SentryCocoa _lib) { - final _ret = - _lib._objc_msgSend_2(_lib._class_PrivateSentrySDKOnly1, _lib._sel_new1); - return PrivateSentrySDKOnly._(_ret, _lib, retain: false, release: true); - } - - static PrivateSentrySDKOnly allocWithZone_( - SentryCocoa _lib, ffi.Pointer<_NSZone> zone) { - final _ret = _lib._objc_msgSend_3( - _lib._class_PrivateSentrySDKOnly1, _lib._sel_allocWithZone_1, zone); - return PrivateSentrySDKOnly._(_ret, _lib, retain: false, release: true); - } - - static PrivateSentrySDKOnly alloc(SentryCocoa _lib) { - final _ret = _lib._objc_msgSend_2( - _lib._class_PrivateSentrySDKOnly1, _lib._sel_alloc1); - return PrivateSentrySDKOnly._(_ret, _lib, retain: false, release: true); - } - - static void cancelPreviousPerformRequestsWithTarget_selector_object_( - SentryCocoa _lib, - NSObject aTarget, - ffi.Pointer aSelector, - NSObject anArgument) { - _lib._objc_msgSend_14( - _lib._class_PrivateSentrySDKOnly1, - _lib._sel_cancelPreviousPerformRequestsWithTarget_selector_object_1, - aTarget._id, - aSelector, - anArgument._id); - } - - static void cancelPreviousPerformRequestsWithTarget_( - SentryCocoa _lib, NSObject aTarget) { - _lib._objc_msgSend_15(_lib._class_PrivateSentrySDKOnly1, - _lib._sel_cancelPreviousPerformRequestsWithTarget_1, aTarget._id); - } - - static bool getAccessInstanceVariablesDirectly(SentryCocoa _lib) { - return _lib._objc_msgSend_12(_lib._class_PrivateSentrySDKOnly1, - _lib._sel_accessInstanceVariablesDirectly1); - } - - static bool useStoredAccessor(SentryCocoa _lib) { - return _lib._objc_msgSend_12( - _lib._class_PrivateSentrySDKOnly1, _lib._sel_useStoredAccessor1); - } - - static NSSet keyPathsForValuesAffectingValueForKey_( - SentryCocoa _lib, NSString? key) { - final _ret = _lib._objc_msgSend_58( - _lib._class_PrivateSentrySDKOnly1, - _lib._sel_keyPathsForValuesAffectingValueForKey_1, - key?._id ?? ffi.nullptr); - return NSSet._(_ret, _lib, retain: true, release: true); - } - - static bool automaticallyNotifiesObserversForKey_( - SentryCocoa _lib, NSString? key) { - return _lib._objc_msgSend_59( - _lib._class_PrivateSentrySDKOnly1, - _lib._sel_automaticallyNotifiesObserversForKey_1, - key?._id ?? ffi.nullptr); - } - - static void setKeys_triggerChangeNotificationsForDependentKey_( - SentryCocoa _lib, NSArray? keys, NSString? dependentKey) { - _lib._objc_msgSend_82( - _lib._class_PrivateSentrySDKOnly1, - _lib._sel_setKeys_triggerChangeNotificationsForDependentKey_1, - keys?._id ?? ffi.nullptr, - dependentKey?._id ?? ffi.nullptr); - } - - static NSArray classFallbacksForKeyedArchiver(SentryCocoa _lib) { - final _ret = _lib._objc_msgSend_79(_lib._class_PrivateSentrySDKOnly1, - _lib._sel_classFallbacksForKeyedArchiver1); - return NSArray._(_ret, _lib, retain: true, release: true); - } - - static NSObject classForKeyedUnarchiver(SentryCocoa _lib) { - final _ret = _lib._objc_msgSend_2( - _lib._class_PrivateSentrySDKOnly1, _lib._sel_classForKeyedUnarchiver1); - return NSObject._(_ret, _lib, retain: true, release: true); - } -} - -class SentryEnvelope extends NSObject { - SentryEnvelope._(ffi.Pointer id, SentryCocoa lib, - {bool retain = false, bool release = false}) - : super._(id, lib, retain: retain, release: release); - - /// Returns a [SentryEnvelope] that points to the same underlying object as [other]. - static SentryEnvelope castFrom(T other) { - return SentryEnvelope._(other._id, other._lib, retain: true, release: true); - } - - /// Returns a [SentryEnvelope] that wraps the given raw object pointer. - static SentryEnvelope castFromPointer( - SentryCocoa lib, ffi.Pointer other, - {bool retain = false, bool release = false}) { - return SentryEnvelope._(other, lib, retain: retain, release: release); - } - - /// Returns whether [obj] is an instance of [SentryEnvelope]. - static bool isInstance(_ObjCWrapper obj) { - return obj._lib._objc_msgSend_0(obj._id, obj._lib._sel_isKindOfClass_1, - obj._lib._class_SentryEnvelope1); - } - - @override - SentryEnvelope init() { - final _ret = _lib._objc_msgSend_2(_id, _lib._sel_init1); - return SentryEnvelope._(_ret, _lib, retain: true, release: true); - } - - static SentryEnvelope new1(SentryCocoa _lib) { - final _ret = - _lib._objc_msgSend_2(_lib._class_SentryEnvelope1, _lib._sel_new1); - return SentryEnvelope._(_ret, _lib, retain: false, release: true); - } - - SentryEnvelope initWithId_singleItem_( - SentryId? id, SentryEnvelopeItem? item) { - final _ret = _lib._objc_msgSend_1045(_id, _lib._sel_initWithId_singleItem_1, - id?._id ?? ffi.nullptr, item?._id ?? ffi.nullptr); - return SentryEnvelope._(_ret, _lib, retain: true, release: true); - } - - SentryEnvelope initWithHeader_singleItem_( - SentryEnvelopeHeader? header, SentryEnvelopeItem? item) { - final _ret = _lib._objc_msgSend_1051( - _id, - _lib._sel_initWithHeader_singleItem_1, - header?._id ?? ffi.nullptr, - item?._id ?? ffi.nullptr); - return SentryEnvelope._(_ret, _lib, retain: true, release: true); - } - - SentryEnvelope initWithId_items_(SentryId? id, NSArray? items) { - final _ret = _lib._objc_msgSend_1052(_id, _lib._sel_initWithId_items_1, - id?._id ?? ffi.nullptr, items?._id ?? ffi.nullptr); - return SentryEnvelope._(_ret, _lib, retain: true, release: true); - } - - /// Initializes a @c SentryEnvelope with a single session. - /// @param session to init the envelope with. - SentryEnvelope initWithSession_(SentrySession? session) { - final _ret = _lib._objc_msgSend_1040( - _id, _lib._sel_initWithSession_1, session?._id ?? ffi.nullptr); - return SentryEnvelope._(_ret, _lib, retain: true, release: true); - } - - /// Initializes a @c SentryEnvelope with a list of sessions. - /// Can be used when an operation that starts a session closes an ongoing session. - /// @param sessions to init the envelope with. - SentryEnvelope initWithSessions_(NSArray? sessions) { - final _ret = _lib._objc_msgSend_67( - _id, _lib._sel_initWithSessions_1, sessions?._id ?? ffi.nullptr); - return SentryEnvelope._(_ret, _lib, retain: true, release: true); - } - - SentryEnvelope initWithHeader_items_( - SentryEnvelopeHeader? header, NSArray? items) { - final _ret = _lib._objc_msgSend_1053(_id, _lib._sel_initWithHeader_items_1, - header?._id ?? ffi.nullptr, items?._id ?? ffi.nullptr); - return SentryEnvelope._(_ret, _lib, retain: true, release: true); - } - - /// Convenience init for a single event. - SentryEnvelope initWithEvent_(SentryEvent? event) { - final _ret = _lib._objc_msgSend_1039( - _id, _lib._sel_initWithEvent_1, event?._id ?? ffi.nullptr); - return SentryEnvelope._(_ret, _lib, retain: true, release: true); - } - - SentryEnvelope initWithUserFeedback_(SentryUserFeedback? userFeedback) { - final _ret = _lib._objc_msgSend_1041(_id, _lib._sel_initWithUserFeedback_1, - userFeedback?._id ?? ffi.nullptr); - return SentryEnvelope._(_ret, _lib, retain: true, release: true); - } - - /// The envelope header. - SentryEnvelopeHeader? get header { - final _ret = _lib._objc_msgSend_1054(_id, _lib._sel_header1); - return _ret.address == 0 - ? null - : SentryEnvelopeHeader._(_ret, _lib, retain: true, release: true); - } - - /// The envelope items. - NSArray? get items { - final _ret = _lib._objc_msgSend_79(_id, _lib._sel_items1); - return _ret.address == 0 - ? null - : NSArray._(_ret, _lib, retain: true, release: true); - } - - static SentryEnvelope allocWithZone_( - SentryCocoa _lib, ffi.Pointer<_NSZone> zone) { - final _ret = _lib._objc_msgSend_3( - _lib._class_SentryEnvelope1, _lib._sel_allocWithZone_1, zone); - return SentryEnvelope._(_ret, _lib, retain: false, release: true); - } - - static SentryEnvelope alloc(SentryCocoa _lib) { - final _ret = - _lib._objc_msgSend_2(_lib._class_SentryEnvelope1, _lib._sel_alloc1); - return SentryEnvelope._(_ret, _lib, retain: false, release: true); - } - - static void cancelPreviousPerformRequestsWithTarget_selector_object_( - SentryCocoa _lib, - NSObject aTarget, - ffi.Pointer aSelector, - NSObject anArgument) { - _lib._objc_msgSend_14( - _lib._class_SentryEnvelope1, - _lib._sel_cancelPreviousPerformRequestsWithTarget_selector_object_1, - aTarget._id, - aSelector, - anArgument._id); - } - - static void cancelPreviousPerformRequestsWithTarget_( - SentryCocoa _lib, NSObject aTarget) { - _lib._objc_msgSend_15(_lib._class_SentryEnvelope1, - _lib._sel_cancelPreviousPerformRequestsWithTarget_1, aTarget._id); - } - - static bool getAccessInstanceVariablesDirectly(SentryCocoa _lib) { - return _lib._objc_msgSend_12(_lib._class_SentryEnvelope1, - _lib._sel_accessInstanceVariablesDirectly1); - } - - static bool useStoredAccessor(SentryCocoa _lib) { - return _lib._objc_msgSend_12( - _lib._class_SentryEnvelope1, _lib._sel_useStoredAccessor1); - } - - static NSSet keyPathsForValuesAffectingValueForKey_( - SentryCocoa _lib, NSString? key) { - final _ret = _lib._objc_msgSend_58( - _lib._class_SentryEnvelope1, - _lib._sel_keyPathsForValuesAffectingValueForKey_1, - key?._id ?? ffi.nullptr); - return NSSet._(_ret, _lib, retain: true, release: true); - } - - static bool automaticallyNotifiesObserversForKey_( - SentryCocoa _lib, NSString? key) { - return _lib._objc_msgSend_59( - _lib._class_SentryEnvelope1, - _lib._sel_automaticallyNotifiesObserversForKey_1, - key?._id ?? ffi.nullptr); - } - - static void setKeys_triggerChangeNotificationsForDependentKey_( - SentryCocoa _lib, NSArray? keys, NSString? dependentKey) { - _lib._objc_msgSend_82( - _lib._class_SentryEnvelope1, - _lib._sel_setKeys_triggerChangeNotificationsForDependentKey_1, - keys?._id ?? ffi.nullptr, - dependentKey?._id ?? ffi.nullptr); - } - - static NSArray classFallbacksForKeyedArchiver(SentryCocoa _lib) { - final _ret = _lib._objc_msgSend_79( - _lib._class_SentryEnvelope1, _lib._sel_classFallbacksForKeyedArchiver1); - return NSArray._(_ret, _lib, retain: true, release: true); + _lib._class_NSXMLDTD1, + _lib._sel_attributeWithName_stringValue_1, + name?._id ?? ffi.nullptr, + stringValue?._id ?? ffi.nullptr); + return NSObject._(_ret, _lib, retain: true, release: true); } - static NSObject classForKeyedUnarchiver(SentryCocoa _lib) { - final _ret = _lib._objc_msgSend_2( - _lib._class_SentryEnvelope1, _lib._sel_classForKeyedUnarchiver1); + static NSObject attributeWithName_URI_stringValue_( + SentryCocoa _lib, NSString? name, NSString? URI, NSString? stringValue) { + final _ret = _lib._objc_msgSend_26( + _lib._class_NSXMLDTD1, + _lib._sel_attributeWithName_URI_stringValue_1, + name?._id ?? ffi.nullptr, + URI?._id ?? ffi.nullptr, + stringValue?._id ?? ffi.nullptr); return NSObject._(_ret, _lib, retain: true, release: true); } -} -class SentryId extends NSObject { - SentryId._(ffi.Pointer id, SentryCocoa lib, - {bool retain = false, bool release = false}) - : super._(id, lib, retain: retain, release: release); - - /// Returns a [SentryId] that points to the same underlying object as [other]. - static SentryId castFrom(T other) { - return SentryId._(other._id, other._lib, retain: true, release: true); + static NSObject namespaceWithName_stringValue_( + SentryCocoa _lib, NSString? name, NSString? stringValue) { + final _ret = _lib._objc_msgSend_165( + _lib._class_NSXMLDTD1, + _lib._sel_namespaceWithName_stringValue_1, + name?._id ?? ffi.nullptr, + stringValue?._id ?? ffi.nullptr); + return NSObject._(_ret, _lib, retain: true, release: true); } - /// Returns a [SentryId] that wraps the given raw object pointer. - static SentryId castFromPointer( - SentryCocoa lib, ffi.Pointer other, - {bool retain = false, bool release = false}) { - return SentryId._(other, lib, retain: retain, release: release); + static NSObject processingInstructionWithName_stringValue_( + SentryCocoa _lib, NSString? name, NSString? stringValue) { + final _ret = _lib._objc_msgSend_165( + _lib._class_NSXMLDTD1, + _lib._sel_processingInstructionWithName_stringValue_1, + name?._id ?? ffi.nullptr, + stringValue?._id ?? ffi.nullptr); + return NSObject._(_ret, _lib, retain: true, release: true); } - /// Returns whether [obj] is an instance of [SentryId]. - static bool isInstance(_ObjCWrapper obj) { - return obj._lib._objc_msgSend_0( - obj._id, obj._lib._sel_isKindOfClass_1, obj._lib._class_SentryId1); + static NSObject commentWithStringValue_( + SentryCocoa _lib, NSString? stringValue) { + final _ret = _lib._objc_msgSend_30(_lib._class_NSXMLDTD1, + _lib._sel_commentWithStringValue_1, stringValue?._id ?? ffi.nullptr); + return NSObject._(_ret, _lib, retain: true, release: true); } - /// Creates a @c SentryId with a random UUID. - @override - SentryId init() { - final _ret = _lib._objc_msgSend_2(_id, _lib._sel_init1); - return SentryId._(_ret, _lib, retain: true, release: true); + static NSObject textWithStringValue_( + SentryCocoa _lib, NSString? stringValue) { + final _ret = _lib._objc_msgSend_30(_lib._class_NSXMLDTD1, + _lib._sel_textWithStringValue_1, stringValue?._id ?? ffi.nullptr); + return NSObject._(_ret, _lib, retain: true, release: true); } - /// Creates a SentryId with the given UUID. - SentryId initWithUUID_(NSUUID? uuid) { - final _ret = _lib._objc_msgSend_1037( - _id, _lib._sel_initWithUUID_1, uuid?._id ?? ffi.nullptr); - return SentryId._(_ret, _lib, retain: true, release: true); + static NSObject DTDNodeWithXMLString_(SentryCocoa _lib, NSString? string) { + final _ret = _lib._objc_msgSend_30(_lib._class_NSXMLDTD1, + _lib._sel_DTDNodeWithXMLString_1, string?._id ?? ffi.nullptr); + return NSObject._(_ret, _lib, retain: true, release: true); } - /// Creates a @c SentryId from a 32 character hexadecimal string without dashes such as - /// "12c2d058d58442709aa2eca08bf20986" or a 36 character hexadecimal string such as such as - /// "12c2d058-d584-4270-9aa2-eca08bf20986". - /// @return SentryId.empty for invalid strings. - SentryId initWithUUIDString_(NSString? string) { - final _ret = _lib._objc_msgSend_30( - _id, _lib._sel_initWithUUIDString_1, string?._id ?? ffi.nullptr); - return SentryId._(_ret, _lib, retain: true, release: true); + static NSString localNameForName_(SentryCocoa _lib, NSString? name) { + final _ret = _lib._objc_msgSend_64(_lib._class_NSXMLDTD1, + _lib._sel_localNameForName_1, name?._id ?? ffi.nullptr); + return NSString._(_ret, _lib, retain: true, release: true); } - /// Returns a 32 lowercase character hexadecimal string description of the @c SentryId, such as - /// "12c2d058d58442709aa2eca08bf20986". - NSString? get sentryIdString { - final _ret = _lib._objc_msgSend_20(_id, _lib._sel_sentryIdString1); - return _ret.address == 0 - ? null - : NSString._(_ret, _lib, retain: true, release: true); + static NSString prefixForName_(SentryCocoa _lib, NSString? name) { + final _ret = _lib._objc_msgSend_64(_lib._class_NSXMLDTD1, + _lib._sel_prefixForName_1, name?._id ?? ffi.nullptr); + return NSString._(_ret, _lib, retain: true, release: true); } - /// A @c SentryId with an empty UUID "00000000000000000000000000000000". - static SentryId? getEmpty(SentryCocoa _lib) { - final _ret = - _lib._objc_msgSend_1038(_lib._class_SentryId1, _lib._sel_empty1); - return _ret.address == 0 - ? null - : SentryId._(_ret, _lib, retain: true, release: true); + static NSXMLNode predefinedNamespaceForPrefix_( + SentryCocoa _lib, NSString? name) { + final _ret = _lib._objc_msgSend_1032(_lib._class_NSXMLDTD1, + _lib._sel_predefinedNamespaceForPrefix_1, name?._id ?? ffi.nullptr); + return NSXMLNode._(_ret, _lib, retain: true, release: true); } - static SentryId new1(SentryCocoa _lib) { - final _ret = _lib._objc_msgSend_2(_lib._class_SentryId1, _lib._sel_new1); - return SentryId._(_ret, _lib, retain: false, release: true); + static NSXMLDTD new1(SentryCocoa _lib) { + final _ret = _lib._objc_msgSend_2(_lib._class_NSXMLDTD1, _lib._sel_new1); + return NSXMLDTD._(_ret, _lib, retain: false, release: true); } - static SentryId allocWithZone_(SentryCocoa _lib, ffi.Pointer<_NSZone> zone) { + static NSXMLDTD allocWithZone_(SentryCocoa _lib, ffi.Pointer<_NSZone> zone) { final _ret = _lib._objc_msgSend_3( - _lib._class_SentryId1, _lib._sel_allocWithZone_1, zone); - return SentryId._(_ret, _lib, retain: false, release: true); + _lib._class_NSXMLDTD1, _lib._sel_allocWithZone_1, zone); + return NSXMLDTD._(_ret, _lib, retain: false, release: true); } - static SentryId alloc(SentryCocoa _lib) { - final _ret = _lib._objc_msgSend_2(_lib._class_SentryId1, _lib._sel_alloc1); - return SentryId._(_ret, _lib, retain: false, release: true); + static NSXMLDTD alloc(SentryCocoa _lib) { + final _ret = _lib._objc_msgSend_2(_lib._class_NSXMLDTD1, _lib._sel_alloc1); + return NSXMLDTD._(_ret, _lib, retain: false, release: true); } static void cancelPreviousPerformRequestsWithTarget_selector_object_( @@ -70964,7 +70273,7 @@ class SentryId extends NSObject { ffi.Pointer aSelector, NSObject anArgument) { _lib._objc_msgSend_14( - _lib._class_SentryId1, + _lib._class_NSXMLDTD1, _lib._sel_cancelPreviousPerformRequestsWithTarget_selector_object_1, aTarget._id, aSelector, @@ -70973,24 +70282,24 @@ class SentryId extends NSObject { static void cancelPreviousPerformRequestsWithTarget_( SentryCocoa _lib, NSObject aTarget) { - _lib._objc_msgSend_15(_lib._class_SentryId1, + _lib._objc_msgSend_15(_lib._class_NSXMLDTD1, _lib._sel_cancelPreviousPerformRequestsWithTarget_1, aTarget._id); } static bool getAccessInstanceVariablesDirectly(SentryCocoa _lib) { return _lib._objc_msgSend_12( - _lib._class_SentryId1, _lib._sel_accessInstanceVariablesDirectly1); + _lib._class_NSXMLDTD1, _lib._sel_accessInstanceVariablesDirectly1); } static bool useStoredAccessor(SentryCocoa _lib) { return _lib._objc_msgSend_12( - _lib._class_SentryId1, _lib._sel_useStoredAccessor1); + _lib._class_NSXMLDTD1, _lib._sel_useStoredAccessor1); } static NSSet keyPathsForValuesAffectingValueForKey_( SentryCocoa _lib, NSString? key) { final _ret = _lib._objc_msgSend_58( - _lib._class_SentryId1, + _lib._class_NSXMLDTD1, _lib._sel_keyPathsForValuesAffectingValueForKey_1, key?._id ?? ffi.nullptr); return NSSet._(_ret, _lib, retain: true, release: true); @@ -70999,7 +70308,7 @@ class SentryId extends NSObject { static bool automaticallyNotifiesObserversForKey_( SentryCocoa _lib, NSString? key) { return _lib._objc_msgSend_59( - _lib._class_SentryId1, + _lib._class_NSXMLDTD1, _lib._sel_automaticallyNotifiesObserversForKey_1, key?._id ?? ffi.nullptr); } @@ -71007,7 +70316,7 @@ class SentryId extends NSObject { static void setKeys_triggerChangeNotificationsForDependentKey_( SentryCocoa _lib, NSArray? keys, NSString? dependentKey) { _lib._objc_msgSend_82( - _lib._class_SentryId1, + _lib._class_NSXMLDTD1, _lib._sel_setKeys_triggerChangeNotificationsForDependentKey_1, keys?._id ?? ffi.nullptr, dependentKey?._id ?? ffi.nullptr); @@ -71015,260 +70324,260 @@ class SentryId extends NSObject { static NSArray classFallbacksForKeyedArchiver(SentryCocoa _lib) { final _ret = _lib._objc_msgSend_79( - _lib._class_SentryId1, _lib._sel_classFallbacksForKeyedArchiver1); + _lib._class_NSXMLDTD1, _lib._sel_classFallbacksForKeyedArchiver1); return NSArray._(_ret, _lib, retain: true, release: true); } static NSObject classForKeyedUnarchiver(SentryCocoa _lib) { final _ret = _lib._objc_msgSend_2( - _lib._class_SentryId1, _lib._sel_classForKeyedUnarchiver1); + _lib._class_NSXMLDTD1, _lib._sel_classForKeyedUnarchiver1); return NSObject._(_ret, _lib, retain: true, release: true); } } -class NSUUID extends NSObject { - NSUUID._(ffi.Pointer id, SentryCocoa lib, +class NSXMLDTDNode extends NSXMLNode { + NSXMLDTDNode._(ffi.Pointer id, SentryCocoa lib, {bool retain = false, bool release = false}) : super._(id, lib, retain: retain, release: release); - /// Returns a [NSUUID] that points to the same underlying object as [other]. - static NSUUID castFrom(T other) { - return NSUUID._(other._id, other._lib, retain: true, release: true); + /// Returns a [NSXMLDTDNode] that points to the same underlying object as [other]. + static NSXMLDTDNode castFrom(T other) { + return NSXMLDTDNode._(other._id, other._lib, retain: true, release: true); } - /// Returns a [NSUUID] that wraps the given raw object pointer. - static NSUUID castFromPointer(SentryCocoa lib, ffi.Pointer other, + /// Returns a [NSXMLDTDNode] that wraps the given raw object pointer. + static NSXMLDTDNode castFromPointer( + SentryCocoa lib, ffi.Pointer other, {bool retain = false, bool release = false}) { - return NSUUID._(other, lib, retain: retain, release: release); + return NSXMLDTDNode._(other, lib, retain: retain, release: release); } - /// Returns whether [obj] is an instance of [NSUUID]. + /// Returns whether [obj] is an instance of [NSXMLDTDNode]. static bool isInstance(_ObjCWrapper obj) { return obj._lib._objc_msgSend_0( - obj._id, obj._lib._sel_isKindOfClass_1, obj._lib._class_NSUUID1); + obj._id, obj._lib._sel_isKindOfClass_1, obj._lib._class_NSXMLDTDNode1); } - static NSUUID UUID(SentryCocoa _lib) { - final _ret = _lib._objc_msgSend_2(_lib._class_NSUUID1, _lib._sel_UUID1); - return NSUUID._(_ret, _lib, retain: true, release: true); + NSXMLDTDNode initWithXMLString_(NSString? string) { + final _ret = _lib._objc_msgSend_30( + _id, _lib._sel_initWithXMLString_1, string?._id ?? ffi.nullptr); + return NSXMLDTDNode._(_ret, _lib, retain: true, release: true); } @override - NSUUID init() { - final _ret = _lib._objc_msgSend_2(_id, _lib._sel_init1); - return NSUUID._(_ret, _lib, retain: true, release: true); + NSXMLDTDNode initWithKind_options_(int kind, int options) { + final _ret = _lib._objc_msgSend_1016( + _id, _lib._sel_initWithKind_options_1, kind, options); + return NSXMLDTDNode._(_ret, _lib, retain: true, release: true); } - NSUUID initWithUUIDString_(NSString? string) { - final _ret = _lib._objc_msgSend_30( - _id, _lib._sel_initWithUUIDString_1, string?._id ?? ffi.nullptr); - return NSUUID._(_ret, _lib, retain: true, release: true); + @override + NSXMLDTDNode init() { + final _ret = _lib._objc_msgSend_2(_id, _lib._sel_init1); + return NSXMLDTDNode._(_ret, _lib, retain: true, release: true); } - NSUUID initWithUUIDBytes_(ffi.Pointer bytes) { - final _ret = - _lib._objc_msgSend_1034(_id, _lib._sel_initWithUUIDBytes_1, bytes); - return NSUUID._(_ret, _lib, retain: true, release: true); + int get DTDKind { + return _lib._objc_msgSend_1030(_id, _lib._sel_DTDKind1); } - void getUUIDBytes_(ffi.Pointer uuid) { - _lib._objc_msgSend_1035(_id, _lib._sel_getUUIDBytes_1, uuid); + set DTDKind(int value) { + return _lib._objc_msgSend_1031(_id, _lib._sel_setDTDKind_1, value); } - int compare_(NSUUID? otherUUID) { - return _lib._objc_msgSend_1036( - _id, _lib._sel_compare_1, otherUUID?._id ?? ffi.nullptr); + bool get external1 { + return _lib._objc_msgSend_12(_id, _lib._sel_isExternal1); } - NSString? get UUIDString { - final _ret = _lib._objc_msgSend_20(_id, _lib._sel_UUIDString1); + NSString? get publicID { + final _ret = _lib._objc_msgSend_20(_id, _lib._sel_publicID1); return _ret.address == 0 ? null : NSString._(_ret, _lib, retain: true, release: true); } - static NSUUID new1(SentryCocoa _lib) { - final _ret = _lib._objc_msgSend_2(_lib._class_NSUUID1, _lib._sel_new1); - return NSUUID._(_ret, _lib, retain: false, release: true); - } - - static NSUUID allocWithZone_(SentryCocoa _lib, ffi.Pointer<_NSZone> zone) { - final _ret = _lib._objc_msgSend_3( - _lib._class_NSUUID1, _lib._sel_allocWithZone_1, zone); - return NSUUID._(_ret, _lib, retain: false, release: true); + set publicID(NSString? value) { + return _lib._objc_msgSend_509( + _id, _lib._sel_setPublicID_1, value?._id ?? ffi.nullptr); } - static NSUUID alloc(SentryCocoa _lib) { - final _ret = _lib._objc_msgSend_2(_lib._class_NSUUID1, _lib._sel_alloc1); - return NSUUID._(_ret, _lib, retain: false, release: true); + NSString? get systemID { + final _ret = _lib._objc_msgSend_20(_id, _lib._sel_systemID1); + return _ret.address == 0 + ? null + : NSString._(_ret, _lib, retain: true, release: true); } - static void cancelPreviousPerformRequestsWithTarget_selector_object_( - SentryCocoa _lib, - NSObject aTarget, - ffi.Pointer aSelector, - NSObject anArgument) { - _lib._objc_msgSend_14( - _lib._class_NSUUID1, - _lib._sel_cancelPreviousPerformRequestsWithTarget_selector_object_1, - aTarget._id, - aSelector, - anArgument._id); + set systemID(NSString? value) { + return _lib._objc_msgSend_509( + _id, _lib._sel_setSystemID_1, value?._id ?? ffi.nullptr); } - static void cancelPreviousPerformRequestsWithTarget_( - SentryCocoa _lib, NSObject aTarget) { - _lib._objc_msgSend_15(_lib._class_NSUUID1, - _lib._sel_cancelPreviousPerformRequestsWithTarget_1, aTarget._id); + NSString? get notationName { + final _ret = _lib._objc_msgSend_20(_id, _lib._sel_notationName1); + return _ret.address == 0 + ? null + : NSString._(_ret, _lib, retain: true, release: true); } - static bool getAccessInstanceVariablesDirectly(SentryCocoa _lib) { - return _lib._objc_msgSend_12( - _lib._class_NSUUID1, _lib._sel_accessInstanceVariablesDirectly1); + set notationName(NSString? value) { + return _lib._objc_msgSend_509( + _id, _lib._sel_setNotationName_1, value?._id ?? ffi.nullptr); } - static bool useStoredAccessor(SentryCocoa _lib) { - return _lib._objc_msgSend_12( - _lib._class_NSUUID1, _lib._sel_useStoredAccessor1); + @override + NSXMLDTDNode initWithKind_(int kind) { + final _ret = _lib._objc_msgSend_1015(_id, _lib._sel_initWithKind_1, kind); + return NSXMLDTDNode._(_ret, _lib, retain: true, release: true); } - static NSSet keyPathsForValuesAffectingValueForKey_( - SentryCocoa _lib, NSString? key) { - final _ret = _lib._objc_msgSend_58( - _lib._class_NSUUID1, - _lib._sel_keyPathsForValuesAffectingValueForKey_1, - key?._id ?? ffi.nullptr); - return NSSet._(_ret, _lib, retain: true, release: true); + static NSObject document(SentryCocoa _lib) { + final _ret = + _lib._objc_msgSend_2(_lib._class_NSXMLDTDNode1, _lib._sel_document1); + return NSObject._(_ret, _lib, retain: true, release: true); } - static bool automaticallyNotifiesObserversForKey_( - SentryCocoa _lib, NSString? key) { - return _lib._objc_msgSend_59( - _lib._class_NSUUID1, - _lib._sel_automaticallyNotifiesObserversForKey_1, - key?._id ?? ffi.nullptr); + static NSObject documentWithRootElement_( + SentryCocoa _lib, NSXMLElement? element) { + final _ret = _lib._objc_msgSend_1017(_lib._class_NSXMLDTDNode1, + _lib._sel_documentWithRootElement_1, element?._id ?? ffi.nullptr); + return NSObject._(_ret, _lib, retain: true, release: true); } - static void setKeys_triggerChangeNotificationsForDependentKey_( - SentryCocoa _lib, NSArray? keys, NSString? dependentKey) { - _lib._objc_msgSend_82( - _lib._class_NSUUID1, - _lib._sel_setKeys_triggerChangeNotificationsForDependentKey_1, - keys?._id ?? ffi.nullptr, - dependentKey?._id ?? ffi.nullptr); + static NSObject elementWithName_(SentryCocoa _lib, NSString? name) { + final _ret = _lib._objc_msgSend_30(_lib._class_NSXMLDTDNode1, + _lib._sel_elementWithName_1, name?._id ?? ffi.nullptr); + return NSObject._(_ret, _lib, retain: true, release: true); } - static NSArray classFallbacksForKeyedArchiver(SentryCocoa _lib) { - final _ret = _lib._objc_msgSend_79( - _lib._class_NSUUID1, _lib._sel_classFallbacksForKeyedArchiver1); - return NSArray._(_ret, _lib, retain: true, release: true); + static NSObject elementWithName_URI_( + SentryCocoa _lib, NSString? name, NSString? URI) { + final _ret = _lib._objc_msgSend_165( + _lib._class_NSXMLDTDNode1, + _lib._sel_elementWithName_URI_1, + name?._id ?? ffi.nullptr, + URI?._id ?? ffi.nullptr); + return NSObject._(_ret, _lib, retain: true, release: true); } - static NSObject classForKeyedUnarchiver(SentryCocoa _lib) { - final _ret = _lib._objc_msgSend_2( - _lib._class_NSUUID1, _lib._sel_classForKeyedUnarchiver1); + static NSObject elementWithName_stringValue_( + SentryCocoa _lib, NSString? name, NSString? string) { + final _ret = _lib._objc_msgSend_165( + _lib._class_NSXMLDTDNode1, + _lib._sel_elementWithName_stringValue_1, + name?._id ?? ffi.nullptr, + string?._id ?? ffi.nullptr); return NSObject._(_ret, _lib, retain: true, release: true); } -} -class SentryEnvelopeItem extends NSObject { - SentryEnvelopeItem._(ffi.Pointer id, SentryCocoa lib, - {bool retain = false, bool release = false}) - : super._(id, lib, retain: retain, release: release); - - /// Returns a [SentryEnvelopeItem] that points to the same underlying object as [other]. - static SentryEnvelopeItem castFrom(T other) { - return SentryEnvelopeItem._(other._id, other._lib, - retain: true, release: true); + static NSObject elementWithName_children_attributes_(SentryCocoa _lib, + NSString? name, NSArray? children, NSArray? attributes) { + final _ret = _lib._objc_msgSend_1018( + _lib._class_NSXMLDTDNode1, + _lib._sel_elementWithName_children_attributes_1, + name?._id ?? ffi.nullptr, + children?._id ?? ffi.nullptr, + attributes?._id ?? ffi.nullptr); + return NSObject._(_ret, _lib, retain: true, release: true); } - /// Returns a [SentryEnvelopeItem] that wraps the given raw object pointer. - static SentryEnvelopeItem castFromPointer( - SentryCocoa lib, ffi.Pointer other, - {bool retain = false, bool release = false}) { - return SentryEnvelopeItem._(other, lib, retain: retain, release: release); + static NSObject attributeWithName_stringValue_( + SentryCocoa _lib, NSString? name, NSString? stringValue) { + final _ret = _lib._objc_msgSend_165( + _lib._class_NSXMLDTDNode1, + _lib._sel_attributeWithName_stringValue_1, + name?._id ?? ffi.nullptr, + stringValue?._id ?? ffi.nullptr); + return NSObject._(_ret, _lib, retain: true, release: true); } - /// Returns whether [obj] is an instance of [SentryEnvelopeItem]. - static bool isInstance(_ObjCWrapper obj) { - return obj._lib._objc_msgSend_0(obj._id, obj._lib._sel_isKindOfClass_1, - obj._lib._class_SentryEnvelopeItem1); + static NSObject attributeWithName_URI_stringValue_( + SentryCocoa _lib, NSString? name, NSString? URI, NSString? stringValue) { + final _ret = _lib._objc_msgSend_26( + _lib._class_NSXMLDTDNode1, + _lib._sel_attributeWithName_URI_stringValue_1, + name?._id ?? ffi.nullptr, + URI?._id ?? ffi.nullptr, + stringValue?._id ?? ffi.nullptr); + return NSObject._(_ret, _lib, retain: true, release: true); } - @override - SentryEnvelopeItem init() { - final _ret = _lib._objc_msgSend_2(_id, _lib._sel_init1); - return SentryEnvelopeItem._(_ret, _lib, retain: true, release: true); + static NSObject namespaceWithName_stringValue_( + SentryCocoa _lib, NSString? name, NSString? stringValue) { + final _ret = _lib._objc_msgSend_165( + _lib._class_NSXMLDTDNode1, + _lib._sel_namespaceWithName_stringValue_1, + name?._id ?? ffi.nullptr, + stringValue?._id ?? ffi.nullptr); + return NSObject._(_ret, _lib, retain: true, release: true); } - static SentryEnvelopeItem new1(SentryCocoa _lib) { - final _ret = - _lib._objc_msgSend_2(_lib._class_SentryEnvelopeItem1, _lib._sel_new1); - return SentryEnvelopeItem._(_ret, _lib, retain: false, release: true); + static NSObject processingInstructionWithName_stringValue_( + SentryCocoa _lib, NSString? name, NSString? stringValue) { + final _ret = _lib._objc_msgSend_165( + _lib._class_NSXMLDTDNode1, + _lib._sel_processingInstructionWithName_stringValue_1, + name?._id ?? ffi.nullptr, + stringValue?._id ?? ffi.nullptr); + return NSObject._(_ret, _lib, retain: true, release: true); } - SentryEnvelopeItem initWithEvent_(SentryEvent? event) { - final _ret = _lib._objc_msgSend_1039( - _id, _lib._sel_initWithEvent_1, event?._id ?? ffi.nullptr); - return SentryEnvelopeItem._(_ret, _lib, retain: true, release: true); + static NSObject commentWithStringValue_( + SentryCocoa _lib, NSString? stringValue) { + final _ret = _lib._objc_msgSend_30(_lib._class_NSXMLDTDNode1, + _lib._sel_commentWithStringValue_1, stringValue?._id ?? ffi.nullptr); + return NSObject._(_ret, _lib, retain: true, release: true); } - SentryEnvelopeItem initWithSession_(SentrySession? session) { - final _ret = _lib._objc_msgSend_1040( - _id, _lib._sel_initWithSession_1, session?._id ?? ffi.nullptr); - return SentryEnvelopeItem._(_ret, _lib, retain: true, release: true); + static NSObject textWithStringValue_( + SentryCocoa _lib, NSString? stringValue) { + final _ret = _lib._objc_msgSend_30(_lib._class_NSXMLDTDNode1, + _lib._sel_textWithStringValue_1, stringValue?._id ?? ffi.nullptr); + return NSObject._(_ret, _lib, retain: true, release: true); } - SentryEnvelopeItem initWithUserFeedback_(SentryUserFeedback? userFeedback) { - final _ret = _lib._objc_msgSend_1041(_id, _lib._sel_initWithUserFeedback_1, - userFeedback?._id ?? ffi.nullptr); - return SentryEnvelopeItem._(_ret, _lib, retain: true, release: true); + static NSObject DTDNodeWithXMLString_(SentryCocoa _lib, NSString? string) { + final _ret = _lib._objc_msgSend_30(_lib._class_NSXMLDTDNode1, + _lib._sel_DTDNodeWithXMLString_1, string?._id ?? ffi.nullptr); + return NSObject._(_ret, _lib, retain: true, release: true); } - SentryEnvelopeItem initWithAttachment_maxAttachmentSize_( - SentryAttachment? attachment, int maxAttachmentSize) { - final _ret = _lib._objc_msgSend_1042( - _id, - _lib._sel_initWithAttachment_maxAttachmentSize_1, - attachment?._id ?? ffi.nullptr, - maxAttachmentSize); - return SentryEnvelopeItem._(_ret, _lib, retain: true, release: true); + static NSString localNameForName_(SentryCocoa _lib, NSString? name) { + final _ret = _lib._objc_msgSend_64(_lib._class_NSXMLDTDNode1, + _lib._sel_localNameForName_1, name?._id ?? ffi.nullptr); + return NSString._(_ret, _lib, retain: true, release: true); } - SentryEnvelopeItem initWithHeader_data_( - SentryEnvelopeItemHeader? header, NSData? data) { - final _ret = _lib._objc_msgSend_1043(_id, _lib._sel_initWithHeader_data_1, - header?._id ?? ffi.nullptr, data?._id ?? ffi.nullptr); - return SentryEnvelopeItem._(_ret, _lib, retain: true, release: true); + static NSString prefixForName_(SentryCocoa _lib, NSString? name) { + final _ret = _lib._objc_msgSend_64(_lib._class_NSXMLDTDNode1, + _lib._sel_prefixForName_1, name?._id ?? ffi.nullptr); + return NSString._(_ret, _lib, retain: true, release: true); } - /// The envelope item header. - SentryEnvelopeItemHeader? get header { - final _ret = _lib._objc_msgSend_1044(_id, _lib._sel_header1); - return _ret.address == 0 - ? null - : SentryEnvelopeItemHeader._(_ret, _lib, retain: true, release: true); + static NSXMLNode predefinedNamespaceForPrefix_( + SentryCocoa _lib, NSString? name) { + final _ret = _lib._objc_msgSend_1032(_lib._class_NSXMLDTDNode1, + _lib._sel_predefinedNamespaceForPrefix_1, name?._id ?? ffi.nullptr); + return NSXMLNode._(_ret, _lib, retain: true, release: true); } - /// The envelope payload. - NSData? get data { - final _ret = _lib._objc_msgSend_39(_id, _lib._sel_data1); - return _ret.address == 0 - ? null - : NSData._(_ret, _lib, retain: true, release: true); + static NSXMLDTDNode new1(SentryCocoa _lib) { + final _ret = + _lib._objc_msgSend_2(_lib._class_NSXMLDTDNode1, _lib._sel_new1); + return NSXMLDTDNode._(_ret, _lib, retain: false, release: true); } - static SentryEnvelopeItem allocWithZone_( + static NSXMLDTDNode allocWithZone_( SentryCocoa _lib, ffi.Pointer<_NSZone> zone) { final _ret = _lib._objc_msgSend_3( - _lib._class_SentryEnvelopeItem1, _lib._sel_allocWithZone_1, zone); - return SentryEnvelopeItem._(_ret, _lib, retain: false, release: true); + _lib._class_NSXMLDTDNode1, _lib._sel_allocWithZone_1, zone); + return NSXMLDTDNode._(_ret, _lib, retain: false, release: true); } - static SentryEnvelopeItem alloc(SentryCocoa _lib) { + static NSXMLDTDNode alloc(SentryCocoa _lib) { final _ret = - _lib._objc_msgSend_2(_lib._class_SentryEnvelopeItem1, _lib._sel_alloc1); - return SentryEnvelopeItem._(_ret, _lib, retain: false, release: true); + _lib._objc_msgSend_2(_lib._class_NSXMLDTDNode1, _lib._sel_alloc1); + return NSXMLDTDNode._(_ret, _lib, retain: false, release: true); } static void cancelPreviousPerformRequestsWithTarget_selector_object_( @@ -71277,7 +70586,7 @@ class SentryEnvelopeItem extends NSObject { ffi.Pointer aSelector, NSObject anArgument) { _lib._objc_msgSend_14( - _lib._class_SentryEnvelopeItem1, + _lib._class_NSXMLDTDNode1, _lib._sel_cancelPreviousPerformRequestsWithTarget_selector_object_1, aTarget._id, aSelector, @@ -71286,24 +70595,24 @@ class SentryEnvelopeItem extends NSObject { static void cancelPreviousPerformRequestsWithTarget_( SentryCocoa _lib, NSObject aTarget) { - _lib._objc_msgSend_15(_lib._class_SentryEnvelopeItem1, + _lib._objc_msgSend_15(_lib._class_NSXMLDTDNode1, _lib._sel_cancelPreviousPerformRequestsWithTarget_1, aTarget._id); } static bool getAccessInstanceVariablesDirectly(SentryCocoa _lib) { - return _lib._objc_msgSend_12(_lib._class_SentryEnvelopeItem1, - _lib._sel_accessInstanceVariablesDirectly1); + return _lib._objc_msgSend_12( + _lib._class_NSXMLDTDNode1, _lib._sel_accessInstanceVariablesDirectly1); } static bool useStoredAccessor(SentryCocoa _lib) { return _lib._objc_msgSend_12( - _lib._class_SentryEnvelopeItem1, _lib._sel_useStoredAccessor1); + _lib._class_NSXMLDTDNode1, _lib._sel_useStoredAccessor1); } static NSSet keyPathsForValuesAffectingValueForKey_( SentryCocoa _lib, NSString? key) { final _ret = _lib._objc_msgSend_58( - _lib._class_SentryEnvelopeItem1, + _lib._class_NSXMLDTDNode1, _lib._sel_keyPathsForValuesAffectingValueForKey_1, key?._id ?? ffi.nullptr); return NSSet._(_ret, _lib, retain: true, release: true); @@ -71312,7 +70621,7 @@ class SentryEnvelopeItem extends NSObject { static bool automaticallyNotifiesObserversForKey_( SentryCocoa _lib, NSString? key) { return _lib._objc_msgSend_59( - _lib._class_SentryEnvelopeItem1, + _lib._class_NSXMLDTDNode1, _lib._sel_automaticallyNotifiesObserversForKey_1, key?._id ?? ffi.nullptr); } @@ -71320,287 +70629,284 @@ class SentryEnvelopeItem extends NSObject { static void setKeys_triggerChangeNotificationsForDependentKey_( SentryCocoa _lib, NSArray? keys, NSString? dependentKey) { _lib._objc_msgSend_82( - _lib._class_SentryEnvelopeItem1, + _lib._class_NSXMLDTDNode1, _lib._sel_setKeys_triggerChangeNotificationsForDependentKey_1, keys?._id ?? ffi.nullptr, dependentKey?._id ?? ffi.nullptr); } static NSArray classFallbacksForKeyedArchiver(SentryCocoa _lib) { - final _ret = _lib._objc_msgSend_79(_lib._class_SentryEnvelopeItem1, - _lib._sel_classFallbacksForKeyedArchiver1); + final _ret = _lib._objc_msgSend_79( + _lib._class_NSXMLDTDNode1, _lib._sel_classFallbacksForKeyedArchiver1); return NSArray._(_ret, _lib, retain: true, release: true); } static NSObject classForKeyedUnarchiver(SentryCocoa _lib) { final _ret = _lib._objc_msgSend_2( - _lib._class_SentryEnvelopeItem1, _lib._sel_classForKeyedUnarchiver1); + _lib._class_NSXMLDTDNode1, _lib._sel_classForKeyedUnarchiver1); return NSObject._(_ret, _lib, retain: true, release: true); } } -class SentryEvent extends _ObjCWrapper { - SentryEvent._(ffi.Pointer id, SentryCocoa lib, - {bool retain = false, bool release = false}) - : super._(id, lib, retain: retain, release: release); - - /// Returns a [SentryEvent] that points to the same underlying object as [other]. - static SentryEvent castFrom(T other) { - return SentryEvent._(other._id, other._lib, retain: true, release: true); - } - - /// Returns a [SentryEvent] that wraps the given raw object pointer. - static SentryEvent castFromPointer( - SentryCocoa lib, ffi.Pointer other, - {bool retain = false, bool release = false}) { - return SentryEvent._(other, lib, retain: retain, release: release); - } - - /// Returns whether [obj] is an instance of [SentryEvent]. - static bool isInstance(_ObjCWrapper obj) { - return obj._lib._objc_msgSend_0( - obj._id, obj._lib._sel_isKindOfClass_1, obj._lib._class_SentryEvent1); - } +abstract class NSXMLDTDNodeKind { + static const int NSXMLEntityGeneralKind = 1; + static const int NSXMLEntityParsedKind = 2; + static const int NSXMLEntityUnparsedKind = 3; + static const int NSXMLEntityParameterKind = 4; + static const int NSXMLEntityPredefined = 5; + static const int NSXMLAttributeCDATAKind = 6; + static const int NSXMLAttributeIDKind = 7; + static const int NSXMLAttributeIDRefKind = 8; + static const int NSXMLAttributeIDRefsKind = 9; + static const int NSXMLAttributeEntityKind = 10; + static const int NSXMLAttributeEntitiesKind = 11; + static const int NSXMLAttributeNMTokenKind = 12; + static const int NSXMLAttributeNMTokensKind = 13; + static const int NSXMLAttributeEnumerationKind = 14; + static const int NSXMLAttributeNotationKind = 15; + static const int NSXMLElementDeclarationUndefinedKind = 16; + static const int NSXMLElementDeclarationEmptyKind = 17; + static const int NSXMLElementDeclarationAnyKind = 18; + static const int NSXMLElementDeclarationMixedKind = 19; + static const int NSXMLElementDeclarationElementKind = 20; } -class SentrySession extends _ObjCWrapper { - SentrySession._(ffi.Pointer id, SentryCocoa lib, +/// @warning This class is reserved for hybrid SDKs. Methods may be changed, renamed or removed +/// without notice. If you want to use one of these methods here please open up an issue and let us +/// know. +/// @note The name of this class is supposed to be a bit weird and ugly. The name starts with private +/// on purpose so users don't see it in code completion when typing Sentry. We also add only at the +/// end to make it more obvious you shouldn't use it. +class PrivateSentrySDKOnly extends NSObject { + PrivateSentrySDKOnly._(ffi.Pointer id, SentryCocoa lib, {bool retain = false, bool release = false}) : super._(id, lib, retain: retain, release: release); - /// Returns a [SentrySession] that points to the same underlying object as [other]. - static SentrySession castFrom(T other) { - return SentrySession._(other._id, other._lib, retain: true, release: true); + /// Returns a [PrivateSentrySDKOnly] that points to the same underlying object as [other]. + static PrivateSentrySDKOnly castFrom(T other) { + return PrivateSentrySDKOnly._(other._id, other._lib, + retain: true, release: true); } - /// Returns a [SentrySession] that wraps the given raw object pointer. - static SentrySession castFromPointer( + /// Returns a [PrivateSentrySDKOnly] that wraps the given raw object pointer. + static PrivateSentrySDKOnly castFromPointer( SentryCocoa lib, ffi.Pointer other, {bool retain = false, bool release = false}) { - return SentrySession._(other, lib, retain: retain, release: release); + return PrivateSentrySDKOnly._(other, lib, retain: retain, release: release); } - /// Returns whether [obj] is an instance of [SentrySession]. + /// Returns whether [obj] is an instance of [PrivateSentrySDKOnly]. static bool isInstance(_ObjCWrapper obj) { - return obj._lib._objc_msgSend_0( - obj._id, obj._lib._sel_isKindOfClass_1, obj._lib._class_SentrySession1); + return obj._lib._objc_msgSend_0(obj._id, obj._lib._sel_isKindOfClass_1, + obj._lib._class_PrivateSentrySDKOnly1); } -} - -class SentryUserFeedback extends _ObjCWrapper { - SentryUserFeedback._(ffi.Pointer id, SentryCocoa lib, - {bool retain = false, bool release = false}) - : super._(id, lib, retain: retain, release: release); - /// Returns a [SentryUserFeedback] that points to the same underlying object as [other]. - static SentryUserFeedback castFrom(T other) { - return SentryUserFeedback._(other._id, other._lib, - retain: true, release: true); + /// For storing an envelope synchronously to disk. + static void storeEnvelope_(SentryCocoa _lib, SentryEnvelope? envelope) { + _lib._objc_msgSend_1050(_lib._class_PrivateSentrySDKOnly1, + _lib._sel_storeEnvelope_1, envelope?._id ?? ffi.nullptr); } - /// Returns a [SentryUserFeedback] that wraps the given raw object pointer. - static SentryUserFeedback castFromPointer( - SentryCocoa lib, ffi.Pointer other, - {bool retain = false, bool release = false}) { - return SentryUserFeedback._(other, lib, retain: retain, release: release); + static void captureEnvelope_(SentryCocoa _lib, SentryEnvelope? envelope) { + _lib._objc_msgSend_1050(_lib._class_PrivateSentrySDKOnly1, + _lib._sel_captureEnvelope_1, envelope?._id ?? ffi.nullptr); } - /// Returns whether [obj] is an instance of [SentryUserFeedback]. - static bool isInstance(_ObjCWrapper obj) { - return obj._lib._objc_msgSend_0(obj._id, obj._lib._sel_isKindOfClass_1, - obj._lib._class_SentryUserFeedback1); + /// Create an envelope from @c NSData. Needed for example by Flutter. + static SentryEnvelope envelopeWithData_(SentryCocoa _lib, NSData? data) { + final _ret = _lib._objc_msgSend_1051(_lib._class_PrivateSentrySDKOnly1, + _lib._sel_envelopeWithData_1, data?._id ?? ffi.nullptr); + return SentryEnvelope._(_ret, _lib, retain: true, release: true); } -} - -class SentryAttachment extends _ObjCWrapper { - SentryAttachment._(ffi.Pointer id, SentryCocoa lib, - {bool retain = false, bool release = false}) - : super._(id, lib, retain: retain, release: release); - /// Returns a [SentryAttachment] that points to the same underlying object as [other]. - static SentryAttachment castFrom(T other) { - return SentryAttachment._(other._id, other._lib, - retain: true, release: true); + /// Returns the current list of debug images. Be aware that the @c SentryDebugMeta is actually + /// describing a debug image. + /// @warning This assumes a crash has occurred and attempts to read the crash information from each + /// image's data segment, which may not be present or be invalid if a crash has not actually + /// occurred. To avoid this, use the new @c +[getDebugImagesCrashed:] instead. + static NSArray getDebugImages(SentryCocoa _lib) { + final _ret = _lib._objc_msgSend_79( + _lib._class_PrivateSentrySDKOnly1, _lib._sel_getDebugImages1); + return NSArray._(_ret, _lib, retain: true, release: true); } - /// Returns a [SentryAttachment] that wraps the given raw object pointer. - static SentryAttachment castFromPointer( - SentryCocoa lib, ffi.Pointer other, - {bool retain = false, bool release = false}) { - return SentryAttachment._(other, lib, retain: retain, release: release); + /// Returns the current list of debug images. Be aware that the @c SentryDebugMeta is actually + /// describing a debug image. + /// @param isCrash @c YES if we're collecting binary images for a crash report, @c NO if we're + /// gathering them for other backtrace information, like a performance transaction. If this is for a + /// crash, each image's data section crash info is also included. + static NSArray getDebugImagesCrashed_(SentryCocoa _lib, bool isCrash) { + final _ret = _lib._objc_msgSend_1052(_lib._class_PrivateSentrySDKOnly1, + _lib._sel_getDebugImagesCrashed_1, isCrash); + return NSArray._(_ret, _lib, retain: true, release: true); } - /// Returns whether [obj] is an instance of [SentryAttachment]. - static bool isInstance(_ObjCWrapper obj) { - return obj._lib._objc_msgSend_0(obj._id, obj._lib._sel_isKindOfClass_1, - obj._lib._class_SentryAttachment1); + /// Override SDK information. + static void setSdkName_andVersionString_( + SentryCocoa _lib, NSString? sdkName, NSString? versionString) { + _lib._objc_msgSend_515( + _lib._class_PrivateSentrySDKOnly1, + _lib._sel_setSdkName_andVersionString_1, + sdkName?._id ?? ffi.nullptr, + versionString?._id ?? ffi.nullptr); } -} -class SentryEnvelopeItemHeader extends _ObjCWrapper { - SentryEnvelopeItemHeader._(ffi.Pointer id, SentryCocoa lib, - {bool retain = false, bool release = false}) - : super._(id, lib, retain: retain, release: release); + /// Override SDK information. + static void setSdkName_(SentryCocoa _lib, NSString? sdkName) { + _lib._objc_msgSend_192(_lib._class_PrivateSentrySDKOnly1, + _lib._sel_setSdkName_1, sdkName?._id ?? ffi.nullptr); + } - /// Returns a [SentryEnvelopeItemHeader] that points to the same underlying object as [other]. - static SentryEnvelopeItemHeader castFrom(T other) { - return SentryEnvelopeItemHeader._(other._id, other._lib, - retain: true, release: true); + /// Retrieves the SDK name + static NSString getSdkName(SentryCocoa _lib) { + final _ret = _lib._objc_msgSend_20( + _lib._class_PrivateSentrySDKOnly1, _lib._sel_getSdkName1); + return NSString._(_ret, _lib, retain: true, release: true); } - /// Returns a [SentryEnvelopeItemHeader] that wraps the given raw object pointer. - static SentryEnvelopeItemHeader castFromPointer( - SentryCocoa lib, ffi.Pointer other, - {bool retain = false, bool release = false}) { - return SentryEnvelopeItemHeader._(other, lib, - retain: retain, release: release); + /// Retrieves the SDK version string + static NSString getSdkVersionString(SentryCocoa _lib) { + final _ret = _lib._objc_msgSend_20( + _lib._class_PrivateSentrySDKOnly1, _lib._sel_getSdkVersionString1); + return NSString._(_ret, _lib, retain: true, release: true); } - /// Returns whether [obj] is an instance of [SentryEnvelopeItemHeader]. - static bool isInstance(_ObjCWrapper obj) { - return obj._lib._objc_msgSend_0(obj._id, obj._lib._sel_isKindOfClass_1, - obj._lib._class_SentryEnvelopeItemHeader1); + /// Retrieves extra context + static NSDictionary getExtraContext(SentryCocoa _lib) { + final _ret = _lib._objc_msgSend_170( + _lib._class_PrivateSentrySDKOnly1, _lib._sel_getExtraContext1); + return NSDictionary._(_ret, _lib, retain: true, release: true); } -} - -class SentryEnvelopeHeader extends NSObject { - SentryEnvelopeHeader._(ffi.Pointer id, SentryCocoa lib, - {bool retain = false, bool release = false}) - : super._(id, lib, retain: retain, release: release); - /// Returns a [SentryEnvelopeHeader] that points to the same underlying object as [other]. - static SentryEnvelopeHeader castFrom(T other) { - return SentryEnvelopeHeader._(other._id, other._lib, - retain: true, release: true); + /// Start a profiler session associated with the given @c SentryId. + /// @return The system time when the profiler session started. + static int startProfilerForTrace_(SentryCocoa _lib, SentryId1? traceId) { + return _lib._objc_msgSend_1053(_lib._class_PrivateSentrySDKOnly1, + _lib._sel_startProfilerForTrace_1, traceId?._id ?? ffi.nullptr); } - /// Returns a [SentryEnvelopeHeader] that wraps the given raw object pointer. - static SentryEnvelopeHeader castFromPointer( - SentryCocoa lib, ffi.Pointer other, - {bool retain = false, bool release = false}) { - return SentryEnvelopeHeader._(other, lib, retain: retain, release: release); + /// Collect a profiler session data associated with the given @c SentryId. + /// This also discards the profiler. + static NSMutableDictionary collectProfileBetween_and_forTrace_( + SentryCocoa _lib, + int startSystemTime, + int endSystemTime, + SentryId? traceId) { + final _ret = _lib._objc_msgSend_1054( + _lib._class_PrivateSentrySDKOnly1, + _lib._sel_collectProfileBetween_and_forTrace_1, + startSystemTime, + endSystemTime, + traceId?._id ?? ffi.nullptr); + return NSMutableDictionary._(_ret, _lib, retain: true, release: true); } - /// Returns whether [obj] is an instance of [SentryEnvelopeHeader]. - static bool isInstance(_ObjCWrapper obj) { - return obj._lib._objc_msgSend_0(obj._id, obj._lib._sel_isKindOfClass_1, - obj._lib._class_SentryEnvelopeHeader1); + /// Discard profiler session data associated with the given @c SentryId. + /// This only needs to be called in case you haven't collected the profile (and don't intend to). + static void discardProfilerForTrace_(SentryCocoa _lib, SentryId? traceId) { + _lib._objc_msgSend_1055(_lib._class_PrivateSentrySDKOnly1, + _lib._sel_discardProfilerForTrace_1, traceId?._id ?? ffi.nullptr); } - @override - SentryEnvelopeHeader init() { - final _ret = _lib._objc_msgSend_2(_id, _lib._sel_init1); - return SentryEnvelopeHeader._(_ret, _lib, retain: true, release: true); + static ObjCBlock_ffiVoid_SentryAppStartMeasurement + getOnAppStartMeasurementAvailable(SentryCocoa _lib) { + final _ret = _lib._objc_msgSend_1056(_lib._class_PrivateSentrySDKOnly1, + _lib._sel_onAppStartMeasurementAvailable1); + return ObjCBlock_ffiVoid_SentryAppStartMeasurement._(_ret, _lib); } - static SentryEnvelopeHeader new1(SentryCocoa _lib) { - final _ret = - _lib._objc_msgSend_2(_lib._class_SentryEnvelopeHeader1, _lib._sel_new1); - return SentryEnvelopeHeader._(_ret, _lib, retain: false, release: true); - } - - /// Initializes an @c SentryEnvelopeHeader object with the specified eventId. - /// @note Sets the @c sdkInfo from @c SentryMeta. - /// @param eventId The identifier of the event. Can be nil if no event in the envelope or attachment - /// related to event. - SentryEnvelopeHeader initWithId_(SentryId? eventId) { - final _ret = _lib._objc_msgSend_1046( - _id, _lib._sel_initWithId_1, eventId?._id ?? ffi.nullptr); - return SentryEnvelopeHeader._(_ret, _lib, retain: true, release: true); - } - - /// Initializes a @c SentryEnvelopeHeader object with the specified @c eventId and @c traceContext. - /// @param eventId The identifier of the event. Can be @c nil if no event in the envelope or - /// attachment related to event. - /// @param traceContext Current trace state. - SentryEnvelopeHeader initWithId_traceContext_( - SentryId? eventId, SentryTraceContext? traceContext) { - final _ret = _lib._objc_msgSend_1047( - _id, - _lib._sel_initWithId_traceContext_1, - eventId?._id ?? ffi.nullptr, - traceContext?._id ?? ffi.nullptr); - return SentryEnvelopeHeader._(_ret, _lib, retain: true, release: true); - } - - /// Initializes a @c SentryEnvelopeHeader object with the specified @c eventId, @c skdInfo and - /// @c traceContext. It is recommended to use @c initWithId:traceContext: because it sets the - /// @c sdkInfo for you. - /// @param eventId The identifier of the event. Can be @c nil if no event in the envelope or - /// attachment related to event. - /// @param sdkInfo Describes the Sentry SDK. Can be @c nil for backwards compatibility. New - /// instances should always provide a version. - /// @param traceContext Current trace state. - SentryEnvelopeHeader initWithId_sdkInfo_traceContext_(SentryId? eventId, - SentrySdkInfo? sdkInfo, SentryTraceContext? traceContext) { - final _ret = _lib._objc_msgSend_1048( - _id, - _lib._sel_initWithId_sdkInfo_traceContext_1, - eventId?._id ?? ffi.nullptr, - sdkInfo?._id ?? ffi.nullptr, - traceContext?._id ?? ffi.nullptr); - return SentryEnvelopeHeader._(_ret, _lib, retain: true, release: true); + static void setOnAppStartMeasurementAvailable( + SentryCocoa _lib, ObjCBlock_ffiVoid_SentryAppStartMeasurement value) { + return _lib._objc_msgSend_1057(_lib._class_PrivateSentrySDKOnly1, + _lib._sel_setOnAppStartMeasurementAvailable_1, value._id); } - /// The event identifier, if available. - /// An event id exist if the envelope contains an event of items within it are related. i.e - /// Attachments - SentryId? get eventId { - final _ret = _lib._objc_msgSend_1038(_id, _lib._sel_eventId1); + static SentryAppStartMeasurement? getAppStartMeasurement(SentryCocoa _lib) { + final _ret = _lib._objc_msgSend_1058( + _lib._class_PrivateSentrySDKOnly1, _lib._sel_appStartMeasurement1); return _ret.address == 0 ? null - : SentryId._(_ret, _lib, retain: true, release: true); + : SentryAppStartMeasurement._(_ret, _lib, retain: true, release: true); } - SentrySdkInfo? get sdkInfo { - final _ret = _lib._objc_msgSend_1049(_id, _lib._sel_sdkInfo1); + static NSString? getInstallationID(SentryCocoa _lib) { + final _ret = _lib._objc_msgSend_20( + _lib._class_PrivateSentrySDKOnly1, _lib._sel_installationID1); return _ret.address == 0 ? null - : SentrySdkInfo._(_ret, _lib, retain: true, release: true); + : NSString._(_ret, _lib, retain: true, release: true); } - SentryTraceContext? get traceContext { - final _ret = _lib._objc_msgSend_1050(_id, _lib._sel_traceContext1); + static SentryOptions? getOptions(SentryCocoa _lib) { + final _ret = _lib._objc_msgSend_1059( + _lib._class_PrivateSentrySDKOnly1, _lib._sel_options1); return _ret.address == 0 ? null - : SentryTraceContext._(_ret, _lib, retain: true, release: true); + : SentryOptions._(_ret, _lib, retain: true, release: true); } - /// The timestamp when the event was sent from the SDK as string in RFC 3339 format. Used - /// for clock drift correction of the event timestamp. The time zone must be UTC. - /// - /// The timestamp should be generated as close as possible to the transmision of the event, - /// so that the delay between sending the envelope and receiving it on the server-side is - /// minimized. - NSDate? get sentAt { - final _ret = _lib._objc_msgSend_162(_id, _lib._sel_sentAt1); - return _ret.address == 0 - ? null - : NSDate._(_ret, _lib, retain: true, release: true); + /// If enabled, the SDK won't send the app start measurement with the first transaction. Instead, if + /// @c enableAutoPerformanceTracing is enabled, the SDK measures the app start and then calls + /// @c onAppStartMeasurementAvailable. Furthermore, the SDK doesn't set all values for the app start + /// measurement because the HybridSDKs initialize the Cocoa SDK too late to receive all + /// notifications. Instead, the SDK sets the @c appStartDuration to @c 0 and the + /// @c didFinishLaunchingTimestamp to @c timeIntervalSinceReferenceDate. + /// @note Default is @c NO. + static bool getAppStartMeasurementHybridSDKMode(SentryCocoa _lib) { + return _lib._objc_msgSend_12(_lib._class_PrivateSentrySDKOnly1, + _lib._sel_appStartMeasurementHybridSDKMode1); } - /// The timestamp when the event was sent from the SDK as string in RFC 3339 format. Used - /// for clock drift correction of the event timestamp. The time zone must be UTC. - /// - /// The timestamp should be generated as close as possible to the transmision of the event, - /// so that the delay between sending the envelope and receiving it on the server-side is - /// minimized. - set sentAt(NSDate? value) { - return _lib._objc_msgSend_525( - _id, _lib._sel_setSentAt_1, value?._id ?? ffi.nullptr); + /// If enabled, the SDK won't send the app start measurement with the first transaction. Instead, if + /// @c enableAutoPerformanceTracing is enabled, the SDK measures the app start and then calls + /// @c onAppStartMeasurementAvailable. Furthermore, the SDK doesn't set all values for the app start + /// measurement because the HybridSDKs initialize the Cocoa SDK too late to receive all + /// notifications. Instead, the SDK sets the @c appStartDuration to @c 0 and the + /// @c didFinishLaunchingTimestamp to @c timeIntervalSinceReferenceDate. + /// @note Default is @c NO. + static void setAppStartMeasurementHybridSDKMode( + SentryCocoa _lib, bool value) { + return _lib._objc_msgSend_492(_lib._class_PrivateSentrySDKOnly1, + _lib._sel_setAppStartMeasurementHybridSDKMode_1, value); + } + + static SentryUser userWithDictionary_( + SentryCocoa _lib, NSDictionary? dictionary) { + final _ret = _lib._objc_msgSend_1060(_lib._class_PrivateSentrySDKOnly1, + _lib._sel_userWithDictionary_1, dictionary?._id ?? ffi.nullptr); + return SentryUser._(_ret, _lib, retain: true, release: true); } - static SentryEnvelopeHeader allocWithZone_( + static SentryBreadcrumb breadcrumbWithDictionary_( + SentryCocoa _lib, NSDictionary? dictionary) { + final _ret = _lib._objc_msgSend_1061(_lib._class_PrivateSentrySDKOnly1, + _lib._sel_breadcrumbWithDictionary_1, dictionary?._id ?? ffi.nullptr); + return SentryBreadcrumb._(_ret, _lib, retain: true, release: true); + } + + @override + PrivateSentrySDKOnly init() { + final _ret = _lib._objc_msgSend_2(_id, _lib._sel_init1); + return PrivateSentrySDKOnly._(_ret, _lib, retain: true, release: true); + } + + static PrivateSentrySDKOnly new1(SentryCocoa _lib) { + final _ret = + _lib._objc_msgSend_2(_lib._class_PrivateSentrySDKOnly1, _lib._sel_new1); + return PrivateSentrySDKOnly._(_ret, _lib, retain: false, release: true); + } + + static PrivateSentrySDKOnly allocWithZone_( SentryCocoa _lib, ffi.Pointer<_NSZone> zone) { final _ret = _lib._objc_msgSend_3( - _lib._class_SentryEnvelopeHeader1, _lib._sel_allocWithZone_1, zone); - return SentryEnvelopeHeader._(_ret, _lib, retain: false, release: true); + _lib._class_PrivateSentrySDKOnly1, _lib._sel_allocWithZone_1, zone); + return PrivateSentrySDKOnly._(_ret, _lib, retain: false, release: true); } - static SentryEnvelopeHeader alloc(SentryCocoa _lib) { + static PrivateSentrySDKOnly alloc(SentryCocoa _lib) { final _ret = _lib._objc_msgSend_2( - _lib._class_SentryEnvelopeHeader1, _lib._sel_alloc1); - return SentryEnvelopeHeader._(_ret, _lib, retain: false, release: true); + _lib._class_PrivateSentrySDKOnly1, _lib._sel_alloc1); + return PrivateSentrySDKOnly._(_ret, _lib, retain: false, release: true); } static void cancelPreviousPerformRequestsWithTarget_selector_object_( @@ -71609,7 +70915,7 @@ class SentryEnvelopeHeader extends NSObject { ffi.Pointer aSelector, NSObject anArgument) { _lib._objc_msgSend_14( - _lib._class_SentryEnvelopeHeader1, + _lib._class_PrivateSentrySDKOnly1, _lib._sel_cancelPreviousPerformRequestsWithTarget_selector_object_1, aTarget._id, aSelector, @@ -71618,24 +70924,24 @@ class SentryEnvelopeHeader extends NSObject { static void cancelPreviousPerformRequestsWithTarget_( SentryCocoa _lib, NSObject aTarget) { - _lib._objc_msgSend_15(_lib._class_SentryEnvelopeHeader1, + _lib._objc_msgSend_15(_lib._class_PrivateSentrySDKOnly1, _lib._sel_cancelPreviousPerformRequestsWithTarget_1, aTarget._id); } static bool getAccessInstanceVariablesDirectly(SentryCocoa _lib) { - return _lib._objc_msgSend_12(_lib._class_SentryEnvelopeHeader1, + return _lib._objc_msgSend_12(_lib._class_PrivateSentrySDKOnly1, _lib._sel_accessInstanceVariablesDirectly1); } static bool useStoredAccessor(SentryCocoa _lib) { return _lib._objc_msgSend_12( - _lib._class_SentryEnvelopeHeader1, _lib._sel_useStoredAccessor1); + _lib._class_PrivateSentrySDKOnly1, _lib._sel_useStoredAccessor1); } static NSSet keyPathsForValuesAffectingValueForKey_( SentryCocoa _lib, NSString? key) { final _ret = _lib._objc_msgSend_58( - _lib._class_SentryEnvelopeHeader1, + _lib._class_PrivateSentrySDKOnly1, _lib._sel_keyPathsForValuesAffectingValueForKey_1, key?._id ?? ffi.nullptr); return NSSet._(_ret, _lib, retain: true, release: true); @@ -71644,7 +70950,7 @@ class SentryEnvelopeHeader extends NSObject { static bool automaticallyNotifiesObserversForKey_( SentryCocoa _lib, NSString? key) { return _lib._objc_msgSend_59( - _lib._class_SentryEnvelopeHeader1, + _lib._class_PrivateSentrySDKOnly1, _lib._sel_automaticallyNotifiesObserversForKey_1, key?._id ?? ffi.nullptr); } @@ -71652,71 +70958,70 @@ class SentryEnvelopeHeader extends NSObject { static void setKeys_triggerChangeNotificationsForDependentKey_( SentryCocoa _lib, NSArray? keys, NSString? dependentKey) { _lib._objc_msgSend_82( - _lib._class_SentryEnvelopeHeader1, + _lib._class_PrivateSentrySDKOnly1, _lib._sel_setKeys_triggerChangeNotificationsForDependentKey_1, keys?._id ?? ffi.nullptr, dependentKey?._id ?? ffi.nullptr); } static NSArray classFallbacksForKeyedArchiver(SentryCocoa _lib) { - final _ret = _lib._objc_msgSend_79(_lib._class_SentryEnvelopeHeader1, + final _ret = _lib._objc_msgSend_79(_lib._class_PrivateSentrySDKOnly1, _lib._sel_classFallbacksForKeyedArchiver1); return NSArray._(_ret, _lib, retain: true, release: true); } static NSObject classForKeyedUnarchiver(SentryCocoa _lib) { final _ret = _lib._objc_msgSend_2( - _lib._class_SentryEnvelopeHeader1, _lib._sel_classForKeyedUnarchiver1); + _lib._class_PrivateSentrySDKOnly1, _lib._sel_classForKeyedUnarchiver1); return NSObject._(_ret, _lib, retain: true, release: true); } } -class SentryTraceContext extends _ObjCWrapper { - SentryTraceContext._(ffi.Pointer id, SentryCocoa lib, +class SentryEnvelope extends _ObjCWrapper { + SentryEnvelope._(ffi.Pointer id, SentryCocoa lib, {bool retain = false, bool release = false}) : super._(id, lib, retain: retain, release: release); - /// Returns a [SentryTraceContext] that points to the same underlying object as [other]. - static SentryTraceContext castFrom(T other) { - return SentryTraceContext._(other._id, other._lib, - retain: true, release: true); + /// Returns a [SentryEnvelope] that points to the same underlying object as [other]. + static SentryEnvelope castFrom(T other) { + return SentryEnvelope._(other._id, other._lib, retain: true, release: true); } - /// Returns a [SentryTraceContext] that wraps the given raw object pointer. - static SentryTraceContext castFromPointer( + /// Returns a [SentryEnvelope] that wraps the given raw object pointer. + static SentryEnvelope castFromPointer( SentryCocoa lib, ffi.Pointer other, {bool retain = false, bool release = false}) { - return SentryTraceContext._(other, lib, retain: retain, release: release); + return SentryEnvelope._(other, lib, retain: retain, release: release); } - /// Returns whether [obj] is an instance of [SentryTraceContext]. + /// Returns whether [obj] is an instance of [SentryEnvelope]. static bool isInstance(_ObjCWrapper obj) { return obj._lib._objc_msgSend_0(obj._id, obj._lib._sel_isKindOfClass_1, - obj._lib._class_SentryTraceContext1); + obj._lib._class_SentryEnvelope1); } } -class SentrySdkInfo extends _ObjCWrapper { - SentrySdkInfo._(ffi.Pointer id, SentryCocoa lib, +class SentryId extends _ObjCWrapper { + SentryId._(ffi.Pointer id, SentryCocoa lib, {bool retain = false, bool release = false}) : super._(id, lib, retain: retain, release: release); - /// Returns a [SentrySdkInfo] that points to the same underlying object as [other]. - static SentrySdkInfo castFrom(T other) { - return SentrySdkInfo._(other._id, other._lib, retain: true, release: true); + /// Returns a [SentryId] that points to the same underlying object as [other]. + static SentryId castFrom(T other) { + return SentryId._(other._id, other._lib, retain: true, release: true); } - /// Returns a [SentrySdkInfo] that wraps the given raw object pointer. - static SentrySdkInfo castFromPointer( + /// Returns a [SentryId] that wraps the given raw object pointer. + static SentryId castFromPointer( SentryCocoa lib, ffi.Pointer other, {bool retain = false, bool release = false}) { - return SentrySdkInfo._(other, lib, retain: retain, release: release); + return SentryId._(other, lib, retain: retain, release: release); } - /// Returns whether [obj] is an instance of [SentrySdkInfo]. + /// Returns whether [obj] is an instance of [SentryId]. static bool isInstance(_ObjCWrapper obj) { return obj._lib._objc_msgSend_0( - obj._id, obj._lib._sel_isKindOfClass_1, obj._lib._class_SentrySdkInfo1); + obj._id, obj._lib._sel_isKindOfClass_1, obj._lib._class_SentryId2); } } @@ -71892,3 +71197,454 @@ class SentryBreadcrumb extends _ObjCWrapper { obj._lib._class_SentryBreadcrumb1); } } + +class SentryCurrentDateProvider extends NSObject { + SentryCurrentDateProvider._(ffi.Pointer id, SentryCocoa lib, + {bool retain = false, bool release = false}) + : super._(id, lib, retain: retain, release: release); + + /// Returns a [SentryCurrentDateProvider] that points to the same underlying object as [other]. + static SentryCurrentDateProvider castFrom(T other) { + return SentryCurrentDateProvider._(other._id, other._lib, + retain: true, release: true); + } + + /// Returns a [SentryCurrentDateProvider] that wraps the given raw object pointer. + static SentryCurrentDateProvider castFromPointer( + SentryCocoa lib, ffi.Pointer other, + {bool retain = false, bool release = false}) { + return SentryCurrentDateProvider._(other, lib, + retain: retain, release: release); + } + + /// Returns whether [obj] is an instance of [SentryCurrentDateProvider]. + static bool isInstance(_ObjCWrapper obj) { + return obj._lib._objc_msgSend_0(obj._id, obj._lib._sel_isKindOfClass_1, + obj._lib._class_SentryCurrentDateProvider1); + } + + NSDate date() { + final _ret = _lib._objc_msgSend_162(_id, _lib._sel_date1); + return NSDate._(_ret, _lib, retain: true, release: true); + } + + int timezoneOffset() { + return _lib._objc_msgSend_78(_id, _lib._sel_timezoneOffset1); + } + + int systemTime() { + return _lib._objc_msgSend_1062(_id, _lib._sel_systemTime1); + } + + @override + SentryCurrentDateProvider init() { + final _ret = _lib._objc_msgSend_2(_id, _lib._sel_init1); + return SentryCurrentDateProvider._(_ret, _lib, retain: true, release: true); + } + + int get bucketTimestamp { + return _lib._objc_msgSend_1062(_id, _lib._sel_bucketTimestamp1); + } + + static SentryCurrentDateProvider new1(SentryCocoa _lib) { + final _ret = _lib._objc_msgSend_2( + _lib._class_SentryCurrentDateProvider1, _lib._sel_new1); + return SentryCurrentDateProvider._(_ret, _lib, + retain: false, release: true); + } + + static SentryCurrentDateProvider allocWithZone_( + SentryCocoa _lib, ffi.Pointer<_NSZone> zone) { + final _ret = _lib._objc_msgSend_3(_lib._class_SentryCurrentDateProvider1, + _lib._sel_allocWithZone_1, zone); + return SentryCurrentDateProvider._(_ret, _lib, + retain: false, release: true); + } + + static SentryCurrentDateProvider alloc(SentryCocoa _lib) { + final _ret = _lib._objc_msgSend_2( + _lib._class_SentryCurrentDateProvider1, _lib._sel_alloc1); + return SentryCurrentDateProvider._(_ret, _lib, + retain: false, release: true); + } + + static void cancelPreviousPerformRequestsWithTarget_selector_object_( + SentryCocoa _lib, + NSObject aTarget, + ffi.Pointer aSelector, + NSObject anArgument) { + _lib._objc_msgSend_14( + _lib._class_SentryCurrentDateProvider1, + _lib._sel_cancelPreviousPerformRequestsWithTarget_selector_object_1, + aTarget._id, + aSelector, + anArgument._id); + } + + static void cancelPreviousPerformRequestsWithTarget_( + SentryCocoa _lib, NSObject aTarget) { + _lib._objc_msgSend_15(_lib._class_SentryCurrentDateProvider1, + _lib._sel_cancelPreviousPerformRequestsWithTarget_1, aTarget._id); + } + + static bool getAccessInstanceVariablesDirectly(SentryCocoa _lib) { + return _lib._objc_msgSend_12(_lib._class_SentryCurrentDateProvider1, + _lib._sel_accessInstanceVariablesDirectly1); + } + + static bool useStoredAccessor(SentryCocoa _lib) { + return _lib._objc_msgSend_12( + _lib._class_SentryCurrentDateProvider1, _lib._sel_useStoredAccessor1); + } + + static NSSet keyPathsForValuesAffectingValueForKey_( + SentryCocoa _lib, NSString? key) { + final _ret = _lib._objc_msgSend_58( + _lib._class_SentryCurrentDateProvider1, + _lib._sel_keyPathsForValuesAffectingValueForKey_1, + key?._id ?? ffi.nullptr); + return NSSet._(_ret, _lib, retain: true, release: true); + } + + static bool automaticallyNotifiesObserversForKey_( + SentryCocoa _lib, NSString? key) { + return _lib._objc_msgSend_59( + _lib._class_SentryCurrentDateProvider1, + _lib._sel_automaticallyNotifiesObserversForKey_1, + key?._id ?? ffi.nullptr); + } + + static void setKeys_triggerChangeNotificationsForDependentKey_( + SentryCocoa _lib, NSArray? keys, NSString? dependentKey) { + _lib._objc_msgSend_82( + _lib._class_SentryCurrentDateProvider1, + _lib._sel_setKeys_triggerChangeNotificationsForDependentKey_1, + keys?._id ?? ffi.nullptr, + dependentKey?._id ?? ffi.nullptr); + } + + static NSArray classFallbacksForKeyedArchiver(SentryCocoa _lib) { + final _ret = _lib._objc_msgSend_79(_lib._class_SentryCurrentDateProvider1, + _lib._sel_classFallbacksForKeyedArchiver1); + return NSArray._(_ret, _lib, retain: true, release: true); + } + + static NSObject classForKeyedUnarchiver(SentryCocoa _lib) { + final _ret = _lib._objc_msgSend_2(_lib._class_SentryCurrentDateProvider1, + _lib._sel_classForKeyedUnarchiver1); + return NSObject._(_ret, _lib, retain: true, release: true); + } +} + +class SentryId1 extends NSObject { + SentryId1._(ffi.Pointer id, SentryCocoa lib, + {bool retain = false, bool release = false}) + : super._(id, lib, retain: retain, release: release); + + /// Returns a [SentryId1] that points to the same underlying object as [other]. + static SentryId1 castFrom(T other) { + return SentryId1._(other._id, other._lib, retain: true, release: true); + } + + /// Returns a [SentryId1] that wraps the given raw object pointer. + static SentryId1 castFromPointer( + SentryCocoa lib, ffi.Pointer other, + {bool retain = false, bool release = false}) { + return SentryId1._(other, lib, retain: retain, release: release); + } + + /// Returns whether [obj] is an instance of [SentryId1]. + static bool isInstance(_ObjCWrapper obj) { + return obj._lib._objc_msgSend_0( + obj._id, obj._lib._sel_isKindOfClass_1, obj._lib._class_SentryId11); + } + + static SentryId1? getEmpty(SentryCocoa _lib) { + final _ret = + _lib._objc_msgSend_1063(_lib._class_SentryId11, _lib._sel_empty1); + return _ret.address == 0 + ? null + : SentryId1._(_ret, _lib, retain: true, release: true); + } + + static void setEmpty(SentryCocoa _lib, SentryId1? value) { + return _lib._objc_msgSend_1064(_lib._class_SentryId11, _lib._sel_setEmpty_1, + value?._id ?? ffi.nullptr); + } + + /// Returns a 32 lowercase character hexadecimal string description of the @c SentryId, such as + /// “12c2d058d58442709aa2eca08bf20986”. + NSString? get sentryIdString { + final _ret = _lib._objc_msgSend_20(_id, _lib._sel_sentryIdString1); + return _ret.address == 0 + ? null + : NSString._(_ret, _lib, retain: true, release: true); + } + + /// Creates a @c SentryId with a random UUID. + @override + SentryId1 init() { + final _ret = _lib._objc_msgSend_2(_id, _lib._sel_init1); + return SentryId1._(_ret, _lib, retain: true, release: true); + } + + /// Creates a SentryId with the given UUID. + SentryId1 initWithUuid_(NSUUID? uuid) { + final _ret = _lib._objc_msgSend_1068( + _id, _lib._sel_initWithUuid_1, uuid?._id ?? ffi.nullptr); + return SentryId1._(_ret, _lib, retain: true, release: true); + } + + /// Creates a @c SentryId from a 32 character hexadecimal string without dashes such as + /// “12c2d058d58442709aa2eca08bf20986” or a 36 character hexadecimal string such as such as + /// “12c2d058-d584-4270-9aa2-eca08bf20986”. + /// @return SentryId.empty for invalid strings. + SentryId1 initWithUUIDString_(NSString? uuidString) { + final _ret = _lib._objc_msgSend_30( + _id, _lib._sel_initWithUUIDString_1, uuidString?._id ?? ffi.nullptr); + return SentryId1._(_ret, _lib, retain: true, release: true); + } + + bool isEqual_(NSObject object) { + return _lib._objc_msgSend_0(_id, _lib._sel_isEqual_1, object._id); + } + + NSString? get description { + final _ret = _lib._objc_msgSend_20(_id, _lib._sel_description1); + return _ret.address == 0 + ? null + : NSString._(_ret, _lib, retain: true, release: true); + } + + int get hash { + return _lib._objc_msgSend_10(_id, _lib._sel_hash1); + } + + static SentryId1 new1(SentryCocoa _lib) { + final _ret = _lib._objc_msgSend_2(_lib._class_SentryId11, _lib._sel_new1); + return SentryId1._(_ret, _lib, retain: false, release: true); + } + + static SentryId1 allocWithZone_(SentryCocoa _lib, ffi.Pointer<_NSZone> zone) { + final _ret = _lib._objc_msgSend_3( + _lib._class_SentryId11, _lib._sel_allocWithZone_1, zone); + return SentryId1._(_ret, _lib, retain: false, release: true); + } + + static SentryId1 alloc(SentryCocoa _lib) { + final _ret = _lib._objc_msgSend_2(_lib._class_SentryId11, _lib._sel_alloc1); + return SentryId1._(_ret, _lib, retain: false, release: true); + } + + static void cancelPreviousPerformRequestsWithTarget_selector_object_( + SentryCocoa _lib, + NSObject aTarget, + ffi.Pointer aSelector, + NSObject anArgument) { + _lib._objc_msgSend_14( + _lib._class_SentryId11, + _lib._sel_cancelPreviousPerformRequestsWithTarget_selector_object_1, + aTarget._id, + aSelector, + anArgument._id); + } + + static void cancelPreviousPerformRequestsWithTarget_( + SentryCocoa _lib, NSObject aTarget) { + _lib._objc_msgSend_15(_lib._class_SentryId11, + _lib._sel_cancelPreviousPerformRequestsWithTarget_1, aTarget._id); + } + + static bool getAccessInstanceVariablesDirectly(SentryCocoa _lib) { + return _lib._objc_msgSend_12( + _lib._class_SentryId11, _lib._sel_accessInstanceVariablesDirectly1); + } + + static bool useStoredAccessor(SentryCocoa _lib) { + return _lib._objc_msgSend_12( + _lib._class_SentryId11, _lib._sel_useStoredAccessor1); + } + + static NSSet keyPathsForValuesAffectingValueForKey_( + SentryCocoa _lib, NSString? key) { + final _ret = _lib._objc_msgSend_58( + _lib._class_SentryId11, + _lib._sel_keyPathsForValuesAffectingValueForKey_1, + key?._id ?? ffi.nullptr); + return NSSet._(_ret, _lib, retain: true, release: true); + } + + static bool automaticallyNotifiesObserversForKey_( + SentryCocoa _lib, NSString? key) { + return _lib._objc_msgSend_59( + _lib._class_SentryId11, + _lib._sel_automaticallyNotifiesObserversForKey_1, + key?._id ?? ffi.nullptr); + } + + static void setKeys_triggerChangeNotificationsForDependentKey_( + SentryCocoa _lib, NSArray? keys, NSString? dependentKey) { + _lib._objc_msgSend_82( + _lib._class_SentryId11, + _lib._sel_setKeys_triggerChangeNotificationsForDependentKey_1, + keys?._id ?? ffi.nullptr, + dependentKey?._id ?? ffi.nullptr); + } + + static NSArray classFallbacksForKeyedArchiver(SentryCocoa _lib) { + final _ret = _lib._objc_msgSend_79( + _lib._class_SentryId11, _lib._sel_classFallbacksForKeyedArchiver1); + return NSArray._(_ret, _lib, retain: true, release: true); + } + + static NSObject classForKeyedUnarchiver(SentryCocoa _lib) { + final _ret = _lib._objc_msgSend_2( + _lib._class_SentryId11, _lib._sel_classForKeyedUnarchiver1); + return NSObject._(_ret, _lib, retain: true, release: true); + } +} + +class NSUUID extends NSObject { + NSUUID._(ffi.Pointer id, SentryCocoa lib, + {bool retain = false, bool release = false}) + : super._(id, lib, retain: retain, release: release); + + /// Returns a [NSUUID] that points to the same underlying object as [other]. + static NSUUID castFrom(T other) { + return NSUUID._(other._id, other._lib, retain: true, release: true); + } + + /// Returns a [NSUUID] that wraps the given raw object pointer. + static NSUUID castFromPointer(SentryCocoa lib, ffi.Pointer other, + {bool retain = false, bool release = false}) { + return NSUUID._(other, lib, retain: retain, release: release); + } + + /// Returns whether [obj] is an instance of [NSUUID]. + static bool isInstance(_ObjCWrapper obj) { + return obj._lib._objc_msgSend_0( + obj._id, obj._lib._sel_isKindOfClass_1, obj._lib._class_NSUUID1); + } + + static NSUUID UUID(SentryCocoa _lib) { + final _ret = _lib._objc_msgSend_2(_lib._class_NSUUID1, _lib._sel_UUID1); + return NSUUID._(_ret, _lib, retain: true, release: true); + } + + @override + NSUUID init() { + final _ret = _lib._objc_msgSend_2(_id, _lib._sel_init1); + return NSUUID._(_ret, _lib, retain: true, release: true); + } + + NSUUID initWithUUIDString_(NSString? string) { + final _ret = _lib._objc_msgSend_30( + _id, _lib._sel_initWithUUIDString_1, string?._id ?? ffi.nullptr); + return NSUUID._(_ret, _lib, retain: true, release: true); + } + + NSUUID initWithUUIDBytes_(ffi.Pointer bytes) { + final _ret = + _lib._objc_msgSend_1065(_id, _lib._sel_initWithUUIDBytes_1, bytes); + return NSUUID._(_ret, _lib, retain: true, release: true); + } + + void getUUIDBytes_(ffi.Pointer uuid) { + _lib._objc_msgSend_1066(_id, _lib._sel_getUUIDBytes_1, uuid); + } + + int compare_(NSUUID? otherUUID) { + return _lib._objc_msgSend_1067( + _id, _lib._sel_compare_1, otherUUID?._id ?? ffi.nullptr); + } + + NSString? get UUIDString { + final _ret = _lib._objc_msgSend_20(_id, _lib._sel_UUIDString1); + return _ret.address == 0 + ? null + : NSString._(_ret, _lib, retain: true, release: true); + } + + static NSUUID new1(SentryCocoa _lib) { + final _ret = _lib._objc_msgSend_2(_lib._class_NSUUID1, _lib._sel_new1); + return NSUUID._(_ret, _lib, retain: false, release: true); + } + + static NSUUID allocWithZone_(SentryCocoa _lib, ffi.Pointer<_NSZone> zone) { + final _ret = _lib._objc_msgSend_3( + _lib._class_NSUUID1, _lib._sel_allocWithZone_1, zone); + return NSUUID._(_ret, _lib, retain: false, release: true); + } + + static NSUUID alloc(SentryCocoa _lib) { + final _ret = _lib._objc_msgSend_2(_lib._class_NSUUID1, _lib._sel_alloc1); + return NSUUID._(_ret, _lib, retain: false, release: true); + } + + static void cancelPreviousPerformRequestsWithTarget_selector_object_( + SentryCocoa _lib, + NSObject aTarget, + ffi.Pointer aSelector, + NSObject anArgument) { + _lib._objc_msgSend_14( + _lib._class_NSUUID1, + _lib._sel_cancelPreviousPerformRequestsWithTarget_selector_object_1, + aTarget._id, + aSelector, + anArgument._id); + } + + static void cancelPreviousPerformRequestsWithTarget_( + SentryCocoa _lib, NSObject aTarget) { + _lib._objc_msgSend_15(_lib._class_NSUUID1, + _lib._sel_cancelPreviousPerformRequestsWithTarget_1, aTarget._id); + } + + static bool getAccessInstanceVariablesDirectly(SentryCocoa _lib) { + return _lib._objc_msgSend_12( + _lib._class_NSUUID1, _lib._sel_accessInstanceVariablesDirectly1); + } + + static bool useStoredAccessor(SentryCocoa _lib) { + return _lib._objc_msgSend_12( + _lib._class_NSUUID1, _lib._sel_useStoredAccessor1); + } + + static NSSet keyPathsForValuesAffectingValueForKey_( + SentryCocoa _lib, NSString? key) { + final _ret = _lib._objc_msgSend_58( + _lib._class_NSUUID1, + _lib._sel_keyPathsForValuesAffectingValueForKey_1, + key?._id ?? ffi.nullptr); + return NSSet._(_ret, _lib, retain: true, release: true); + } + + static bool automaticallyNotifiesObserversForKey_( + SentryCocoa _lib, NSString? key) { + return _lib._objc_msgSend_59( + _lib._class_NSUUID1, + _lib._sel_automaticallyNotifiesObserversForKey_1, + key?._id ?? ffi.nullptr); + } + + static void setKeys_triggerChangeNotificationsForDependentKey_( + SentryCocoa _lib, NSArray? keys, NSString? dependentKey) { + _lib._objc_msgSend_82( + _lib._class_NSUUID1, + _lib._sel_setKeys_triggerChangeNotificationsForDependentKey_1, + keys?._id ?? ffi.nullptr, + dependentKey?._id ?? ffi.nullptr); + } + + static NSArray classFallbacksForKeyedArchiver(SentryCocoa _lib) { + final _ret = _lib._objc_msgSend_79( + _lib._class_NSUUID1, _lib._sel_classFallbacksForKeyedArchiver1); + return NSArray._(_ret, _lib, retain: true, release: true); + } + + static NSObject classForKeyedUnarchiver(SentryCocoa _lib) { + final _ret = _lib._objc_msgSend_2( + _lib._class_NSUUID1, _lib._sel_classForKeyedUnarchiver1); + return NSObject._(_ret, _lib, retain: true, release: true); + } +} diff --git a/flutter/lib/src/native/cocoa/sentry_native_cocoa.dart b/flutter/lib/src/native/cocoa/sentry_native_cocoa.dart index 0e6817cb48..d6912c107c 100644 --- a/flutter/lib/src/native/cocoa/sentry_native_cocoa.dart +++ b/flutter/lib/src/native/cocoa/sentry_native_cocoa.dart @@ -14,7 +14,7 @@ class SentryNativeCocoa extends SentryNativeChannel { @override int? startProfiler(SentryId traceId) { - final cSentryId = cocoa.SentryId.alloc(_lib) + final cSentryId = cocoa.SentryId1.alloc(_lib) ..initWithUUIDString_(cocoa.NSString(_lib, traceId.toString())); final startTime = cocoa.PrivateSentrySDKOnly.startProfilerForTrace_(_lib, cSentryId); diff --git a/flutter/scripts/generate-cocoa-bindings.sh b/flutter/scripts/generate-cocoa-bindings.sh index 0b653d0df1..722a52fb32 100755 --- a/flutter/scripts/generate-cocoa-bindings.sh +++ b/flutter/scripts/generate-cocoa-bindings.sh @@ -28,11 +28,12 @@ dart pub add 'dev:ffigen:{"git":{"url":"https://github.com/getsentry/ffigen","re temp="cocoa_bindings_temp" rm -rf $temp mkdir -p $temp -curl -Lv https://github.com/getsentry/sentry-cocoa/releases/download/$cocoa_version/Sentry.xcframework.zip -o $temp/Sentry.xcframework.zip +curl -Lv --fail-with-body https://github.com/getsentry/sentry-cocoa/releases/download/$cocoa_version/Sentry.xcframework.zip -o $temp/Sentry.xcframework.zip subdir="Sentry.xcframework/macos-arm64_x86_64/Sentry.framework" unzip -q $temp/Sentry.xcframework.zip "$subdir/*" -d $temp mv "$temp/$subdir" $temp/Sentry.framework dart run ffigen --config ffi-cocoa.yaml sed -i.bak 's|final class|class|g' lib/src/native/cocoa/binding.dart +sed -i.bak 's|static int startProfilerForTrace_(SentryCocoa _lib, SentryId? traceId)|static int startProfilerForTrace_(SentryCocoa _lib, SentryId1? traceId)|g' lib/src/native/cocoa/binding.dart rm lib/src/native/cocoa/binding.dart.bak From daecac625586322254a10480ca7a3e616d7095cb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 Apr 2024 14:03:48 +0200 Subject: [PATCH 150/237] build(deps): bump styfle/cancel-workflow-action from 0.11.0 to 0.12.1 (#2003) Bumps [styfle/cancel-workflow-action](https://github.com/styfle/cancel-workflow-action) from 0.11.0 to 0.12.1. - [Release notes](https://github.com/styfle/cancel-workflow-action/releases) - [Commits](https://github.com/styfle/cancel-workflow-action/compare/0.11.0...85880fa0301c86cca9da44039ee3bb12d3bedbfa) --- updated-dependencies: - dependency-name: styfle/cancel-workflow-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor --- .github/workflows/flutter_integration_test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/flutter_integration_test.yml b/.github/workflows/flutter_integration_test.yml index 0b12b5ad74..7f23dec0da 100644 --- a/.github/workflows/flutter_integration_test.yml +++ b/.github/workflows/flutter_integration_test.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Cancel Previous Runs - uses: styfle/cancel-workflow-action@b173b6ec0100793626c2d9e6b90435061f4fc3e5 # pin@0.11.0 + uses: styfle/cancel-workflow-action@85880fa0301c86cca9da44039ee3bb12d3bedbfa # pin@0.12.1 with: access_token: ${{ github.token }} From ce108620c2c267d6fa7dfea643b9f60f7ef6a4a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20Andra=C5=A1ec?= Date: Tue, 23 Apr 2024 12:57:59 +0000 Subject: [PATCH 151/237] Apple Privacy Manifest Info (#2002) --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index 6159941c4c..a9d1e1c4a2 100644 --- a/README.md +++ b/README.md @@ -48,3 +48,10 @@ For detailed usage, check out the inner [dart](https://github.com/getsentry/sent * [![Discord Chat](https://img.shields.io/discord/621778831602221064?logo=discord&logoColor=ffffff&color=7389D8)](https://discord.gg/PXa5Apfe7K) * [![Stack Overflow](https://img.shields.io/badge/stack%20overflow-sentry-green.svg)](https://stackoverflow.com/questions/tagged/sentry) * [![Twitter Follow](https://img.shields.io/twitter/follow/getsentry?label=getsentry&style=social)](https://twitter.com/intent/follow?screen_name=getsentry) + +#### Apple Privacy Manifest + +Starting with [May 1st 2024](https://developer.apple.com/news/?id=3d8a9yyh), iOS apps are required to declare approved reasons to access certain APIs. This also includes third-party SDKs. +If you are using `sentry-flutter`, update to at least version `7.17.0` to get the updated `sentry-cocoa` native iOS/macOS SDK, supporting the privacy manifest. +All other used dependencies with file declarations are supported by Sentry packages. +Run [flutter pub upgrade](https://docs.flutter.dev/release/upgrade#upgrading-packages) to the latest compatible versions of all the dependencies. From cfa25fc88f8dfc0907b0f6ac9ddd0a5cbb14c3c1 Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Wed, 24 Apr 2024 12:50:21 +0200 Subject: [PATCH 152/237] Add APS to iOS sample (#2008) --- flutter/example/ios/Runner.xcodeproj/project.pbxproj | 3 +++ flutter/example/ios/Runner/RunnerRelease.entitlements | 8 ++++++++ 2 files changed, 11 insertions(+) create mode 100644 flutter/example/ios/Runner/RunnerRelease.entitlements diff --git a/flutter/example/ios/Runner.xcodeproj/project.pbxproj b/flutter/example/ios/Runner.xcodeproj/project.pbxproj index f8c39c79d5..11cb23fc9d 100644 --- a/flutter/example/ios/Runner.xcodeproj/project.pbxproj +++ b/flutter/example/ios/Runner.xcodeproj/project.pbxproj @@ -47,6 +47,7 @@ 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 15A74CDD250075770078F130 /* Buggy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Buggy.h; sourceTree = ""; }; 15A74CDE250075770078F130 /* Buggy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Buggy.m; sourceTree = ""; }; + 247E97BE2BD7CCF100751E38 /* RunnerRelease.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = RunnerRelease.entitlements; sourceTree = ""; }; 38199AEAF0F80C193173BC10 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 3CEA108DF90E0A3E0A377D59 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; @@ -146,6 +147,7 @@ 97C146F01CF9000F007C117D /* Runner */ = { isa = PBXGroup; children = ( + 247E97BE2BD7CCF100751E38 /* RunnerRelease.entitlements */, 15A74CDD250075770078F130 /* Buggy.h */, 15A74CDE250075770078F130 /* Buggy.m */, 97C146FA1CF9000F007C117D /* Main.storyboard */, @@ -731,6 +733,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/RunnerRelease.entitlements; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; DEVELOPMENT_TEAM = 97JCY7859U; ENABLE_BITCODE = NO; diff --git a/flutter/example/ios/Runner/RunnerRelease.entitlements b/flutter/example/ios/Runner/RunnerRelease.entitlements new file mode 100644 index 0000000000..903def2af5 --- /dev/null +++ b/flutter/example/ios/Runner/RunnerRelease.entitlements @@ -0,0 +1,8 @@ + + + + + aps-environment + development + + From 47dd15905a775bad20721cd39865888d3d919f2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Uek=C3=B6tter?= Date: Wed, 24 Apr 2024 14:59:49 +0200 Subject: [PATCH 153/237] Set snapshot to true (#2000) * set snapshot to true * test * test the inverse * changelog --------- Co-authored-by: Giancarlo Buenaflor --- CHANGELOG.md | 5 +++++ dart/lib/src/sentry_exception_factory.dart | 3 +-- dart/test/sentry_exception_factory_test.dart | 21 +++++++++++++++++++- 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7cf3f707c7..9231cb36db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ ## Unreleased +### Feature + +- Set snapshot to `true` when Sentry attaches a stacktrace ([#2000](https://github.com/getsentry/sentry-dart/pull/2000)) + - This may change grouping + ### Fixes - Timing metric aggregates metrics in the created span ([#1994](https://github.com/getsentry/sentry-dart/pull/1994)) diff --git a/dart/lib/src/sentry_exception_factory.dart b/dart/lib/src/sentry_exception_factory.dart index 24ad5ae571..0e4eb25cc3 100644 --- a/dart/lib/src/sentry_exception_factory.dart +++ b/dart/lib/src/sentry_exception_factory.dart @@ -38,9 +38,8 @@ class SentryExceptionFactory { // hence we check again if stackTrace is null and if not, read the current stack trace // but only if attachStacktrace is enabled if (_options.attachStacktrace) { - // TODO: snapshot=true if stackTrace is null - // Requires a major breaking change because of grouping if (stackTrace == null || stackTrace == StackTrace.empty) { + snapshot = true; stackTrace = StackTrace.current; } } diff --git a/dart/test/sentry_exception_factory_test.dart b/dart/test/sentry_exception_factory_test.dart index a70a4c8820..cca350f2b4 100644 --- a/dart/test/sentry_exception_factory_test.dart +++ b/dart/test/sentry_exception_factory_test.dart @@ -188,6 +188,24 @@ void main() { expect(sentryException.value, isNull); }); + + test( + 'set snapshot to true when no stracktrace is present & attachStacktrace == true', + () { + final sentryException = + fixture.getSut(attachStacktrace: true).getSentryException(Object()); + + expect(sentryException.stackTrace!.snapshot, true); + }); + + test( + 'set snapshot to false when no stracktrace is present & attachStacktrace == false', + () { + final sentryException = + fixture.getSut(attachStacktrace: false).getSentryException(Object()); + + expect(sentryException.stackTrace!.snapshot, true); + }); } class CustomError extends Error {} @@ -268,7 +286,8 @@ isolate_instructions: 7526344980, vm_instructions: 752633f000 class Fixture { final options = SentryOptions(dsn: fakeDsn); - SentryExceptionFactory getSut() { + SentryExceptionFactory getSut({bool attachStacktrace = true}) { + options.attachStacktrace = true; return SentryExceptionFactory(options); } } From 92f3690ecf93a1e4c785813e3c5c7080647083f6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 24 Apr 2024 16:20:56 +0200 Subject: [PATCH 154/237] build(deps): bump codecov/codecov-action from 4.2.0 to 4.3.0 (#1989) Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 4.2.0 to 4.3.0. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/7afa10ed9b269c561c2336fd862446844e0cbf71...84508663e988701840491b86de86b666e8a86bed) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor --- .github/workflows/dart.yml | 2 +- .github/workflows/dio.yml | 2 +- .github/workflows/drift.yml | 2 +- .github/workflows/file.yml | 2 +- .github/workflows/flutter.yml | 2 +- .github/workflows/hive.yml | 2 +- .github/workflows/isar.yml | 2 +- .github/workflows/logging.yml | 2 +- .github/workflows/sqflite.yml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml index 897a4ad846..b855465c8e 100644 --- a/.github/workflows/dart.yml +++ b/.github/workflows/dart.yml @@ -68,7 +68,7 @@ jobs: dart pub get webdev build - - uses: codecov/codecov-action@7afa10ed9b269c561c2336fd862446844e0cbf71 # pin@v3 + - uses: codecov/codecov-action@84508663e988701840491b86de86b666e8a86bed # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: name: sentry diff --git a/.github/workflows/dio.yml b/.github/workflows/dio.yml index 88abdf1ad5..e6183d6695 100644 --- a/.github/workflows/dio.yml +++ b/.github/workflows/dio.yml @@ -52,7 +52,7 @@ jobs: dart test -p vm --coverage=coverage --test-randomize-ordering-seed=random --chain-stack-traces dart pub run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.dart_tool/package_config.json --report-on=lib - - uses: codecov/codecov-action@7afa10ed9b269c561c2336fd862446844e0cbf71 # pin@v3 + - uses: codecov/codecov-action@84508663e988701840491b86de86b666e8a86bed # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: name: sentry_dio diff --git a/.github/workflows/drift.yml b/.github/workflows/drift.yml index f45a7df266..7179c7b99f 100644 --- a/.github/workflows/drift.yml +++ b/.github/workflows/drift.yml @@ -93,7 +93,7 @@ jobs: cd drift flutter test --coverage --test-randomize-ordering-seed=random - - uses: codecov/codecov-action@7afa10ed9b269c561c2336fd862446844e0cbf71 # pin@v3 + - uses: codecov/codecov-action@84508663e988701840491b86de86b666e8a86bed # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' with: name: sentry_drift diff --git a/.github/workflows/file.yml b/.github/workflows/file.yml index f883957a2b..1f2a94417e 100644 --- a/.github/workflows/file.yml +++ b/.github/workflows/file.yml @@ -52,7 +52,7 @@ jobs: dart test -p vm --coverage=coverage --test-randomize-ordering-seed=random --chain-stack-traces dart pub run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.dart_tool/package_config.json --report-on=lib - - uses: codecov/codecov-action@7afa10ed9b269c561c2336fd862446844e0cbf71 # pin@v3 + - uses: codecov/codecov-action@84508663e988701840491b86de86b666e8a86bed # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: name: sentry_file diff --git a/.github/workflows/flutter.yml b/.github/workflows/flutter.yml index a40f21ca12..5c17ccb4b7 100644 --- a/.github/workflows/flutter.yml +++ b/.github/workflows/flutter.yml @@ -106,7 +106,7 @@ jobs: flutter test --coverage --test-randomize-ordering-seed=random dart run remove_from_coverage -f coverage/lcov.info -r 'binding.dart' - - uses: codecov/codecov-action@7afa10ed9b269c561c2336fd862446844e0cbf71 # pin@v3 + - uses: codecov/codecov-action@84508663e988701840491b86de86b666e8a86bed # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' with: name: sentry_flutter diff --git a/.github/workflows/hive.yml b/.github/workflows/hive.yml index 0131c0b584..4f861c4f6f 100644 --- a/.github/workflows/hive.yml +++ b/.github/workflows/hive.yml @@ -51,7 +51,7 @@ jobs: dart test -p vm --coverage=coverage --test-randomize-ordering-seed=random --chain-stack-traces dart pub run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.dart_tool/package_config.json --report-on=lib - - uses: codecov/codecov-action@7afa10ed9b269c561c2336fd862446844e0cbf71 # pin@v3 + - uses: codecov/codecov-action@84508663e988701840491b86de86b666e8a86bed # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: name: sentry_hive diff --git a/.github/workflows/isar.yml b/.github/workflows/isar.yml index 6b037c1c5a..d2882f0615 100644 --- a/.github/workflows/isar.yml +++ b/.github/workflows/isar.yml @@ -93,7 +93,7 @@ jobs: cd isar flutter test -j 1 --coverage --test-randomize-ordering-seed=random - - uses: codecov/codecov-action@7afa10ed9b269c561c2336fd862446844e0cbf71 # pin@v3 + - uses: codecov/codecov-action@84508663e988701840491b86de86b666e8a86bed # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' with: name: sentry_isar diff --git a/.github/workflows/logging.yml b/.github/workflows/logging.yml index 3058fa2a6e..2011312eb8 100644 --- a/.github/workflows/logging.yml +++ b/.github/workflows/logging.yml @@ -52,7 +52,7 @@ jobs: dart test -p vm --coverage=coverage --test-randomize-ordering-seed=random --chain-stack-traces dart pub run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.dart_tool/package_config.json --report-on=lib - - uses: codecov/codecov-action@7afa10ed9b269c561c2336fd862446844e0cbf71 # pin@v3 + - uses: codecov/codecov-action@84508663e988701840491b86de86b666e8a86bed # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: name: sentry_logging diff --git a/.github/workflows/sqflite.yml b/.github/workflows/sqflite.yml index b4b8c682a8..c610ef749e 100644 --- a/.github/workflows/sqflite.yml +++ b/.github/workflows/sqflite.yml @@ -93,7 +93,7 @@ jobs: cd sqflite flutter test --coverage --test-randomize-ordering-seed=random - - uses: codecov/codecov-action@7afa10ed9b269c561c2336fd862446844e0cbf71 # pin@v3 + - uses: codecov/codecov-action@84508663e988701840491b86de86b666e8a86bed # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' with: name: sentry_sqflite From 0bed04dc3a892af53ccd5ce7840bf134c3fcbc24 Mon Sep 17 00:00:00 2001 From: Alex Li Date: Thu, 25 Apr 2024 18:54:41 +0800 Subject: [PATCH 155/237] Allows `package_info_plus` v8 (#2010) * Update pubspec.yaml * Update CHANGELOG.md * Update CHANGELOG.md * Update pubspec.yaml * Update CHANGELOG.md --------- Co-authored-by: Giancarlo Buenaflor Co-authored-by: Giancarlo Buenaflor --- CHANGELOG.md | 1 + flutter/pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9231cb36db..33f668dc86 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ - Bump Cocoa SDK from v8.21.0 to v8.24.0 ([#1986](https://github.com/getsentry/sentry-dart/pull/1986)) - [changelog](https://github.com/getsentry/sentry-cocoa/blob/main/CHANGELOG.md#8240) - [diff](https://github.com/getsentry/sentry-cocoa/compare/8.21.0...8.24.0) +- Expand dependency range of `package_info_plus` to allow an open range starting from version 1 ([#2010](https://github.com/getsentry/sentry-dart/pull/2010)) ## 8.0.0 diff --git a/flutter/pubspec.yaml b/flutter/pubspec.yaml index 040bbc47cb..98860c3407 100644 --- a/flutter/pubspec.yaml +++ b/flutter/pubspec.yaml @@ -24,7 +24,7 @@ dependencies: flutter_web_plugins: sdk: flutter sentry: 8.0.0 - package_info_plus: '>=1.0.0 <8.0.0' + package_info_plus: '>=1.0.0' meta: ^1.3.0 ffi: ^2.0.0 From f3c1a790de194809ba0848a9a3bd6080c4ba967c Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Fri, 26 Apr 2024 16:38:06 +0200 Subject: [PATCH 156/237] ci: Android Emulator fix (#2015) * try Java 17 * Test * Test * test * macOS 13 --- .github/workflows/flutter_test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/flutter_test.yml b/.github/workflows/flutter_test.yml index 0f3e9369b4..8fd2887a02 100644 --- a/.github/workflows/flutter_test.yml +++ b/.github/workflows/flutter_test.yml @@ -25,7 +25,7 @@ jobs: access_token: ${{ github.token }} test-android: - runs-on: macos-latest + runs-on: macos-13 timeout-minutes: 30 defaults: run: @@ -41,7 +41,7 @@ jobs: - uses: actions/setup-java@v4 with: distribution: "adopt" - java-version: "11" + java-version: "17" - uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 # pin@v2.16.0 with: From 05e70fd1c314b44d5be0c94b2583cd3197eabc1f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 29 Apr 2024 16:37:50 +0200 Subject: [PATCH 157/237] chore(deps): update Cocoa SDK to v8.25.0 (#2018) * chore: update flutter/scripts/update-cocoa.sh to 8.25.0 * Update * Update * Apply formatting * update --------- Co-authored-by: GitHub Co-authored-by: GIancarlo Buenaflor --- CHANGELOG.md | 6 +- flutter/ios/sentry_flutter.podspec | 2 +- flutter/lib/src/native/cocoa/binding.dart | 120 +++++++++++++++------- 3 files changed, 85 insertions(+), 43 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 33f668dc86..94e042df65 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,9 +13,9 @@ ### Dependencies -- Bump Cocoa SDK from v8.21.0 to v8.24.0 ([#1986](https://github.com/getsentry/sentry-dart/pull/1986)) - - [changelog](https://github.com/getsentry/sentry-cocoa/blob/main/CHANGELOG.md#8240) - - [diff](https://github.com/getsentry/sentry-cocoa/compare/8.21.0...8.24.0) +- Bump Cocoa SDK from v8.21.0 to v8.25.0 ([#2018](https://github.com/getsentry/sentry-dart/pull/2018)) + - [changelog](https://github.com/getsentry/sentry-cocoa/blob/main/CHANGELOG.md#8250) + - [diff](https://github.com/getsentry/sentry-cocoa/compare/8.21.0...8.25.0) - Expand dependency range of `package_info_plus` to allow an open range starting from version 1 ([#2010](https://github.com/getsentry/sentry-dart/pull/2010)) ## 8.0.0 diff --git a/flutter/ios/sentry_flutter.podspec b/flutter/ios/sentry_flutter.podspec index f67b35e2e4..f8085d3b35 100644 --- a/flutter/ios/sentry_flutter.podspec +++ b/flutter/ios/sentry_flutter.podspec @@ -16,7 +16,7 @@ Sentry SDK for Flutter with support to native through sentry-cocoa. :tag => s.version.to_s } s.source_files = 'Classes/**/*' s.public_header_files = 'Classes/**/*.h' - s.dependency 'Sentry/HybridSDK', '8.24.0' + s.dependency 'Sentry/HybridSDK', '8.25.0' s.ios.dependency 'Flutter' s.osx.dependency 'FlutterMacOS' s.ios.deployment_target = '12.0' diff --git a/flutter/lib/src/native/cocoa/binding.dart b/flutter/lib/src/native/cocoa/binding.dart index f8c31e95a7..51a645754b 100644 --- a/flutter/lib/src/native/cocoa/binding.dart +++ b/flutter/lib/src/native/cocoa/binding.dart @@ -3625,7 +3625,7 @@ class SentryCocoa { ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer predicateFormat, - ffi.Pointer argList, + ffi.Pointer<__va_list_tag> argList, ) { return __objc_msgSend_135( obj, @@ -3641,13 +3641,13 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Pointer, - ffi.Pointer)>>('objc_msgSend'); + ffi.Pointer<__va_list_tag>)>>('objc_msgSend'); late final __objc_msgSend_135 = __objc_msgSend_135Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, - ffi.Pointer)>(); + ffi.Pointer<__va_list_tag>)>(); late final _sel_predicateFromMetadataQueryString_1 = _registerName1("predicateFromMetadataQueryString:"); @@ -9537,7 +9537,7 @@ class SentryCocoa { ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer format, - ffi.Pointer argList, + ffi.Pointer<__va_list_tag> argList, ) { return __objc_msgSend_348( obj, @@ -9549,11 +9549,14 @@ class SentryCocoa { late final __objc_msgSend_348Ptr = _lookup< ffi.NativeFunction< - instancetype Function(ffi.Pointer, ffi.Pointer, - ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); + instancetype Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer<__va_list_tag>)>>('objc_msgSend'); late final __objc_msgSend_348 = __objc_msgSend_348Ptr.asFunction< instancetype Function(ffi.Pointer, ffi.Pointer, - ffi.Pointer, ffi.Pointer)>(); + ffi.Pointer, ffi.Pointer<__va_list_tag>)>(); late final _sel_initWithFormat_locale_1 = _registerName1("initWithFormat:locale:"); @@ -9564,7 +9567,7 @@ class SentryCocoa { ffi.Pointer sel, ffi.Pointer format, ffi.Pointer locale, - ffi.Pointer argList, + ffi.Pointer<__va_list_tag> argList, ) { return __objc_msgSend_349( obj, @@ -9582,14 +9585,14 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Pointer, - ffi.Pointer)>>('objc_msgSend'); + ffi.Pointer<__va_list_tag>)>>('objc_msgSend'); late final __objc_msgSend_349 = __objc_msgSend_349Ptr.asFunction< instancetype Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer, - ffi.Pointer)>(); + ffi.Pointer<__va_list_tag>)>(); late final _sel_initWithValidatedFormat_validFormatSpecifiers_error_1 = _registerName1("initWithValidatedFormat:validFormatSpecifiers:error:"); @@ -9672,7 +9675,7 @@ class SentryCocoa { ffi.Pointer sel, ffi.Pointer format, ffi.Pointer validFormatSpecifiers, - ffi.Pointer argList, + ffi.Pointer<__va_list_tag> argList, ffi.Pointer> error, ) { return __objc_msgSend_352( @@ -9692,7 +9695,7 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Pointer, - ffi.Pointer, + ffi.Pointer<__va_list_tag>, ffi.Pointer>)>>('objc_msgSend'); late final __objc_msgSend_352 = __objc_msgSend_352Ptr.asFunction< instancetype Function( @@ -9700,7 +9703,7 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Pointer, - ffi.Pointer, + ffi.Pointer<__va_list_tag>, ffi.Pointer>)>(); late final _sel_initWithValidatedFormat_validFormatSpecifiers_locale_arguments_error_1 = @@ -9712,7 +9715,7 @@ class SentryCocoa { ffi.Pointer format, ffi.Pointer validFormatSpecifiers, ffi.Pointer locale, - ffi.Pointer argList, + ffi.Pointer<__va_list_tag> argList, ffi.Pointer> error, ) { return __objc_msgSend_353( @@ -9734,7 +9737,7 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Pointer, - ffi.Pointer, + ffi.Pointer<__va_list_tag>, ffi.Pointer>)>>('objc_msgSend'); late final __objc_msgSend_353 = __objc_msgSend_353Ptr.asFunction< instancetype Function( @@ -9743,7 +9746,7 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Pointer, - ffi.Pointer, + ffi.Pointer<__va_list_tag>, ffi.Pointer>)>(); late final _sel_initWithData_encoding_1 = @@ -19017,7 +19020,7 @@ class SentryCocoa { ffi.Pointer format, int options, ffi.Pointer locale, - ffi.Pointer arguments, + ffi.Pointer<__va_list_tag> arguments, ) { return __objc_msgSend_673( obj, @@ -19037,7 +19040,7 @@ class SentryCocoa { ffi.Pointer, ffi.Int32, ffi.Pointer, - ffi.Pointer)>>('objc_msgSend'); + ffi.Pointer<__va_list_tag>)>>('objc_msgSend'); late final __objc_msgSend_673 = __objc_msgSend_673Ptr.asFunction< instancetype Function( ffi.Pointer, @@ -19045,7 +19048,7 @@ class SentryCocoa { ffi.Pointer, int, ffi.Pointer, - ffi.Pointer)>(); + ffi.Pointer<__va_list_tag>)>(); late final _sel_localizedAttributedStringWithFormat_1 = _registerName1("localizedAttributedStringWithFormat:"); @@ -19120,7 +19123,7 @@ class SentryCocoa { int options, ffi.Pointer locale, ffi.Pointer context, - ffi.Pointer arguments, + ffi.Pointer<__va_list_tag> arguments, ) { return __objc_msgSend_676( obj, @@ -19142,7 +19145,7 @@ class SentryCocoa { ffi.Int32, ffi.Pointer, ffi.Pointer, - ffi.Pointer)>>('objc_msgSend'); + ffi.Pointer<__va_list_tag>)>>('objc_msgSend'); late final __objc_msgSend_676 = __objc_msgSend_676Ptr.asFunction< instancetype Function( ffi.Pointer, @@ -19151,7 +19154,7 @@ class SentryCocoa { int, ffi.Pointer, ffi.Pointer, - ffi.Pointer)>(); + ffi.Pointer<__va_list_tag>)>(); late final _sel_localizedAttributedStringWithFormat_context_1 = _registerName1("localizedAttributedStringWithFormat:context:"); @@ -21856,7 +21859,7 @@ class SentryCocoa { ffi.Pointer sel, ffi.Pointer name, ffi.Pointer format, - ffi.Pointer argList, + ffi.Pointer<__va_list_tag> argList, ) { return __objc_msgSend_764( obj, @@ -21874,14 +21877,14 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Pointer, - ffi.Pointer)>>('objc_msgSend'); + ffi.Pointer<__va_list_tag>)>>('objc_msgSend'); late final __objc_msgSend_764 = __objc_msgSend_764Ptr.asFunction< void Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer, - ffi.Pointer)>(); + ffi.Pointer<__va_list_tag>)>(); late final _class_NSFileHandle1 = _getClass1("NSFileHandle"); late final _sel_availableData1 = _registerName1("availableData"); @@ -30111,6 +30114,12 @@ class SentryCocoa { ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); + late final _sel_captureReplay1 = _registerName1("captureReplay"); + late final _sel_getReplayId1 = _registerName1("getReplayId"); + late final _sel_addReplayIgnoreClasses_1 = + _registerName1("addReplayIgnoreClasses:"); + late final _sel_addReplayRedactClasses_1 = + _registerName1("addReplayRedactClasses:"); late final _class_SentryCurrentDateProvider1 = _getClass1("SentryCurrentDateProvider"); late final _sel_timezoneOffset1 = _registerName1("timezoneOffset"); @@ -32795,7 +32804,7 @@ class NSString extends NSObject { } NSString initWithFormat_arguments_( - NSString? format, ffi.Pointer argList) { + NSString? format, ffi.Pointer<__va_list_tag> argList) { final _ret = _lib._objc_msgSend_348( _id, _lib._sel_initWithFormat_arguments_1, @@ -32811,7 +32820,7 @@ class NSString extends NSObject { } NSString initWithFormat_locale_arguments_( - NSString? format, NSObject locale, ffi.Pointer argList) { + NSString? format, NSObject locale, ffi.Pointer<__va_list_tag> argList) { final _ret = _lib._objc_msgSend_349( _id, _lib._sel_initWithFormat_locale_arguments_1, @@ -32852,7 +32861,7 @@ class NSString extends NSObject { NSString initWithValidatedFormat_validFormatSpecifiers_arguments_error_( NSString? format, NSString? validFormatSpecifiers, - ffi.Pointer argList, + ffi.Pointer<__va_list_tag> argList, ffi.Pointer> error) { final _ret = _lib._objc_msgSend_352( _id, @@ -32869,7 +32878,7 @@ class NSString extends NSObject { NSString? format, NSString? validFormatSpecifiers, NSObject locale, - ffi.Pointer argList, + ffi.Pointer<__va_list_tag> argList, ffi.Pointer> error) { final _ret = _lib._objc_msgSend_353( _id, @@ -37988,7 +37997,7 @@ class NSPredicate extends NSObject { } static NSPredicate predicateWithFormat_arguments_(SentryCocoa _lib, - NSString? predicateFormat, ffi.Pointer argList) { + NSString? predicateFormat, ffi.Pointer<__va_list_tag> argList) { final _ret = _lib._objc_msgSend_135( _lib._class_NSPredicate1, _lib._sel_predicateWithFormat_arguments_1, @@ -38144,6 +38153,18 @@ class NSPredicate extends NSObject { } } +class __va_list_tag extends ffi.Struct { + @ffi.UnsignedInt() + external int gp_offset; + + @ffi.UnsignedInt() + external int fp_offset; + + external ffi.Pointer overflow_arg_area; + + external ffi.Pointer reg_save_area; +} + bool _ObjCBlock_bool_ObjCObject_NSDictionary_fnPtrTrampoline( ffi.Pointer<_ObjCBlock> block, ffi.Pointer arg0, @@ -51429,7 +51450,7 @@ class NSMutableString extends NSString { @override NSMutableString initWithFormat_arguments_( - NSString? format, ffi.Pointer argList) { + NSString? format, ffi.Pointer<__va_list_tag> argList) { final _ret = _lib._objc_msgSend_348( _id, _lib._sel_initWithFormat_arguments_1, @@ -51447,7 +51468,7 @@ class NSMutableString extends NSString { @override NSMutableString initWithFormat_locale_arguments_( - NSString? format, NSObject locale, ffi.Pointer argList) { + NSString? format, NSObject locale, ffi.Pointer<__va_list_tag> argList) { final _ret = _lib._objc_msgSend_349( _id, _lib._sel_initWithFormat_locale_arguments_1, @@ -51492,7 +51513,7 @@ class NSMutableString extends NSString { initWithValidatedFormat_validFormatSpecifiers_arguments_error_( NSString? format, NSString? validFormatSpecifiers, - ffi.Pointer argList, + ffi.Pointer<__va_list_tag> argList, ffi.Pointer> error) { final _ret = _lib._objc_msgSend_352( _id, @@ -51510,7 +51531,7 @@ class NSMutableString extends NSString { NSString? format, NSString? validFormatSpecifiers, NSObject locale, - ffi.Pointer argList, + ffi.Pointer<__va_list_tag> argList, ffi.Pointer> error) { final _ret = _lib._objc_msgSend_353( _id, @@ -52820,7 +52841,7 @@ class NSAttributedString extends NSObject { NSAttributedString? format, int options, NSLocale? locale, - ffi.Pointer arguments) { + ffi.Pointer<__va_list_tag> arguments) { final _ret = _lib._objc_msgSend_673( _id, _lib._sel_initWithFormat_options_locale_arguments_1, @@ -52870,7 +52891,7 @@ class NSAttributedString extends NSObject { int options, NSLocale? locale, NSDictionary? context, - ffi.Pointer arguments) { + ffi.Pointer<__va_list_tag> arguments) { final _ret = _lib._objc_msgSend_676( _id, _lib._sel_initWithFormat_options_locale_context_arguments_1, @@ -53605,7 +53626,7 @@ class NSMutableAttributedString extends NSAttributedString { NSAttributedString? format, int options, NSLocale? locale, - ffi.Pointer arguments) { + ffi.Pointer<__va_list_tag> arguments) { final _ret = _lib._objc_msgSend_673( _id, _lib._sel_initWithFormat_options_locale_arguments_1, @@ -53657,7 +53678,7 @@ class NSMutableAttributedString extends NSAttributedString { int options, NSLocale? locale, NSDictionary? context, - ffi.Pointer arguments) { + ffi.Pointer<__va_list_tag> arguments) { final _ret = _lib._objc_msgSend_676( _id, _lib._sel_initWithFormat_options_locale_context_arguments_1, @@ -57163,7 +57184,7 @@ class NSException extends NSObject { } static void raise_format_arguments_(SentryCocoa _lib, NSString name, - NSString? format, ffi.Pointer argList) { + NSString? format, ffi.Pointer<__va_list_tag> argList) { _lib._objc_msgSend_764( _lib._class_NSException1, _lib._sel_raise_format_arguments_1, @@ -70884,6 +70905,27 @@ class PrivateSentrySDKOnly extends NSObject { return SentryBreadcrumb._(_ret, _lib, retain: true, release: true); } + static void captureReplay(SentryCocoa _lib) { + _lib._objc_msgSend_1( + _lib._class_PrivateSentrySDKOnly1, _lib._sel_captureReplay1); + } + + static NSString getReplayId(SentryCocoa _lib) { + final _ret = _lib._objc_msgSend_20( + _lib._class_PrivateSentrySDKOnly1, _lib._sel_getReplayId1); + return NSString._(_ret, _lib, retain: true, release: true); + } + + static void addReplayIgnoreClasses_(SentryCocoa _lib, NSArray? classes) { + _lib._objc_msgSend_441(_lib._class_PrivateSentrySDKOnly1, + _lib._sel_addReplayIgnoreClasses_1, classes?._id ?? ffi.nullptr); + } + + static void addReplayRedactClasses_(SentryCocoa _lib, NSArray? classes) { + _lib._objc_msgSend_441(_lib._class_PrivateSentrySDKOnly1, + _lib._sel_addReplayRedactClasses_1, classes?._id ?? ffi.nullptr); + } + @override PrivateSentrySDKOnly init() { final _ret = _lib._objc_msgSend_2(_id, _lib._sel_init1); From 0beea56ddb940e15461d6fd54288ee5bd5bd036f Mon Sep 17 00:00:00 2001 From: getsentry-bot Date: Mon, 29 Apr 2024 14:51:28 +0000 Subject: [PATCH 158/237] release: 8.1.0 --- CHANGELOG.md | 2 +- dart/lib/src/version.dart | 2 +- dart/pubspec.yaml | 2 +- dio/lib/src/version.dart | 2 +- dio/pubspec.yaml | 4 ++-- drift/lib/src/version.dart | 2 +- drift/pubspec.yaml | 4 ++-- file/lib/src/version.dart | 2 +- file/pubspec.yaml | 4 ++-- flutter/example/pubspec.yaml | 2 +- flutter/lib/src/version.dart | 2 +- flutter/pubspec.yaml | 4 ++-- hive/lib/src/version.dart | 2 +- hive/pubspec.yaml | 4 ++-- isar/lib/src/version.dart | 2 +- isar/pubspec.yaml | 4 ++-- logging/lib/src/version.dart | 2 +- logging/pubspec.yaml | 4 ++-- sqflite/lib/src/version.dart | 2 +- sqflite/pubspec.yaml | 4 ++-- 20 files changed, 28 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 94e042df65..21d242e8f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## Unreleased +## 8.1.0 ### Feature diff --git a/dart/lib/src/version.dart b/dart/lib/src/version.dart index a62754b2dc..398b593f20 100644 --- a/dart/lib/src/version.dart +++ b/dart/lib/src/version.dart @@ -9,7 +9,7 @@ library version; /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.0.0'; +const String sdkVersion = '8.1.0'; String sdkName(bool isWeb) => isWeb ? _browserSdkName : _ioSdkName; diff --git a/dart/pubspec.yaml b/dart/pubspec.yaml index bc2ef30452..8dff6e892f 100644 --- a/dart/pubspec.yaml +++ b/dart/pubspec.yaml @@ -1,5 +1,5 @@ name: sentry -version: 8.0.0 +version: 8.1.0 description: > A crash reporting library for Dart that sends crash reports to Sentry.io. This library supports Dart VM and Web. For Flutter consider sentry_flutter instead. diff --git a/dio/lib/src/version.dart b/dio/lib/src/version.dart index 73fa6fc4a4..927f78c9b7 100644 --- a/dio/lib/src/version.dart +++ b/dio/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.0.0'; +const String sdkVersion = '8.1.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_dio'; diff --git a/dio/pubspec.yaml b/dio/pubspec.yaml index 9862c54b69..4afea3a748 100644 --- a/dio/pubspec.yaml +++ b/dio/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_dio description: An integration which adds support for performance tracing for the Dio package. -version: 8.0.0 +version: 8.1.0 homepage: https://docs.sentry.io/platforms/dart/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -19,7 +19,7 @@ platforms: dependencies: dio: ^5.0.0 - sentry: 8.0.0 + sentry: 8.1.0 dev_dependencies: meta: ^1.3.0 diff --git a/drift/lib/src/version.dart b/drift/lib/src/version.dart index d71a56fddd..d34cbbe2af 100644 --- a/drift/lib/src/version.dart +++ b/drift/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.0.0'; +const String sdkVersion = '8.1.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_drift'; diff --git a/drift/pubspec.yaml b/drift/pubspec.yaml index d468e90a12..076dc8be56 100644 --- a/drift/pubspec.yaml +++ b/drift/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_drift description: An integration which adds support for performance tracing for the drift package. -version: 8.0.0 +version: 8.1.0 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -17,7 +17,7 @@ platforms: web: dependencies: - sentry: 8.0.0 + sentry: 8.1.0 meta: ^1.3.0 drift: ^2.13.0 diff --git a/file/lib/src/version.dart b/file/lib/src/version.dart index cead856a2f..038a27750a 100644 --- a/file/lib/src/version.dart +++ b/file/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.0.0'; +const String sdkVersion = '8.1.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_file'; diff --git a/file/pubspec.yaml b/file/pubspec.yaml index 3871d9ab38..60336b723e 100644 --- a/file/pubspec.yaml +++ b/file/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_file description: An integration which adds support for performance tracing for dart.io.File. -version: 8.0.0 +version: 8.1.0 homepage: https://docs.sentry.io/platforms/dart/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -17,7 +17,7 @@ platforms: windows: dependencies: - sentry: 8.0.0 + sentry: 8.1.0 meta: ^1.3.0 dev_dependencies: diff --git a/flutter/example/pubspec.yaml b/flutter/example/pubspec.yaml index ef571be2a7..46b0031191 100644 --- a/flutter/example/pubspec.yaml +++ b/flutter/example/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_flutter_example description: Demonstrates how to use the sentry_flutter plugin. -version: 8.0.0 +version: 8.1.0 publish_to: 'none' # Remove this line if you wish to publish to pub.dev diff --git a/flutter/lib/src/version.dart b/flutter/lib/src/version.dart index 233de685ed..f050668b3d 100644 --- a/flutter/lib/src/version.dart +++ b/flutter/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.0.0'; +const String sdkVersion = '8.1.0'; /// The default SDK name reported to Sentry.io in the submitted events. const String sdkName = 'sentry.dart.flutter'; diff --git a/flutter/pubspec.yaml b/flutter/pubspec.yaml index 98860c3407..ada7c12aeb 100644 --- a/flutter/pubspec.yaml +++ b/flutter/pubspec.yaml @@ -1,5 +1,5 @@ name: sentry_flutter -version: 8.0.0 +version: 8.1.0 description: Sentry SDK for Flutter. This package aims to support different Flutter targets by relying on the many platforms supported by Sentry with native SDKs. homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart @@ -23,7 +23,7 @@ dependencies: sdk: flutter flutter_web_plugins: sdk: flutter - sentry: 8.0.0 + sentry: 8.1.0 package_info_plus: '>=1.0.0' meta: ^1.3.0 ffi: ^2.0.0 diff --git a/hive/lib/src/version.dart b/hive/lib/src/version.dart index 524aa89e7f..ed1edf60f3 100644 --- a/hive/lib/src/version.dart +++ b/hive/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.0.0'; +const String sdkVersion = '8.1.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_hive'; diff --git a/hive/pubspec.yaml b/hive/pubspec.yaml index 6aeaed7f68..23473bf73f 100644 --- a/hive/pubspec.yaml +++ b/hive/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_hive description: An integration which adds support for performance tracing for the hive package. -version: 8.0.0 +version: 8.1.0 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -17,7 +17,7 @@ platforms: web: dependencies: - sentry: 8.0.0 + sentry: 8.1.0 hive: ^2.2.3 meta: ^1.3.0 diff --git a/isar/lib/src/version.dart b/isar/lib/src/version.dart index 7410567886..9aa858df6f 100644 --- a/isar/lib/src/version.dart +++ b/isar/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.0.0'; +const String sdkVersion = '8.1.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_isar'; diff --git a/isar/pubspec.yaml b/isar/pubspec.yaml index fb83755493..73b9343d39 100644 --- a/isar/pubspec.yaml +++ b/isar/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_isar description: An integration which adds support for performance tracing for the isar package. -version: 8.0.0 +version: 8.1.0 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -20,7 +20,7 @@ platforms: dependencies: isar: ^3.1.0 isar_flutter_libs: ^3.1.0 # contains Isar Core - sentry: 8.0.0 + sentry: 8.1.0 meta: ^1.3.0 path: ^1.8.3 diff --git a/logging/lib/src/version.dart b/logging/lib/src/version.dart index 21a66180d1..5f31854913 100644 --- a/logging/lib/src/version.dart +++ b/logging/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.0.0'; +const String sdkVersion = '8.1.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_logging'; diff --git a/logging/pubspec.yaml b/logging/pubspec.yaml index b9855f47de..4ee561b50b 100644 --- a/logging/pubspec.yaml +++ b/logging/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_logging description: An integration which adds support for recording log from the logging package. -version: 8.0.0 +version: 8.1.0 homepage: https://docs.sentry.io/platforms/dart/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -19,7 +19,7 @@ platforms: dependencies: logging: ^1.0.0 - sentry: 8.0.0 + sentry: 8.1.0 dev_dependencies: lints: ^3.0.0 diff --git a/sqflite/lib/src/version.dart b/sqflite/lib/src/version.dart index d0fae42df4..81f041236f 100644 --- a/sqflite/lib/src/version.dart +++ b/sqflite/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.0.0'; +const String sdkVersion = '8.1.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_sqflite'; diff --git a/sqflite/pubspec.yaml b/sqflite/pubspec.yaml index 32d060abef..3146f483b1 100644 --- a/sqflite/pubspec.yaml +++ b/sqflite/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_sqflite description: An integration which adds support for performance tracing for the sqflite package. -version: 8.0.0 +version: 8.1.0 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -15,7 +15,7 @@ platforms: macos: dependencies: - sentry: 8.0.0 + sentry: 8.1.0 sqflite: ^2.0.0 sqflite_common: ^2.0.0 meta: ^1.3.0 From 2d457b8545db2918c81e10fe320e97d30210f90f Mon Sep 17 00:00:00 2001 From: Bruno Garcia Date: Tue, 30 Apr 2024 04:41:13 -0400 Subject: [PATCH 159/237] date range to license - 2020-2024 (#2025) --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 8566a0280c..ed77f4ccbb 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2020 Sentry +Copyright (c) 2020-2024 Sentry Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From a4eae38e4c1a2b033bf66679ee179fab1bd8ca35 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Apr 2024 13:13:43 +0200 Subject: [PATCH 160/237] build(deps): bump gradle/gradle-build-action from 2.11.1 to 3.3.2 (#2021) Bumps [gradle/gradle-build-action](https://github.com/gradle/gradle-build-action) from 2.11.1 to 3.3.2. - [Release notes](https://github.com/gradle/gradle-build-action/releases) - [Commits](https://github.com/gradle/gradle-build-action/compare/v2.11.1...4c39dd82cd5e1ec7c6fa0173bb41b4b6bb3b86ff) --- updated-dependencies: - dependency-name: gradle/gradle-build-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/flutter_integration_test.yml | 2 +- .github/workflows/flutter_test.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/flutter_integration_test.yml b/.github/workflows/flutter_integration_test.yml index 7f23dec0da..a9cdd2aa43 100644 --- a/.github/workflows/flutter_integration_test.yml +++ b/.github/workflows/flutter_integration_test.yml @@ -49,7 +49,7 @@ jobs: run: flutter pub get - name: Gradle cache - uses: gradle/gradle-build-action@982da8e78c05368c70dac0351bb82647a9e9a5d2 # pin@v2.11.1 + uses: gradle/gradle-build-action@4c39dd82cd5e1ec7c6fa0173bb41b4b6bb3b86ff # pin@v3.3.2 - name: AVD cache uses: actions/cache@v4 diff --git a/.github/workflows/flutter_test.yml b/.github/workflows/flutter_test.yml index 8fd2887a02..594570857f 100644 --- a/.github/workflows/flutter_test.yml +++ b/.github/workflows/flutter_test.yml @@ -54,7 +54,7 @@ jobs: run: flutter pub get - name: Gradle cache - uses: gradle/gradle-build-action@8baac4c8ef753599f92eeb509c246d09d6250fa6 # pin@v3.0.0 + uses: gradle/gradle-build-action@4c39dd82cd5e1ec7c6fa0173bb41b4b6bb3b86ff # pin@v3.0.0 - name: AVD cache uses: actions/cache@v4 From ed6a3b630d112d4cc06de4e70ed1613e5db8ed9f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Apr 2024 16:02:13 +0200 Subject: [PATCH 161/237] build(deps): bump reactivecircus/android-emulator-runner (#2019) Bumps [reactivecircus/android-emulator-runner](https://github.com/reactivecircus/android-emulator-runner) from 2.28.0 to 2.30.1. - [Release notes](https://github.com/reactivecircus/android-emulator-runner/releases) - [Changelog](https://github.com/ReactiveCircus/android-emulator-runner/blob/main/CHANGELOG.md) - [Commits](https://github.com/reactivecircus/android-emulator-runner/compare/v2.28.0...6b0df4b0efb23bb0ec63d881db79aefbc976e4b2) --- updated-dependencies: - dependency-name: reactivecircus/android-emulator-runner dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor --- .github/workflows/flutter_integration_test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/flutter_integration_test.yml b/.github/workflows/flutter_integration_test.yml index a9cdd2aa43..d6c75ba38f 100644 --- a/.github/workflows/flutter_integration_test.yml +++ b/.github/workflows/flutter_integration_test.yml @@ -62,7 +62,7 @@ jobs: - name: create AVD and generate snapshot for caching if: steps.avd-cache.outputs.cache-hit != 'true' - uses: reactivecircus/android-emulator-runner@d94c3fbe4fe6a29e4a5ba47c12fb47677c73656b #pin@v2.28.0 + uses: reactivecircus/android-emulator-runner@6b0df4b0efb23bb0ec63d881db79aefbc976e4b2 #pin@v2.30.1 with: working-directory: ./flutter/example api-level: 21 @@ -74,7 +74,7 @@ jobs: script: echo 'Generated AVD snapshot for caching.' - name: launch android emulator & run android integration test - uses: reactivecircus/android-emulator-runner@d94c3fbe4fe6a29e4a5ba47c12fb47677c73656b #pin@v2.28.0 + uses: reactivecircus/android-emulator-runner@6b0df4b0efb23bb0ec63d881db79aefbc976e4b2 #pin@v2.30.1 with: working-directory: ./flutter/example api-level: 21 From 52a705261dd388e050bd5c14ba5c578554cfdf80 Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Tue, 30 Apr 2024 17:12:27 +0200 Subject: [PATCH 162/237] release 8.1.0: update changelog (#2026) * Update CHANGELOG * Update grouping * Update * Apply suggestions from code review Co-authored-by: Karl Heinz Struggl --------- Co-authored-by: Karl Heinz Struggl --- CHANGELOG.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 21d242e8f1..eea872b71e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,8 +4,9 @@ ### Feature -- Set snapshot to `true` when Sentry attaches a stacktrace ([#2000](https://github.com/getsentry/sentry-dart/pull/2000)) - - This may change grouping +- Set snapshot to `true` if stacktrace is not provided ([#2000](https://github.com/getsentry/sentry-dart/pull/2000)) + - If the stacktrace is not provided, the Sentry SDK will fetch the current stacktrace via `StackTrace.current` and the snapshot will be set to `true` - **this may change the grouping behavior** + - `snapshot = true` means it's a synthetic exception, reflecting the current state of the thread rather than the stack trace of a real exception ### Fixes From 6575860857eb9784ce13785f3a2eeade01013808 Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Fri, 3 May 2024 19:21:53 +0200 Subject: [PATCH 163/237] App start: Add spans to first transaction (#2009) * commit * Update * Remove print * Remove comments * Update * Add linting * Update CHANGELOG * Update CHANGELOG.md * Update naming * Update naming * Update naming * Update description from first frame render to initial frame render * update * dart format * Update comments * Update * Update * Update * Update * Update * Fix tests * Fix test * Add unused import * Review improvements * Update CHANGELOG * Update CHANGELOG --- CHANGELOG.md | 8 +- .../io/sentry/flutter/SentryFlutterPlugin.kt | 4 + .../Classes/SentryFlutterPluginApple.swift | 5 + .../native_app_start_event_processor.dart | 90 ++++++++++++- .../native_app_start_integration.dart | 43 +++++-- flutter/lib/src/native/sentry_native.dart | 11 +- flutter/lib/src/sentry_flutter.dart | 5 + .../native_app_start_integration_test.dart | 118 +++++++++++++++++- .../sentry_display_widget_test.dart | 2 + flutter/test/sentry_native_channel_test.dart | 1 + flutter/test/sentry_native_test.dart | 3 +- .../test/sentry_navigator_observer_test.dart | 2 + 12 files changed, 271 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index eea872b71e..c545ea3e39 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,14 @@ # Changelog +## Unreleased + +### Features + +- Adds app start spans to first transaction ([#2009](https://github.com/getsentry/sentry-dart/pull/2009)) + ## 8.1.0 -### Feature +### Features - Set snapshot to `true` if stacktrace is not provided ([#2000](https://github.com/getsentry/sentry-dart/pull/2000)) - If the stacktrace is not provided, the Sentry SDK will fetch the current stacktrace via `StackTrace.current` and the snapshot will be set to `true` - **this may change the grouping behavior** diff --git a/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutterPlugin.kt b/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutterPlugin.kt index 5aad15a0b3..8d92c9178c 100644 --- a/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutterPlugin.kt +++ b/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutterPlugin.kt @@ -36,8 +36,11 @@ class SentryFlutterPlugin : FlutterPlugin, MethodCallHandler, ActivityAware { private var activity: WeakReference? = null private var framesTracker: ActivityFramesTracker? = null + private var pluginRegistrationTime: Long? = null override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) { + pluginRegistrationTime = System.currentTimeMillis() + context = flutterPluginBinding.applicationContext channel = MethodChannel(flutterPluginBinding.binaryMessenger, "sentry_flutter") channel.setMethodCallHandler(this) @@ -137,6 +140,7 @@ class SentryFlutterPlugin : FlutterPlugin, MethodCallHandler, ActivityAware { } else { val appStartTimeMillis = DateUtils.nanosToMillis(appStartTime.nanoTimestamp().toDouble()) val item = mapOf( + "pluginRegistrationTime" to pluginRegistrationTime, "appStartTime" to appStartTimeMillis, "isColdStart" to isColdStart, ) diff --git a/flutter/ios/Classes/SentryFlutterPluginApple.swift b/flutter/ios/Classes/SentryFlutterPluginApple.swift index ec6eb7cdb7..97a10c3324 100644 --- a/flutter/ios/Classes/SentryFlutterPluginApple.swift +++ b/flutter/ios/Classes/SentryFlutterPluginApple.swift @@ -26,7 +26,11 @@ public class SentryFlutterPluginApple: NSObject, FlutterPlugin { #endif } + private static var pluginRegistrationTime: Int64 = 0 + public static func register(with registrar: FlutterPluginRegistrar) { + pluginRegistrationTime = Int64(Date().timeIntervalSince1970 * 1000) + #if os(iOS) let channel = FlutterMethodChannel(name: "sentry_flutter", binaryMessenger: registrar.messenger()) #elseif os(macOS) @@ -387,6 +391,7 @@ public class SentryFlutterPluginApple: NSObject, FlutterPlugin { let isColdStart = appStartMeasurement.type == .cold let item: [String: Any] = [ + "pluginRegistrationTime": SentryFlutterPluginApple.pluginRegistrationTime, "appStartTime": appStartTime, "isColdStart": isColdStart ] diff --git a/flutter/lib/src/event_processor/native_app_start_event_processor.dart b/flutter/lib/src/event_processor/native_app_start_event_processor.dart index f75bbc4833..d22226f605 100644 --- a/flutter/lib/src/event_processor/native_app_start_event_processor.dart +++ b/flutter/lib/src/event_processor/native_app_start_event_processor.dart @@ -1,16 +1,24 @@ -import 'dart:async'; +// ignore_for_file: invalid_use_of_internal_member -import 'package:sentry/sentry.dart'; +import 'dart:async'; +import '../../sentry_flutter.dart'; import '../integrations/integrations.dart'; import '../native/sentry_native.dart'; +// ignore: implementation_imports +import 'package:sentry/src/sentry_tracer.dart'; + /// EventProcessor that enriches [SentryTransaction] objects with app start /// measurement. class NativeAppStartEventProcessor implements EventProcessor { final SentryNative _native; + final Hub _hub; - NativeAppStartEventProcessor(this._native); + NativeAppStartEventProcessor( + this._native, { + Hub? hub, + }) : _hub = hub ?? HubAdapter(); @override Future apply(SentryEvent event, Hint hint) async { @@ -25,6 +33,82 @@ class NativeAppStartEventProcessor implements EventProcessor { event.measurements[measurement.name] = measurement; _native.didAddAppStartMeasurement = true; } + + if (appStartInfo != null) { + await _attachAppStartSpans(appStartInfo, event.tracer); + } + return event; } + + Future _attachAppStartSpans( + AppStartInfo appStartInfo, SentryTracer transaction) async { + final transactionTraceId = transaction.context.traceId; + + final appStartSpan = await _createAndFinishSpan( + tracer: transaction, + operation: appStartInfo.appStartTypeOperation, + description: appStartInfo.appStartTypeDescription, + parentSpanId: transaction.context.spanId, + traceId: transactionTraceId, + startTimestamp: appStartInfo.start, + endTimestamp: appStartInfo.end); + + final pluginRegistrationSpan = await _createAndFinishSpan( + tracer: transaction, + operation: appStartInfo.appStartTypeOperation, + description: appStartInfo.pluginRegistrationDescription, + parentSpanId: appStartSpan.context.spanId, + traceId: transactionTraceId, + startTimestamp: appStartInfo.start, + endTimestamp: appStartInfo.pluginRegistration); + + final mainIsolateSetupSpan = await _createAndFinishSpan( + tracer: transaction, + operation: appStartInfo.appStartTypeOperation, + description: appStartInfo.mainIsolateSetupDescription, + parentSpanId: appStartSpan.context.spanId, + traceId: transactionTraceId, + startTimestamp: appStartInfo.pluginRegistration, + endTimestamp: appStartInfo.mainIsolateStart); + + final firstFrameRenderSpan = await _createAndFinishSpan( + tracer: transaction, + operation: appStartInfo.appStartTypeOperation, + description: appStartInfo.firstFrameRenderDescription, + parentSpanId: appStartSpan.context.spanId, + traceId: transactionTraceId, + startTimestamp: appStartInfo.mainIsolateStart, + endTimestamp: appStartInfo.end); + + transaction.children.addAll([ + appStartSpan, + pluginRegistrationSpan, + mainIsolateSetupSpan, + firstFrameRenderSpan + ]); + } + + Future _createAndFinishSpan({ + required SentryTracer tracer, + required String operation, + required String description, + required SpanId parentSpanId, + required SentryId traceId, + required DateTime startTimestamp, + required DateTime endTimestamp, + }) async { + final span = SentrySpan( + tracer, + SentrySpanContext( + operation: operation, + description: description, + parentSpanId: parentSpanId, + traceId: traceId, + ), + _hub, + startTimestamp: startTimestamp); + await span.finish(endTimestamp: endTimestamp); + return span; + } } diff --git a/flutter/lib/src/integrations/native_app_start_integration.dart b/flutter/lib/src/integrations/native_app_start_integration.dart index 0ba5c77c4f..923d1a1bfa 100644 --- a/flutter/lib/src/integrations/native_app_start_integration.dart +++ b/flutter/lib/src/integrations/native_app_start_integration.dart @@ -53,7 +53,11 @@ class NativeAppStartIntegration extends Integration { if (isIntegrationTest) { final appStartInfo = AppStartInfo(AppStartType.cold, start: DateTime.now(), - end: DateTime.now().add(const Duration(milliseconds: 100))); + end: DateTime.now().add(const Duration(milliseconds: 100)), + pluginRegistration: + DateTime.now().add(const Duration(milliseconds: 50)), + mainIsolateStart: + DateTime.now().add(const Duration(milliseconds: 60))); setAppStartInfo(appStartInfo); return; } @@ -67,16 +71,22 @@ class NativeAppStartIntegration extends Integration { // We only assign the current time if it's not already set - this is useful in tests // ignore: invalid_use_of_internal_member _native.appStartEnd ??= options.clock(); - final appStartEnd = _native.appStartEnd; + final appStartEndDateTime = _native.appStartEnd; final nativeAppStart = await _native.fetchNativeAppStart(); + final pluginRegistrationTime = nativeAppStart?.pluginRegistrationTime; + final mainIsolateStartDateTime = SentryFlutter.mainIsolateStartTime; - if (nativeAppStart == null || appStartEnd == null) { + if (nativeAppStart == null || + appStartEndDateTime == null || + pluginRegistrationTime == null) { return; } final appStartDateTime = DateTime.fromMillisecondsSinceEpoch( nativeAppStart.appStartTime.toInt()); - final duration = appStartEnd.difference(appStartDateTime); + final duration = appStartEndDateTime.difference(appStartDateTime); + final pluginRegistrationDateTime = + DateTime.fromMillisecondsSinceEpoch(pluginRegistrationTime); // We filter out app start more than 60s. // This could be due to many different reasons. @@ -93,9 +103,11 @@ class NativeAppStartIntegration extends Integration { final appStartInfo = AppStartInfo( nativeAppStart.isColdStart ? AppStartType.cold : AppStartType.warm, - start: DateTime.fromMillisecondsSinceEpoch( - nativeAppStart.appStartTime.toInt()), - end: appStartEnd); + start: appStartDateTime, + end: appStartEndDateTime, + pluginRegistration: pluginRegistrationDateTime, + mainIsolateStart: mainIsolateStartDateTime); + setAppStartInfo(appStartInfo); }); } @@ -109,11 +121,18 @@ class NativeAppStartIntegration extends Integration { enum AppStartType { cold, warm } class AppStartInfo { - AppStartInfo(this.type, {required this.start, required this.end}); + AppStartInfo(this.type, + {required this.start, + required this.end, + required this.pluginRegistration, + required this.mainIsolateStart}); final AppStartType type; final DateTime start; final DateTime end; + final DateTime pluginRegistration; + final DateTime mainIsolateStart; + Duration get duration => end.difference(start); SentryMeasurement toMeasurement() { @@ -121,4 +140,12 @@ class AppStartInfo { ? SentryMeasurement.coldAppStart(duration) : SentryMeasurement.warmAppStart(duration); } + + String get appStartTypeOperation => 'app.start.${type.name}'; + + String get appStartTypeDescription => + type == AppStartType.cold ? 'Cold start' : 'Warm start'; + final pluginRegistrationDescription = 'App start to plugin registration'; + final mainIsolateSetupDescription = 'Main isolate setup'; + final firstFrameRenderDescription = 'First frame render'; } diff --git a/flutter/lib/src/native/sentry_native.dart b/flutter/lib/src/native/sentry_native.dart index a7973f8a12..4d26239a60 100644 --- a/flutter/lib/src/native/sentry_native.dart +++ b/flutter/lib/src/native/sentry_native.dart @@ -129,15 +129,20 @@ class SentryNative { } class NativeAppStart { - NativeAppStart(this.appStartTime, this.isColdStart); + NativeAppStart( + {required this.appStartTime, + required this.pluginRegistrationTime, + required this.isColdStart}); double appStartTime; + int pluginRegistrationTime; bool isColdStart; factory NativeAppStart.fromJson(Map json) { return NativeAppStart( - json['appStartTime'] as double, - json['isColdStart'] as bool, + appStartTime: json['appStartTime'] as double, + pluginRegistrationTime: json['pluginRegistrationTime'] as int, + isColdStart: json['isColdStart'] as bool, ); } } diff --git a/flutter/lib/src/sentry_flutter.dart b/flutter/lib/src/sentry_flutter.dart index 1931e86981..60c9811bf0 100644 --- a/flutter/lib/src/sentry_flutter.dart +++ b/flutter/lib/src/sentry_flutter.dart @@ -34,6 +34,11 @@ typedef FlutterOptionsConfiguration = FutureOr Function( mixin SentryFlutter { static const _channel = MethodChannel('sentry_flutter'); + /// Represents the time when the main isolate is set up and ready to execute. + @internal + // ignore: invalid_use_of_internal_member + static DateTime mainIsolateStartTime = getUtcDateTime(); + static Future init( FlutterOptionsConfiguration optionsConfiguration, { AppRunner? appRunner, diff --git a/flutter/test/integrations/native_app_start_integration_test.dart b/flutter/test/integrations/native_app_start_integration_test.dart index 70b088cfec..a6b712af12 100644 --- a/flutter/test/integrations/native_app_start_integration_test.dart +++ b/flutter/test/integrations/native_app_start_integration_test.dart @@ -1,4 +1,5 @@ @TestOn('vm') +import 'package:collection/collection.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/mockito.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; @@ -23,7 +24,8 @@ void main() { test('native app start measurement added to first transaction', () async { fixture.native.appStartEnd = DateTime.fromMillisecondsSinceEpoch(10); - fixture.binding.nativeAppStart = NativeAppStart(0, true); + fixture.binding.nativeAppStart = NativeAppStart( + appStartTime: 0, pluginRegistrationTime: 10, isColdStart: true); fixture.getNativeAppStartIntegration().call(fixture.hub, fixture.options); @@ -42,7 +44,8 @@ void main() { test('native app start measurement not added to following transactions', () async { fixture.native.appStartEnd = DateTime.fromMillisecondsSinceEpoch(10); - fixture.binding.nativeAppStart = NativeAppStart(0, true); + fixture.binding.nativeAppStart = NativeAppStart( + appStartTime: 0, pluginRegistrationTime: 10, isColdStart: true); fixture.getNativeAppStartIntegration().call(fixture.hub, fixture.options); @@ -61,7 +64,8 @@ void main() { test('measurements appended', () async { fixture.native.appStartEnd = DateTime.fromMillisecondsSinceEpoch(10); - fixture.binding.nativeAppStart = NativeAppStart(0, true); + fixture.binding.nativeAppStart = NativeAppStart( + appStartTime: 0, pluginRegistrationTime: 10, isColdStart: true); final measurement = SentryMeasurement.warmAppStart(Duration(seconds: 1)); fixture.getNativeAppStartIntegration().call(fixture.hub, fixture.options); @@ -83,7 +87,8 @@ void main() { test('native app start measurement not added if more than 60s', () async { fixture.native.appStartEnd = DateTime.fromMillisecondsSinceEpoch(60001); - fixture.binding.nativeAppStart = NativeAppStart(0, true); + fixture.binding.nativeAppStart = NativeAppStart( + appStartTime: 0, pluginRegistrationTime: 10, isColdStart: true); fixture.getNativeAppStartIntegration().call(fixture.hub, fixture.options); @@ -100,7 +105,8 @@ void main() { test('native app start integration is called and sets app start info', () async { fixture.native.appStartEnd = DateTime.fromMillisecondsSinceEpoch(10); - fixture.binding.nativeAppStart = NativeAppStart(0, true); + fixture.binding.nativeAppStart = NativeAppStart( + appStartTime: 0, pluginRegistrationTime: 10, isColdStart: true); fixture.getNativeAppStartIntegration().call(fixture.hub, fixture.options); @@ -109,6 +115,108 @@ void main() { expect(appStartInfo?.end, DateTime.fromMillisecondsSinceEpoch(10)); }); }); + + group('App start spans', () { + late SentrySpan? coldStartSpan, + pluginRegistrationSpan, + mainIsolateSetupSpan, + firstFrameRenderSpan; + // ignore: invalid_use_of_internal_member + late SentryTracer tracer; + late Fixture fixture; + + setUp(() async { + TestWidgetsFlutterBinding.ensureInitialized(); + + fixture = Fixture(); + NativeAppStartIntegration.clearAppStartInfo(); + + fixture.native.appStartEnd = DateTime.fromMillisecondsSinceEpoch(50); + fixture.binding.nativeAppStart = NativeAppStart( + appStartTime: 0, pluginRegistrationTime: 10, isColdStart: true); + // dartLoadingEnd needs to be set after engine end (see MockNativeChannel) + SentryFlutter.mainIsolateStartTime = + DateTime.fromMillisecondsSinceEpoch(15); + + fixture.getNativeAppStartIntegration().call(fixture.hub, fixture.options); + + final processor = fixture.options.eventProcessors.first; + tracer = fixture.createTracer(); + final transaction = SentryTransaction(tracer); + final enriched = + await processor.apply(transaction, Hint()) as SentryTransaction; + + final appStartInfo = await NativeAppStartIntegration.getAppStartInfo(); + + coldStartSpan = enriched.spans.firstWhereOrNull((element) => + element.context.description == appStartInfo?.appStartTypeDescription); + pluginRegistrationSpan = enriched.spans.firstWhereOrNull((element) => + element.context.description == + appStartInfo?.pluginRegistrationDescription); + mainIsolateSetupSpan = enriched.spans.firstWhereOrNull((element) => + element.context.description == + appStartInfo?.mainIsolateSetupDescription); + firstFrameRenderSpan = enriched.spans.firstWhereOrNull((element) => + element.context.description == + appStartInfo?.firstFrameRenderDescription); + }); + + test('are added by event processor', () async { + expect(coldStartSpan, isNotNull); + expect(pluginRegistrationSpan, isNotNull); + expect(mainIsolateSetupSpan, isNotNull); + expect(firstFrameRenderSpan, isNotNull); + }); + + test('have correct op', () async { + const op = 'app.start.cold'; + expect(coldStartSpan?.context.operation, op); + expect(pluginRegistrationSpan?.context.operation, op); + expect(mainIsolateSetupSpan?.context.operation, op); + expect(firstFrameRenderSpan?.context.operation, op); + }); + + test('have correct parents', () async { + expect(coldStartSpan?.context.parentSpanId, tracer.context.spanId); + expect(pluginRegistrationSpan?.context.parentSpanId, + coldStartSpan?.context.spanId); + expect(mainIsolateSetupSpan?.context.parentSpanId, + coldStartSpan?.context.spanId); + expect(firstFrameRenderSpan?.context.parentSpanId, + coldStartSpan?.context.spanId); + }); + + test('have correct traceId', () async { + final traceId = tracer.context.traceId; + expect(coldStartSpan?.context.traceId, traceId); + expect(pluginRegistrationSpan?.context.traceId, traceId); + expect(mainIsolateSetupSpan?.context.traceId, traceId); + expect(firstFrameRenderSpan?.context.traceId, traceId); + }); + + test('have correct startTimestamp', () async { + final appStartTime = DateTime.fromMillisecondsSinceEpoch( + fixture.binding.nativeAppStart!.appStartTime.toInt()) + .toUtc(); + expect(coldStartSpan?.startTimestamp, appStartTime); + expect(pluginRegistrationSpan?.startTimestamp, appStartTime); + expect(mainIsolateSetupSpan?.startTimestamp, + pluginRegistrationSpan?.endTimestamp); + expect(firstFrameRenderSpan?.startTimestamp, + mainIsolateSetupSpan?.endTimestamp); + }); + + test('have correct endTimestamp', () async { + final engineReadyEndtime = DateTime.fromMillisecondsSinceEpoch( + fixture.binding.nativeAppStart!.pluginRegistrationTime.toInt()) + .toUtc(); + expect(coldStartSpan?.endTimestamp, fixture.native.appStartEnd?.toUtc()); + expect(pluginRegistrationSpan?.endTimestamp, engineReadyEndtime); + expect(mainIsolateSetupSpan?.endTimestamp, + SentryFlutter.mainIsolateStartTime.toUtc()); + expect(firstFrameRenderSpan?.endTimestamp, coldStartSpan?.endTimestamp); + }); + }); } class Fixture { diff --git a/flutter/test/navigation/sentry_display_widget_test.dart b/flutter/test/navigation/sentry_display_widget_test.dart index b9c2eb37cb..092dc0ab65 100644 --- a/flutter/test/navigation/sentry_display_widget_test.dart +++ b/flutter/test/navigation/sentry_display_widget_test.dart @@ -61,6 +61,8 @@ void main() { AppStartType.cold, start: getUtcDateTime().add(Duration(seconds: 1)), end: getUtcDateTime().add(Duration(seconds: 2)), + pluginRegistration: getUtcDateTime().add(Duration(seconds: 3)), + mainIsolateStart: getUtcDateTime().add(Duration(seconds: 4)), ); NativeAppStartIntegration.setAppStartInfo(appStartInfo); diff --git a/flutter/test/sentry_native_channel_test.dart b/flutter/test/sentry_native_channel_test.dart index 04ec723feb..4d5e539838 100644 --- a/flutter/test/sentry_native_channel_test.dart +++ b/flutter/test/sentry_native_channel_test.dart @@ -20,6 +20,7 @@ void main() { test('fetchNativeAppStart', () async { final map = { + 'pluginRegistrationTime': 1, 'appStartTime': 0.1, 'isColdStart': true, }; diff --git a/flutter/test/sentry_native_test.dart b/flutter/test/sentry_native_test.dart index 68dc16fdfa..341c8aaad8 100644 --- a/flutter/test/sentry_native_test.dart +++ b/flutter/test/sentry_native_test.dart @@ -16,7 +16,8 @@ void main() { }); test('fetchNativeAppStart sets didFetchAppStart', () async { - final nativeAppStart = NativeAppStart(0.0, true); + final nativeAppStart = NativeAppStart( + appStartTime: 0.0, pluginRegistrationTime: 10, isColdStart: true); channel.nativeAppStart = nativeAppStart; expect(sut.didFetchAppStart, false); diff --git a/flutter/test/sentry_navigator_observer_test.dart b/flutter/test/sentry_navigator_observer_test.dart index 1b41833e20..94ce9e6107 100644 --- a/flutter/test/sentry_navigator_observer_test.dart +++ b/flutter/test/sentry_navigator_observer_test.dart @@ -501,6 +501,8 @@ void main() { AppStartType.cold, start: DateTime.now().add(const Duration(seconds: 1)), end: DateTime.now().add(const Duration(seconds: 2)), + pluginRegistration: DateTime.now().add(const Duration(seconds: 3)), + mainIsolateStart: DateTime.now().add(const Duration(seconds: 4)), ), ); From 6fedcab9f494397bd4e1d450b5423f074c63fd82 Mon Sep 17 00:00:00 2001 From: Ivan Dlugos <6349682+vaind@users.noreply.github.com> Date: Mon, 6 May 2024 16:06:02 +0200 Subject: [PATCH 164/237] ci: fix expected iOS binary size (#2035) --- metrics/metrics-ios.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/metrics/metrics-ios.yml b/metrics/metrics-ios.yml index e4263a6560..57177c0899 100644 --- a/metrics/metrics-ios.yml +++ b/metrics/metrics-ios.yml @@ -11,4 +11,4 @@ startupTimeTest: binarySizeTest: diffMin: 900 KiB - diffMax: 1200 KiB + diffMax: 1300 KiB From c9784770c2d501233c3643f98ae182e51f08f6c2 Mon Sep 17 00:00:00 2001 From: Ivan Dlugos <6349682+vaind@users.noreply.github.com> Date: Mon, 6 May 2024 17:06:43 +0200 Subject: [PATCH 165/237] refactor: move native SDK init and close to SentryNativeBinding (#2030) * refactor: move native SDK init and close to SentryNativeBinding * fixup * rename test file * test files cleanup --- .../integrations/native_sdk_integration.dart | 71 ++---- flutter/lib/src/native/factory_real.dart | 3 + flutter/lib/src/native/factory_web.dart | 2 +- .../src/native/java/sentry_native_java.dart | 10 + flutter/lib/src/native/sentry_native.dart | 5 + .../lib/src/native/sentry_native_binding.dart | 3 + .../lib/src/native/sentry_native_channel.dart | 43 ++++ flutter/lib/src/sentry_flutter.dart | 4 +- .../init_native_sdk_integration_test.dart | 210 ------------------ .../integrations/init_native_sdk_test.dart | 182 +++++++++++++++ .../native_sdk_integration_test.dart | 128 +++++------ flutter/test/mocks.dart | 30 +++ 12 files changed, 362 insertions(+), 329 deletions(-) create mode 100644 flutter/lib/src/native/java/sentry_native_java.dart delete mode 100644 flutter/test/integrations/init_native_sdk_integration_test.dart create mode 100644 flutter/test/integrations/init_native_sdk_test.dart diff --git a/flutter/lib/src/integrations/native_sdk_integration.dart b/flutter/lib/src/integrations/native_sdk_integration.dart index 715a821cf9..35181afc1e 100644 --- a/flutter/lib/src/integrations/native_sdk_integration.dart +++ b/flutter/lib/src/integrations/native_sdk_integration.dart @@ -1,61 +1,26 @@ import 'dart:async'; -import 'package:flutter/services.dart'; import 'package:sentry/sentry.dart'; +import '../native/sentry_native.dart'; import '../sentry_flutter_options.dart'; /// Enables Sentry's native SDKs (Android and iOS) with options. class NativeSdkIntegration implements Integration { - NativeSdkIntegration(this._channel); + NativeSdkIntegration(this._native); - final MethodChannel _channel; SentryFlutterOptions? _options; + final SentryNative _native; @override Future call(Hub hub, SentryFlutterOptions options) async { _options = options; + if (!options.autoInitializeNativeSdk) { return; } - try { - await _channel.invokeMethod('initNativeSdk', { - 'dsn': options.dsn, - 'debug': options.debug, - 'environment': options.environment, - 'release': options.release, - 'enableAutoSessionTracking': options.enableAutoSessionTracking, - 'enableNativeCrashHandling': options.enableNativeCrashHandling, - 'attachStacktrace': options.attachStacktrace, - 'attachThreads': options.attachThreads, - 'autoSessionTrackingIntervalMillis': - options.autoSessionTrackingInterval.inMilliseconds, - 'dist': options.dist, - 'integrations': options.sdk.integrations, - 'packages': - options.sdk.packages.map((e) => e.toJson()).toList(growable: false), - 'diagnosticLevel': options.diagnosticLevel.name, - 'maxBreadcrumbs': options.maxBreadcrumbs, - 'anrEnabled': options.anrEnabled, - 'anrTimeoutIntervalMillis': options.anrTimeoutInterval.inMilliseconds, - 'enableAutoNativeBreadcrumbs': options.enableAutoNativeBreadcrumbs, - 'maxCacheItems': options.maxCacheItems, - 'sendDefaultPii': options.sendDefaultPii, - 'enableWatchdogTerminationTracking': - options.enableWatchdogTerminationTracking, - 'enableNdkScopeSync': options.enableNdkScopeSync, - 'enableAutoPerformanceTracing': options.enableAutoPerformanceTracing, - 'sendClientReports': options.sendClientReports, - 'proguardUuid': options.proguardUuid, - 'maxAttachmentSize': options.maxAttachmentSize, - 'recordHttpBreadcrumbs': options.recordHttpBreadcrumbs, - 'captureFailedRequests': options.captureFailedRequests, - 'enableAppHangTracking': options.enableAppHangTracking, - 'connectionTimeoutMillis': options.connectionTimeout.inMilliseconds, - 'readTimeoutMillis': options.readTimeout.inMilliseconds, - 'appHangTimeoutIntervalMillis': - options.appHangTimeoutInterval.inMilliseconds, - }); + try { + await _native.init(options); options.sdk.addIntegration('nativeSdkIntegration'); } catch (exception, stackTrace) { options.logger( @@ -69,19 +34,17 @@ class NativeSdkIntegration implements Integration { @override Future close() async { - final options = _options; - if (options != null && !options.autoInitializeNativeSdk) { - return; - } - try { - await _channel.invokeMethod('closeNativeSdk'); - } catch (exception, stackTrace) { - _options?.logger( - SentryLevel.fatal, - 'nativeSdkIntegration failed to be closed', - exception: exception, - stackTrace: stackTrace, - ); + if (_options?.autoInitializeNativeSdk == true) { + try { + await _native.close(); + } catch (exception, stackTrace) { + _options?.logger( + SentryLevel.fatal, + 'nativeSdkIntegration failed to be closed', + exception: exception, + stackTrace: stackTrace, + ); + } } } } diff --git a/flutter/lib/src/native/factory_real.dart b/flutter/lib/src/native/factory_real.dart index 3c918b7be7..d5ee4f5cca 100644 --- a/flutter/lib/src/native/factory_real.dart +++ b/flutter/lib/src/native/factory_real.dart @@ -2,12 +2,15 @@ import 'package:flutter/services.dart'; import '../../sentry_flutter.dart'; import 'cocoa/sentry_native_cocoa.dart'; +import 'java/sentry_native_java.dart'; import 'sentry_native_binding.dart'; import 'sentry_native_channel.dart'; SentryNativeBinding createBinding(PlatformChecker pc, MethodChannel channel) { if (pc.platform.isIOS || pc.platform.isMacOS) { return SentryNativeCocoa(channel); + } else if (pc.platform.isAndroid) { + return SentryNativeJava(channel); } else { return SentryNativeChannel(channel); } diff --git a/flutter/lib/src/native/factory_web.dart b/flutter/lib/src/native/factory_web.dart index 8038ea9780..c2cd57ada7 100644 --- a/flutter/lib/src/native/factory_web.dart +++ b/flutter/lib/src/native/factory_web.dart @@ -4,6 +4,6 @@ import '../../sentry_flutter.dart'; import 'sentry_native_binding.dart'; // This isn't actually called, see SentryFlutter.init() -SentryNativeBinding createBinding(PlatformChecker pc, MethodChannel channel) { +SentryNativeBinding createBinding(PlatformChecker _, MethodChannel __) { throw UnsupportedError("Native binding is not supported on this platform."); } diff --git a/flutter/lib/src/native/java/sentry_native_java.dart b/flutter/lib/src/native/java/sentry_native_java.dart new file mode 100644 index 0000000000..20774e11fa --- /dev/null +++ b/flutter/lib/src/native/java/sentry_native_java.dart @@ -0,0 +1,10 @@ +import 'package:meta/meta.dart'; + +import '../sentry_native_channel.dart'; + +// Note: currently this doesn't do anything. Later, it shall be used with +// generated JNI bindings. See https://github.com/getsentry/sentry-dart/issues/1444 +@internal +class SentryNativeJava extends SentryNativeChannel { + SentryNativeJava(super.channel); +} diff --git a/flutter/lib/src/native/sentry_native.dart b/flutter/lib/src/native/sentry_native.dart index 4d26239a60..893c55d6bc 100644 --- a/flutter/lib/src/native/sentry_native.dart +++ b/flutter/lib/src/native/sentry_native.dart @@ -30,6 +30,11 @@ class SentryNative { /// Flag indicating if app start measurement was added to the first transaction. bool didAddAppStartMeasurement = false; + Future init(SentryFlutterOptions options) async => + _invoke("init", () => _binding.init(options)); + + Future close() async => _invoke("close", _binding.close); + /// Fetch [NativeAppStart] from native channels. Can only be called once. Future fetchNativeAppStart() async { _didFetchAppStart = true; diff --git a/flutter/lib/src/native/sentry_native_binding.dart b/flutter/lib/src/native/sentry_native_binding.dart index 54d335d529..950e7f9994 100644 --- a/flutter/lib/src/native/sentry_native_binding.dart +++ b/flutter/lib/src/native/sentry_native_binding.dart @@ -9,6 +9,9 @@ import 'sentry_native.dart'; @internal abstract class SentryNativeBinding { // TODO Move other native calls here. + Future init(SentryFlutterOptions options); + + Future close(); Future fetchNativeAppStart(); diff --git a/flutter/lib/src/native/sentry_native_channel.dart b/flutter/lib/src/native/sentry_native_channel.dart index 4bf9745cb3..61b361de30 100644 --- a/flutter/lib/src/native/sentry_native_channel.dart +++ b/flutter/lib/src/native/sentry_native_channel.dart @@ -17,6 +17,49 @@ class SentryNativeChannel implements SentryNativeBinding { // TODO Move other native calls here. + @override + Future init(SentryFlutterOptions options) async => + _channel.invokeMethod('initNativeSdk', { + 'dsn': options.dsn, + 'debug': options.debug, + 'environment': options.environment, + 'release': options.release, + 'enableAutoSessionTracking': options.enableAutoSessionTracking, + 'enableNativeCrashHandling': options.enableNativeCrashHandling, + 'attachStacktrace': options.attachStacktrace, + 'attachThreads': options.attachThreads, + 'autoSessionTrackingIntervalMillis': + options.autoSessionTrackingInterval.inMilliseconds, + 'dist': options.dist, + 'integrations': options.sdk.integrations, + 'packages': + options.sdk.packages.map((e) => e.toJson()).toList(growable: false), + 'diagnosticLevel': options.diagnosticLevel.name, + 'maxBreadcrumbs': options.maxBreadcrumbs, + 'anrEnabled': options.anrEnabled, + 'anrTimeoutIntervalMillis': options.anrTimeoutInterval.inMilliseconds, + 'enableAutoNativeBreadcrumbs': options.enableAutoNativeBreadcrumbs, + 'maxCacheItems': options.maxCacheItems, + 'sendDefaultPii': options.sendDefaultPii, + 'enableWatchdogTerminationTracking': + options.enableWatchdogTerminationTracking, + 'enableNdkScopeSync': options.enableNdkScopeSync, + 'enableAutoPerformanceTracing': options.enableAutoPerformanceTracing, + 'sendClientReports': options.sendClientReports, + 'proguardUuid': options.proguardUuid, + 'maxAttachmentSize': options.maxAttachmentSize, + 'recordHttpBreadcrumbs': options.recordHttpBreadcrumbs, + 'captureFailedRequests': options.captureFailedRequests, + 'enableAppHangTracking': options.enableAppHangTracking, + 'connectionTimeoutMillis': options.connectionTimeout.inMilliseconds, + 'readTimeoutMillis': options.readTimeout.inMilliseconds, + 'appHangTimeoutIntervalMillis': + options.appHangTimeoutInterval.inMilliseconds, + }); + + @override + Future close() async => _channel.invokeMethod('closeNativeSdk'); + @override Future fetchNativeAppStart() async { final json = diff --git a/flutter/lib/src/sentry_flutter.dart b/flutter/lib/src/sentry_flutter.dart index 60c9811bf0..9b0792c7e3 100644 --- a/flutter/lib/src/sentry_flutter.dart +++ b/flutter/lib/src/sentry_flutter.dart @@ -158,8 +158,8 @@ mixin SentryFlutter { // The ordering here matters, as we'd like to first start the native integration. // That allow us to send events to the network and then the Flutter integrations. // Flutter Web doesn't need that, only Android and iOS. - if (platformChecker.hasNativeIntegration) { - integrations.add(NativeSdkIntegration(channel)); + if (_native != null) { + integrations.add(NativeSdkIntegration(_native!)); } // Will enrich events with device context, native packages and integrations diff --git a/flutter/test/integrations/init_native_sdk_integration_test.dart b/flutter/test/integrations/init_native_sdk_integration_test.dart deleted file mode 100644 index b41c2d51cf..0000000000 --- a/flutter/test/integrations/init_native_sdk_integration_test.dart +++ /dev/null @@ -1,210 +0,0 @@ -@TestOn('vm') - -import 'package:flutter/services.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:sentry_flutter/sentry_flutter.dart'; -import 'package:sentry_flutter/src/integrations/native_sdk_integration.dart'; -import 'package:sentry_flutter/src/version.dart'; - -import '../mocks.dart'; - -void main() { - group(NativeSdkIntegration, () { - late Fixture fixture; - setUp(() { - fixture = Fixture(); - TestWidgetsFlutterBinding.ensureInitialized(); - }); - - test('test default values', () async { - String? methodName; - dynamic arguments; - final channel = createChannelWithCallback((call) async { - methodName = call.method; - arguments = call.arguments; - }); - var sut = fixture.getSut(channel); - - await sut.call(HubAdapter(), createOptions()); - - channel.setMethodCallHandler(null); - - expect(methodName, 'initNativeSdk'); - expect(arguments, { - 'dsn': fakeDsn, - 'debug': false, - 'environment': null, - 'release': null, - 'enableAutoSessionTracking': true, - 'enableNativeCrashHandling': true, - 'attachStacktrace': true, - 'attachThreads': false, - 'autoSessionTrackingIntervalMillis': 30000, - 'dist': null, - 'integrations': [], - 'packages': [ - {'name': 'pub:sentry_flutter', 'version': sdkVersion} - ], - 'diagnosticLevel': 'debug', - 'maxBreadcrumbs': 100, - 'anrEnabled': false, - 'anrTimeoutIntervalMillis': 5000, - 'enableAutoNativeBreadcrumbs': true, - 'maxCacheItems': 30, - 'sendDefaultPii': false, - 'enableWatchdogTerminationTracking': true, - 'enableNdkScopeSync': true, - 'enableAutoPerformanceTracing': true, - 'sendClientReports': true, - 'proguardUuid': null, - 'maxAttachmentSize': 20 * 1024 * 1024, - 'recordHttpBreadcrumbs': true, - 'captureFailedRequests': true, - 'enableAppHangTracking': true, - 'connectionTimeoutMillis': 5000, - 'readTimeoutMillis': 5000, - 'appHangTimeoutIntervalMillis': 2000, - }); - }); - - test('test custom values', () async { - String? methodName; - dynamic arguments; - final channel = createChannelWithCallback((call) async { - methodName = call.method; - arguments = call.arguments; - }); - var sut = fixture.getSut(channel); - - final options = createOptions() - ..debug = false - ..environment = 'foo' - ..release = 'foo@bar+1' - ..enableAutoSessionTracking = false - ..enableNativeCrashHandling = false - ..attachStacktrace = false - ..attachThreads = true - ..autoSessionTrackingInterval = Duration(milliseconds: 240000) - ..dist = 'distfoo' - ..diagnosticLevel = SentryLevel.error - ..maxBreadcrumbs = 0 - ..anrEnabled = false - ..anrTimeoutInterval = Duration(seconds: 1) - ..enableAutoNativeBreadcrumbs = false - ..maxCacheItems = 0 - ..sendDefaultPii = true - ..enableWatchdogTerminationTracking = false - ..enableAutoPerformanceTracing = false - ..sendClientReports = false - ..enableNdkScopeSync = true - ..proguardUuid = fakeProguardUuid - ..maxAttachmentSize = 10 - ..recordHttpBreadcrumbs = false - ..captureFailedRequests = false - ..enableAppHangTracking = false - ..connectionTimeout = Duration(milliseconds: 9001) - ..readTimeout = Duration(milliseconds: 9002) - ..appHangTimeoutInterval = Duration(milliseconds: 9003); - - options.sdk.addIntegration('foo'); - options.sdk.addPackage('bar', '1'); - - await sut.call(HubAdapter(), options); - - channel.setMethodCallHandler(null); - - expect(methodName, 'initNativeSdk'); - expect(arguments, { - 'dsn': fakeDsn, - 'debug': false, - 'environment': 'foo', - 'release': 'foo@bar+1', - 'enableAutoSessionTracking': false, - 'enableNativeCrashHandling': false, - 'attachStacktrace': false, - 'attachThreads': true, - 'autoSessionTrackingIntervalMillis': 240000, - 'dist': 'distfoo', - 'integrations': ['foo'], - 'packages': [ - {'name': 'pub:sentry_flutter', 'version': sdkVersion}, - {'name': 'bar', 'version': '1'}, - ], - 'diagnosticLevel': 'error', - 'maxBreadcrumbs': 0, - 'anrEnabled': false, - 'anrTimeoutIntervalMillis': 1000, - 'enableAutoNativeBreadcrumbs': false, - 'maxCacheItems': 0, - 'sendDefaultPii': true, - 'enableWatchdogTerminationTracking': false, - 'enableNdkScopeSync': true, - 'enableAutoPerformanceTracing': false, - 'sendClientReports': false, - 'proguardUuid': fakeProguardUuid, - 'maxAttachmentSize': 10, - 'recordHttpBreadcrumbs': false, - 'captureFailedRequests': false, - 'enableAppHangTracking': false, - 'connectionTimeoutMillis': 9001, - 'readTimeoutMillis': 9002, - 'appHangTimeoutIntervalMillis': 9003, - }); - }); - - test('adds integration', () async { - final channel = createChannelWithCallback((call) async {}); - var sut = fixture.getSut(channel); - - final options = createOptions(); - await sut.call(HubAdapter(), options); - - expect(options.sdk.integrations, ['nativeSdkIntegration']); - - channel.setMethodCallHandler(null); - }); - - test('integration is not added in case of an exception', () async { - final channel = createChannelWithCallback((call) async { - throw Exception('foo'); - }); - var sut = fixture.getSut(channel); - - final options = createOptions(); - await sut.call(NoOpHub(), options); - - expect(options.sdk.integrations, []); - - channel.setMethodCallHandler(null); - }); - }); -} - -MethodChannel createChannelWithCallback( - Future? Function(MethodCall call)? handler, -) { - final channel = MethodChannel('initNativeSdk'); - // ignore: deprecated_member_use - channel.setMockMethodCallHandler(handler); - return channel; -} - -SentryFlutterOptions createOptions() { - final mockPlatformChecker = MockPlatformChecker(hasNativeIntegration: true); - final options = SentryFlutterOptions( - dsn: fakeDsn, - checker: mockPlatformChecker, - ); - options.sdk = SdkVersion( - name: sdkName, - version: sdkVersion, - ); - options.sdk.addPackage('pub:sentry_flutter', sdkVersion); - return options; -} - -class Fixture { - NativeSdkIntegration getSut(MethodChannel channel) { - return NativeSdkIntegration(channel); - } -} diff --git a/flutter/test/integrations/init_native_sdk_test.dart b/flutter/test/integrations/init_native_sdk_test.dart new file mode 100644 index 0000000000..fa3b76f153 --- /dev/null +++ b/flutter/test/integrations/init_native_sdk_test.dart @@ -0,0 +1,182 @@ +@TestOn('vm') + +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:sentry_flutter/sentry_flutter.dart'; +import 'package:sentry_flutter/src/native/sentry_native_channel.dart'; +import 'package:sentry_flutter/src/version.dart'; + +import '../mocks.dart'; + +void main() { + late Fixture fixture; + setUp(() { + fixture = Fixture(); + TestWidgetsFlutterBinding.ensureInitialized(); + }); + + test('test default values', () async { + String? methodName; + dynamic arguments; + final channel = createChannelWithCallback((call) async { + methodName = call.method; + arguments = call.arguments; + }); + var sut = fixture.getSut(channel); + + await sut.init(createOptions()); + + channel.setMethodCallHandler(null); + + expect(methodName, 'initNativeSdk'); + expect(arguments, { + 'dsn': fakeDsn, + 'debug': false, + 'environment': null, + 'release': null, + 'enableAutoSessionTracking': true, + 'enableNativeCrashHandling': true, + 'attachStacktrace': true, + 'attachThreads': false, + 'autoSessionTrackingIntervalMillis': 30000, + 'dist': null, + 'integrations': [], + 'packages': [ + {'name': 'pub:sentry_flutter', 'version': sdkVersion} + ], + 'diagnosticLevel': 'debug', + 'maxBreadcrumbs': 100, + 'anrEnabled': false, + 'anrTimeoutIntervalMillis': 5000, + 'enableAutoNativeBreadcrumbs': true, + 'maxCacheItems': 30, + 'sendDefaultPii': false, + 'enableWatchdogTerminationTracking': true, + 'enableNdkScopeSync': true, + 'enableAutoPerformanceTracing': true, + 'sendClientReports': true, + 'proguardUuid': null, + 'maxAttachmentSize': 20 * 1024 * 1024, + 'recordHttpBreadcrumbs': true, + 'captureFailedRequests': true, + 'enableAppHangTracking': true, + 'connectionTimeoutMillis': 5000, + 'readTimeoutMillis': 5000, + 'appHangTimeoutIntervalMillis': 2000, + }); + }); + + test('test custom values', () async { + String? methodName; + dynamic arguments; + final channel = createChannelWithCallback((call) async { + methodName = call.method; + arguments = call.arguments; + }); + var sut = fixture.getSut(channel); + + final options = createOptions() + ..debug = false + ..environment = 'foo' + ..release = 'foo@bar+1' + ..enableAutoSessionTracking = false + ..enableNativeCrashHandling = false + ..attachStacktrace = false + ..attachThreads = true + ..autoSessionTrackingInterval = Duration(milliseconds: 240000) + ..dist = 'distfoo' + ..diagnosticLevel = SentryLevel.error + ..maxBreadcrumbs = 0 + ..anrEnabled = false + ..anrTimeoutInterval = Duration(seconds: 1) + ..enableAutoNativeBreadcrumbs = false + ..maxCacheItems = 0 + ..sendDefaultPii = true + ..enableWatchdogTerminationTracking = false + ..enableAutoPerformanceTracing = false + ..sendClientReports = false + ..enableNdkScopeSync = true + ..proguardUuid = fakeProguardUuid + ..maxAttachmentSize = 10 + ..recordHttpBreadcrumbs = false + ..captureFailedRequests = false + ..enableAppHangTracking = false + ..connectionTimeout = Duration(milliseconds: 9001) + ..readTimeout = Duration(milliseconds: 9002) + ..appHangTimeoutInterval = Duration(milliseconds: 9003); + + options.sdk.addIntegration('foo'); + options.sdk.addPackage('bar', '1'); + + await sut.init(options); + + channel.setMethodCallHandler(null); + + expect(methodName, 'initNativeSdk'); + expect(arguments, { + 'dsn': fakeDsn, + 'debug': false, + 'environment': 'foo', + 'release': 'foo@bar+1', + 'enableAutoSessionTracking': false, + 'enableNativeCrashHandling': false, + 'attachStacktrace': false, + 'attachThreads': true, + 'autoSessionTrackingIntervalMillis': 240000, + 'dist': 'distfoo', + 'integrations': ['foo'], + 'packages': [ + {'name': 'pub:sentry_flutter', 'version': sdkVersion}, + {'name': 'bar', 'version': '1'}, + ], + 'diagnosticLevel': 'error', + 'maxBreadcrumbs': 0, + 'anrEnabled': false, + 'anrTimeoutIntervalMillis': 1000, + 'enableAutoNativeBreadcrumbs': false, + 'maxCacheItems': 0, + 'sendDefaultPii': true, + 'enableWatchdogTerminationTracking': false, + 'enableNdkScopeSync': true, + 'enableAutoPerformanceTracing': false, + 'sendClientReports': false, + 'proguardUuid': fakeProguardUuid, + 'maxAttachmentSize': 10, + 'recordHttpBreadcrumbs': false, + 'captureFailedRequests': false, + 'enableAppHangTracking': false, + 'connectionTimeoutMillis': 9001, + 'readTimeoutMillis': 9002, + 'appHangTimeoutIntervalMillis': 9003, + }); + }); +} + +MethodChannel createChannelWithCallback( + Future? Function(MethodCall call)? handler, +) { + final channel = MethodChannel('initNativeSdk'); + // ignore: deprecated_member_use + channel.setMockMethodCallHandler(handler); + return channel; +} + +SentryFlutterOptions createOptions() { + final mockPlatformChecker = MockPlatformChecker(hasNativeIntegration: true); + final options = SentryFlutterOptions( + dsn: fakeDsn, + checker: mockPlatformChecker, + ); + options.sdk = SdkVersion( + name: sdkName, + version: sdkVersion, + ); + options.sdk.addPackage('pub:sentry_flutter', sdkVersion); + return options; +} + +class Fixture { + SentryNativeChannel getSut(MethodChannel native) { + return SentryNativeChannel(native); + } +} diff --git a/flutter/test/integrations/native_sdk_integration_test.dart b/flutter/test/integrations/native_sdk_integration_test.dart index e48a22933a..b67eccbe0e 100644 --- a/flutter/test/integrations/native_sdk_integration_test.dart +++ b/flutter/test/integrations/native_sdk_integration_test.dart @@ -9,93 +9,90 @@ import '../mocks.dart'; import '../mocks.mocks.dart'; void main() { - const _channel = MethodChannel('sentry_flutter'); + group(NativeSdkIntegration, () { + const _channel = MethodChannel('sentry_flutter'); - TestWidgetsFlutterBinding.ensureInitialized(); + TestWidgetsFlutterBinding.ensureInitialized(); - late Fixture fixture; + late Fixture fixture; - setUp(() { - fixture = Fixture(); - }); + setUp(() { + fixture = Fixture(); + }); - tearDown(() { - // ignore: deprecated_member_use - _channel.setMockMethodCallHandler(null); - }); + tearDown(() { + // ignore: deprecated_member_use + _channel.setMockMethodCallHandler(null); + }); + + test('adds integration', () async { + // ignore: deprecated_member_use + _channel.setMockMethodCallHandler((MethodCall methodCall) async {}); + final mock = TestMockSentryNative(); + final integration = NativeSdkIntegration(mock); - test('nativeSdkIntegration adds integration', () async { - // ignore: deprecated_member_use - _channel.setMockMethodCallHandler((MethodCall methodCall) async {}); + await integration(fixture.hub, fixture.options); - final integration = NativeSdkIntegration(_channel); + expect( + fixture.options.sdk.integrations, contains('nativeSdkIntegration')); + expect(mock.numberOfInitCalls, 1); + }); - await integration(fixture.hub, fixture.options); + test('do not throw', () async { + final integration = NativeSdkIntegration(_ThrowingMockSentryNative()); - expect(fixture.options.sdk.integrations.contains('nativeSdkIntegration'), - true); - }); + await integration(fixture.hub, fixture.options); - test('nativeSdkIntegration do not throw', () async { - // ignore: deprecated_member_use - _channel.setMockMethodCallHandler((MethodCall methodCall) async { - throw Exception(); + expect(fixture.options.sdk.integrations.contains('nativeSdkIntegration'), + false); }); - final integration = NativeSdkIntegration(_channel); + test('closes native SDK', () async { + final mock = TestMockSentryNative(); + final integration = NativeSdkIntegration(mock); - await integration(fixture.hub, fixture.options); + await integration.call(fixture.hub, fixture.options); + await integration.close(); - expect(fixture.options.sdk.integrations.contains('nativeSdkIntegration'), - false); - }); - - test('nativeSdkIntegration closes native SDK', () async { - var closeCalled = false; - // ignore: deprecated_member_use - _channel.setMockMethodCallHandler((MethodCall methodCall) async { - expect(methodCall.method, 'closeNativeSdk'); - closeCalled = true; + expect(mock.numberOfCloseCalls, 1); }); - final integration = NativeSdkIntegration(_channel); + test('does not call native sdk when auto init disabled', () async { + final mock = TestMockSentryNative(); + final integration = NativeSdkIntegration(mock); + fixture.options.autoInitializeNativeSdk = false; - await integration.close(); + await integration.call(fixture.hub, fixture.options); - expect(closeCalled, true); - }); - - test('nativeSdkIntegration does not call native sdk when auto init disabled', - () async { - var methodChannelCalled = false; - // ignore: deprecated_member_use - _channel.setMockMethodCallHandler((MethodCall methodCall) async { - methodChannelCalled = true; + expect(mock.numberOfInitCalls, 0); }); - fixture.options.autoInitializeNativeSdk = false; - - final integration = NativeSdkIntegration(_channel); - await integration.call(fixture.hub, fixture.options); + test('does not close native when auto init disabled', () async { + final mock = TestMockSentryNative(); + final integration = NativeSdkIntegration(mock); + fixture.options.autoInitializeNativeSdk = false; - expect(methodChannelCalled, false); - }); + await integration(fixture.hub, fixture.options); + await integration.close(); - test('nativeSdkIntegration does not close native when auto init disabled', - () async { - var methodChannelCalled = false; - // ignore: deprecated_member_use - _channel.setMockMethodCallHandler((MethodCall methodCall) async { - methodChannelCalled = true; + expect(mock.numberOfCloseCalls, 0); }); - fixture.options.autoInitializeNativeSdk = false; - final integration = NativeSdkIntegration(_channel); + test('adds integration', () async { + final mock = TestMockSentryNative(); + final integration = NativeSdkIntegration(mock); - await integration(fixture.hub, fixture.options); - await integration.close(); + await integration.call(fixture.hub, fixture.options); + + expect(fixture.options.sdk.integrations, ['nativeSdkIntegration']); + }); - expect(methodChannelCalled, false); + test(' is not added in case of an exception', () async { + final integration = NativeSdkIntegration(_ThrowingMockSentryNative()); + + await integration.call(fixture.hub, fixture.options); + expect(fixture.options.sdk.integrations, []); + }); }); } @@ -103,3 +100,10 @@ class Fixture { final hub = MockHub(); final options = SentryFlutterOptions(dsn: fakeDsn); } + +class _ThrowingMockSentryNative extends TestMockSentryNative { + @override + Future init(SentryFlutterOptions options) async { + throw Exception(); + } +} diff --git a/flutter/test/mocks.dart b/flutter/test/mocks.dart index 0520a09884..a373ee7511 100644 --- a/flutter/test/mocks.dart +++ b/flutter/test/mocks.dart @@ -199,6 +199,9 @@ class TestMockSentryNative implements SentryNative { var numberOfStartProfilerCalls = 0; var numberOfDiscardProfilerCalls = 0; var numberOfCollectProfileCalls = 0; + var numberOfInitCalls = 0; + SentryFlutterOptions? initOptions; + var numberOfCloseCalls = 0; @override Future addBreadcrumb(Breadcrumb breadcrumb) async { @@ -294,6 +297,19 @@ class TestMockSentryNative implements SentryNative { numberOfDiscardProfilerCalls++; return Future.value(null); } + + @override + Future init(SentryFlutterOptions options) { + numberOfInitCalls++; + initOptions = options; + return Future.value(null); + } + + @override + Future close() { + numberOfCloseCalls++; + return Future.value(null); + } } // TODO can this be replaced with https://pub.dev/packages/mockito#verifying-exact-number-of-invocations--at-least-x--never @@ -316,6 +332,8 @@ class MockNativeChannel implements SentryNativeBinding { int numberOfStartProfilerCalls = 0; int numberOfDiscardProfilerCalls = 0; int numberOfCollectProfileCalls = 0; + int numberOfInitCalls = 0; + int numberOfCloseCalls = 0; @override Future fetchNativeAppStart() async => nativeAppStart; @@ -395,6 +413,18 @@ class MockNativeChannel implements SentryNativeBinding { numberOfDiscardProfilerCalls++; return Future.value(null); } + + @override + Future init(SentryFlutterOptions options) { + numberOfInitCalls++; + return Future.value(null); + } + + @override + Future close() { + numberOfCloseCalls++; + return Future.value(null); + } } class MockRendererWrapper implements RendererWrapper { From dd5c515b868d70851201f9b56e46ded2a46a7f60 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 May 2024 17:11:08 +0200 Subject: [PATCH 166/237] build(deps): bump codecov/codecov-action from 4.3.0 to 4.3.1 (#2036) Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 4.3.0 to 4.3.1. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/84508663e988701840491b86de86b666e8a86bed...5ecb98a3c6b747ed38dc09f787459979aebb39be) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/dart.yml | 2 +- .github/workflows/dio.yml | 2 +- .github/workflows/drift.yml | 2 +- .github/workflows/file.yml | 2 +- .github/workflows/flutter.yml | 2 +- .github/workflows/hive.yml | 2 +- .github/workflows/isar.yml | 2 +- .github/workflows/logging.yml | 2 +- .github/workflows/sqflite.yml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml index b855465c8e..09365adcfe 100644 --- a/.github/workflows/dart.yml +++ b/.github/workflows/dart.yml @@ -68,7 +68,7 @@ jobs: dart pub get webdev build - - uses: codecov/codecov-action@84508663e988701840491b86de86b666e8a86bed # pin@v3 + - uses: codecov/codecov-action@5ecb98a3c6b747ed38dc09f787459979aebb39be # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: name: sentry diff --git a/.github/workflows/dio.yml b/.github/workflows/dio.yml index e6183d6695..e441deffea 100644 --- a/.github/workflows/dio.yml +++ b/.github/workflows/dio.yml @@ -52,7 +52,7 @@ jobs: dart test -p vm --coverage=coverage --test-randomize-ordering-seed=random --chain-stack-traces dart pub run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.dart_tool/package_config.json --report-on=lib - - uses: codecov/codecov-action@84508663e988701840491b86de86b666e8a86bed # pin@v3 + - uses: codecov/codecov-action@5ecb98a3c6b747ed38dc09f787459979aebb39be # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: name: sentry_dio diff --git a/.github/workflows/drift.yml b/.github/workflows/drift.yml index 7179c7b99f..198806fbf1 100644 --- a/.github/workflows/drift.yml +++ b/.github/workflows/drift.yml @@ -93,7 +93,7 @@ jobs: cd drift flutter test --coverage --test-randomize-ordering-seed=random - - uses: codecov/codecov-action@84508663e988701840491b86de86b666e8a86bed # pin@v3 + - uses: codecov/codecov-action@5ecb98a3c6b747ed38dc09f787459979aebb39be # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' with: name: sentry_drift diff --git a/.github/workflows/file.yml b/.github/workflows/file.yml index 1f2a94417e..d59b127a9d 100644 --- a/.github/workflows/file.yml +++ b/.github/workflows/file.yml @@ -52,7 +52,7 @@ jobs: dart test -p vm --coverage=coverage --test-randomize-ordering-seed=random --chain-stack-traces dart pub run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.dart_tool/package_config.json --report-on=lib - - uses: codecov/codecov-action@84508663e988701840491b86de86b666e8a86bed # pin@v3 + - uses: codecov/codecov-action@5ecb98a3c6b747ed38dc09f787459979aebb39be # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: name: sentry_file diff --git a/.github/workflows/flutter.yml b/.github/workflows/flutter.yml index 5c17ccb4b7..afca6d9aac 100644 --- a/.github/workflows/flutter.yml +++ b/.github/workflows/flutter.yml @@ -106,7 +106,7 @@ jobs: flutter test --coverage --test-randomize-ordering-seed=random dart run remove_from_coverage -f coverage/lcov.info -r 'binding.dart' - - uses: codecov/codecov-action@84508663e988701840491b86de86b666e8a86bed # pin@v3 + - uses: codecov/codecov-action@5ecb98a3c6b747ed38dc09f787459979aebb39be # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' with: name: sentry_flutter diff --git a/.github/workflows/hive.yml b/.github/workflows/hive.yml index 4f861c4f6f..dcc483df81 100644 --- a/.github/workflows/hive.yml +++ b/.github/workflows/hive.yml @@ -51,7 +51,7 @@ jobs: dart test -p vm --coverage=coverage --test-randomize-ordering-seed=random --chain-stack-traces dart pub run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.dart_tool/package_config.json --report-on=lib - - uses: codecov/codecov-action@84508663e988701840491b86de86b666e8a86bed # pin@v3 + - uses: codecov/codecov-action@5ecb98a3c6b747ed38dc09f787459979aebb39be # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: name: sentry_hive diff --git a/.github/workflows/isar.yml b/.github/workflows/isar.yml index d2882f0615..d2ba1d37e7 100644 --- a/.github/workflows/isar.yml +++ b/.github/workflows/isar.yml @@ -93,7 +93,7 @@ jobs: cd isar flutter test -j 1 --coverage --test-randomize-ordering-seed=random - - uses: codecov/codecov-action@84508663e988701840491b86de86b666e8a86bed # pin@v3 + - uses: codecov/codecov-action@5ecb98a3c6b747ed38dc09f787459979aebb39be # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' with: name: sentry_isar diff --git a/.github/workflows/logging.yml b/.github/workflows/logging.yml index 2011312eb8..5561719acb 100644 --- a/.github/workflows/logging.yml +++ b/.github/workflows/logging.yml @@ -52,7 +52,7 @@ jobs: dart test -p vm --coverage=coverage --test-randomize-ordering-seed=random --chain-stack-traces dart pub run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.dart_tool/package_config.json --report-on=lib - - uses: codecov/codecov-action@84508663e988701840491b86de86b666e8a86bed # pin@v3 + - uses: codecov/codecov-action@5ecb98a3c6b747ed38dc09f787459979aebb39be # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: name: sentry_logging diff --git a/.github/workflows/sqflite.yml b/.github/workflows/sqflite.yml index c610ef749e..3e44664474 100644 --- a/.github/workflows/sqflite.yml +++ b/.github/workflows/sqflite.yml @@ -93,7 +93,7 @@ jobs: cd sqflite flutter test --coverage --test-randomize-ordering-seed=random - - uses: codecov/codecov-action@84508663e988701840491b86de86b666e8a86bed # pin@v3 + - uses: codecov/codecov-action@5ecb98a3c6b747ed38dc09f787459979aebb39be # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' with: name: sentry_sqflite From 3fbe78ade8f20560c1ab6c170748f6086315824c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 May 2024 17:11:26 +0200 Subject: [PATCH 167/237] build(deps): bump ScaCap/action-ktlint from 1.8.1 to 1.8.2 (#2037) Bumps [ScaCap/action-ktlint](https://github.com/scacap/action-ktlint) from 1.8.1 to 1.8.2. - [Release notes](https://github.com/scacap/action-ktlint/releases) - [Commits](https://github.com/scacap/action-ktlint/compare/38262d0fb8bff43ddafc8b3c04bce6e6c7263319...5fdeb923cb8de70cb3ef2cfd853799d430946a5d) --- updated-dependencies: - dependency-name: ScaCap/action-ktlint dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/flutter.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/flutter.yml b/.github/workflows/flutter.yml index afca6d9aac..7940dc8a1a 100644 --- a/.github/workflows/flutter.yml +++ b/.github/workflows/flutter.yml @@ -188,7 +188,7 @@ jobs: - uses: actions/checkout@v4 - name: ktlint - uses: ScaCap/action-ktlint@38262d0fb8bff43ddafc8b3c04bce6e6c7263319 # pin@1.8.1 + uses: ScaCap/action-ktlint@5fdeb923cb8de70cb3ef2cfd853799d430946a5d # pin@1.8.2 with: github_token: ${{ secrets.github_token }} reporter: github-pr-review From a5031f107229a41e4011ecb24b772e551e11316c Mon Sep 17 00:00:00 2001 From: Ivan Dlugos <6349682+vaind@users.noreply.github.com> Date: Mon, 6 May 2024 20:28:12 +0200 Subject: [PATCH 168/237] chore(deps): support prereleases in update scripts (#2031) --- flutter/scripts/update-android.sh | 3 ++- flutter/scripts/update-cocoa.sh | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/flutter/scripts/update-android.sh b/flutter/scripts/update-android.sh index 183441bee7..60775a6eec 100755 --- a/flutter/scripts/update-android.sh +++ b/flutter/scripts/update-android.sh @@ -4,7 +4,7 @@ set -euo pipefail cd $(dirname "$0")/../android file='build.gradle' content=$(cat $file) -regex='(io\.sentry:sentry-android:)([0-9\.]+)' +regex='(io\.sentry:sentry-android:)([0-9\.]+(\-[a-z0-9\.]+)?)' if ! [[ $content =~ $regex ]]; then echo "Failed to find the android plugin version in $file" exit 1 @@ -20,6 +20,7 @@ get-repo) set-version) newValue="${BASH_REMATCH[1]}$2" echo "${content/${BASH_REMATCH[0]}/$newValue}" >$file + ../scripts/generate-android-bindings.sh "$2" ;; *) echo "Unknown argument $1" diff --git a/flutter/scripts/update-cocoa.sh b/flutter/scripts/update-cocoa.sh index d54a754399..55f1c854db 100755 --- a/flutter/scripts/update-cocoa.sh +++ b/flutter/scripts/update-cocoa.sh @@ -4,7 +4,7 @@ set -euo pipefail cd $(dirname "$0")/../ios file='sentry_flutter.podspec' content=$(cat $file) -regex="('Sentry/HybridSDK', *)'([0-9\.]+)'" +regex="('Sentry/HybridSDK', *)'([0-9\.]+(\-[a-z0-9\.]+)?)'" if ! [[ $content =~ $regex ]]; then echo "Failed to find the plugin version in $file" exit 1 From 9fe67d51d3fe8a8daa73206ae4eac77ca507e406 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20Andra=C5=A1ec?= Date: Tue, 7 May 2024 07:52:29 +0000 Subject: [PATCH 169/237] Fix `PlatformException` title parsing (#2033) --- CHANGELOG.md | 4 ++ ...id_platform_exception_event_processor.dart | 7 +- ...atform_exception_event_processor_test.dart | 67 +++++++++++++++++++ 3 files changed, 76 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c545ea3e39..9b4f7e3f6e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ - Adds app start spans to first transaction ([#2009](https://github.com/getsentry/sentry-dart/pull/2009)) +### Fixes + +- Fix `PlatformException` title parsing ([#2033](https://github.com/getsentry/sentry-dart/pull/2033)) + ## 8.1.0 ### Features diff --git a/flutter/lib/src/event_processor/android_platform_exception_event_processor.dart b/flutter/lib/src/event_processor/android_platform_exception_event_processor.dart index 6570dedd81..bffc6707b7 100644 --- a/flutter/lib/src/event_processor/android_platform_exception_event_processor.dart +++ b/flutter/lib/src/event_processor/android_platform_exception_event_processor.dart @@ -153,11 +153,14 @@ extension on JvmException { String? module; final typeParts = type?.split('.'); if (typeParts != null) { - if (typeParts.length > 1) { + if (typeParts.isNotEmpty) { exceptionType = typeParts.last; } typeParts.remove(typeParts.last); - module = typeParts.join('.'); + + if (typeParts.isNotEmpty) { + module = typeParts.join('.'); + } } final stackFrames = stackTrace.asMap().entries.map((entry) { return entry.value.toSentryStackFrame(entry.key, nativePackageName); diff --git a/flutter/test/android_platform_exception_event_processor_test.dart b/flutter/test/android_platform_exception_event_processor_test.dart index 5e916f06a3..060ada138c 100644 --- a/flutter/test/android_platform_exception_event_processor_test.dart +++ b/flutter/test/android_platform_exception_event_processor_test.dart @@ -51,6 +51,32 @@ void main() { expect(platformException_2.stackTrace!.frames.length, 18); }); + test('platform exception is correctly parsed', () async { + final platformExceptionEvent = await fixture.processor + .apply(fixture.eventWithFailingPlatformStackTrace, Hint()); + + final exceptions = platformExceptionEvent!.exceptions!; + expect(exceptions.length, 3); + + final platformException = exceptions[1]; + + expect(platformException.type, 'PlatformException'); + expect( + platformException.value, + "PlatformException(getNotificationChannelsError, Unable to find resource ID #0x7f14000d, android.content.res.Resources\$NotFoundException: Unable to find resource ID #0x7f14000d", + ); + expect(platformException.stackTrace!.frames.length, 20); + + final platformException_2 = exceptions[2]; + + expect(platformException_2.type, 'PlatformException'); + expect( + platformException_2.value, + "PlatformException(getNotificationChannelsError, Unable to find resource ID #0x7f14000d, android.content.res.Resources\$NotFoundException: Unable to find resource ID #0x7f14000d", + ); + expect(platformException_2.stackTrace!.frames.length, 20); + }); + test( 'Dart thread is current and not crashed if Android exception is present', () async { @@ -142,6 +168,16 @@ class Fixture { threads: [dartThread], ); + late SentryException withFailingPlatformStackTrace = options.exceptionFactory + .getSentryException(failingPlatformException) + .copyWith(threadId: 1); + + late SentryEvent eventWithFailingPlatformStackTrace = SentryEvent( + exceptions: [withFailingPlatformStackTrace], + throwable: failingPlatformException, + threads: [dartThread], + ); + late SentryThread dartThread = SentryThread( crashed: true, current: true, @@ -169,6 +205,14 @@ final emptyPlatformException = PlatformException( stacktrace: null, ); +final failingPlatformException = PlatformException( + code: 'error', + details: + "PlatformException: PlatformException(getNotificationChannelsError, Unable to find resource ID #0x7f14000d, android.content.res.Resources\$NotFoundException: Unable to find resource ID #0x7f14000d", + message: _failingStackTrace, + stacktrace: _failingStackTrace, +); + const _jvmStackTrace = """java.lang.IllegalArgumentException: Unsupported value: '[Ljava.lang.StackTraceElement;@ba6feed' of type 'class [Ljava.lang.StackTraceElement;' at io.flutter.plugin.common.StandardMessageCodec.writeValue(StandardMessageCodec.java:292) @@ -189,3 +233,26 @@ const _jvmStackTrace = at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit\$MethodAndArgsCaller.run(RuntimeInit.java:556) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1037)"""; + +const _failingStackTrace = + """PlatformException: PlatformException(getNotificationChannelsError, Unable to find resource ID #0x7f14000d, android.content.res.Resources\$NotFoundException: Unable to find resource ID #0x7f14000d + at android.content.res.ResourcesImpl.getResourceEntryName(ResourcesImpl.java:493) + at android.content.res.Resources.getResourceEntryName(Resources.java:2441) + at com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin.getMappedNotificationChannel(FlutterLocalNotificationsPlugin.java:170) + at com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin.getNotificationChannels(FlutterLocalNotificationsPlugin.java:32) + at com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin.onMethodCall(FlutterLocalNotificationsPlugin.java:399) + at be.j\$a.a(MethodChannel.java:18) + at pd.c.l(DartMessenger.java:19) + at pd.c.m(DartMessenger.java:42) + at pd.c.h(Unknown Source:0) + at pd.b.run(Unknown Source:12) + at android.os.Handler.handleCallback(Handler.java:966) + at android.os.Handler.dispatchMessage(Handler.java:110) + at android.os.Looper.loopOnce(Looper.java:205) + at android.os.Looper.loop(Looper.java:293) + at android.app.ActivityThread.loopProcess(ActivityThread.java:9832) + at android.app.ActivityThread.main(ActivityThread.java:9821) + at java.lang.reflect.Method.invoke(Native Method) + at com.android.internal.os.RuntimeInit\$MethodAndArgsCaller.run(RuntimeInit.java:586) + at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1201) +, null)"""; From e0f6628084e38e4841c776af66a6acae5a338419 Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Tue, 7 May 2024 14:27:49 +0200 Subject: [PATCH 170/237] fix: event processor blocking transactions from being sent if `autoAppStart` is false (#2028) * Add fix * Update CHANGELOG * Fix tests * Update native_app_start_integration.dart * Implement code review * Apply auto ttid only when autoAppStart is true * Revert * Revert --- CHANGELOG.md | 4 + .../native_app_start_event_processor.dart | 24 ++++- .../native_app_start_integration.dart | 94 +++++++++++-------- .../native_app_start_integration_test.dart | 64 +++++++++++++ .../sentry_display_widget_test.dart | 2 +- 5 files changed, 144 insertions(+), 44 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b4f7e3f6e..dbfcbdd00a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Fixes + +- Event processor blocking transactions from being sent if `autoAppStart` is false ([#2028](https://github.com/getsentry/sentry-dart/pull/2028)) + ### Features - Adds app start spans to first transaction ([#2009](https://github.com/getsentry/sentry-dart/pull/2009)) diff --git a/flutter/lib/src/event_processor/native_app_start_event_processor.dart b/flutter/lib/src/event_processor/native_app_start_event_processor.dart index d22226f605..57e2eb4ed6 100644 --- a/flutter/lib/src/event_processor/native_app_start_event_processor.dart +++ b/flutter/lib/src/event_processor/native_app_start_event_processor.dart @@ -22,11 +22,25 @@ class NativeAppStartEventProcessor implements EventProcessor { @override Future apply(SentryEvent event, Hint hint) async { - if (_native.didAddAppStartMeasurement || event is! SentryTransaction) { + final options = _hub.options; + if (_native.didAddAppStartMeasurement || + event is! SentryTransaction || + options is! SentryFlutterOptions) { return event; } final appStartInfo = await NativeAppStartIntegration.getAppStartInfo(); + + final appStartEnd = _native.appStartEnd; + if (!options.autoAppStart) { + if (appStartEnd != null) { + appStartInfo?.end = appStartEnd; + } else { + // If autoAppStart is disabled and appStartEnd is not set, we can't add app starts + return event; + } + } + final measurement = appStartInfo?.toMeasurement(); if (measurement != null) { @@ -44,6 +58,10 @@ class NativeAppStartEventProcessor implements EventProcessor { Future _attachAppStartSpans( AppStartInfo appStartInfo, SentryTracer transaction) async { final transactionTraceId = transaction.context.traceId; + final appStartEnd = appStartInfo.end; + if (appStartEnd == null) { + return; + } final appStartSpan = await _createAndFinishSpan( tracer: transaction, @@ -52,7 +70,7 @@ class NativeAppStartEventProcessor implements EventProcessor { parentSpanId: transaction.context.spanId, traceId: transactionTraceId, startTimestamp: appStartInfo.start, - endTimestamp: appStartInfo.end); + endTimestamp: appStartEnd); final pluginRegistrationSpan = await _createAndFinishSpan( tracer: transaction, @@ -79,7 +97,7 @@ class NativeAppStartEventProcessor implements EventProcessor { parentSpanId: appStartSpan.context.spanId, traceId: transactionTraceId, startTimestamp: appStartInfo.mainIsolateStart, - endTimestamp: appStartInfo.end); + endTimestamp: appStartEnd); transaction.children.addAll([ appStartSpan, diff --git a/flutter/lib/src/integrations/native_app_start_integration.dart b/flutter/lib/src/integrations/native_app_start_integration.dart index 923d1a1bfa..7b015220a9 100644 --- a/flutter/lib/src/integrations/native_app_start_integration.dart +++ b/flutter/lib/src/integrations/native_app_start_integration.dart @@ -15,6 +15,9 @@ class NativeAppStartIntegration extends Integration { final SentryNative _native; final FrameCallbackHandler _frameCallbackHandler; + /// Timeout duration to wait for the app start info to be fetched. + static const _timeoutDuration = Duration(seconds: 30); + /// We filter out App starts more than 60s static const _maxAppStartMillis = 60000; @@ -39,7 +42,8 @@ class NativeAppStartIntegration extends Integration { if (_appStartInfo != null) { return Future.value(_appStartInfo); } - return _appStartCompleter.future; + return _appStartCompleter.future + .timeout(_timeoutDuration, onTimeout: () => null); } @visibleForTesting @@ -62,31 +66,31 @@ class NativeAppStartIntegration extends Integration { return; } - if (options.autoAppStart) { - _frameCallbackHandler.addPostFrameCallback((timeStamp) async { - if (_native.didFetchAppStart) { - return; - } + if (_native.didFetchAppStart) { + return; + } + _frameCallbackHandler.addPostFrameCallback((timeStamp) async { + final nativeAppStart = await _native.fetchNativeAppStart(); + if (nativeAppStart == null) { + setAppStartInfo(null); + return; + } + + final mainIsolateStartDateTime = SentryFlutter.mainIsolateStartTime; + final appStartDateTime = DateTime.fromMillisecondsSinceEpoch( + nativeAppStart.appStartTime.toInt()); + final pluginRegistrationDateTime = DateTime.fromMillisecondsSinceEpoch( + nativeAppStart.pluginRegistrationTime); + DateTime? appStartEndDateTime; + + if (options.autoAppStart) { // We only assign the current time if it's not already set - this is useful in tests // ignore: invalid_use_of_internal_member _native.appStartEnd ??= options.clock(); - final appStartEndDateTime = _native.appStartEnd; - final nativeAppStart = await _native.fetchNativeAppStart(); - final pluginRegistrationTime = nativeAppStart?.pluginRegistrationTime; - final mainIsolateStartDateTime = SentryFlutter.mainIsolateStartTime; - - if (nativeAppStart == null || - appStartEndDateTime == null || - pluginRegistrationTime == null) { - return; - } + appStartEndDateTime = _native.appStartEnd; - final appStartDateTime = DateTime.fromMillisecondsSinceEpoch( - nativeAppStart.appStartTime.toInt()); - final duration = appStartEndDateTime.difference(appStartDateTime); - final pluginRegistrationDateTime = - DateTime.fromMillisecondsSinceEpoch(pluginRegistrationTime); + final duration = appStartEndDateTime?.difference(appStartDateTime); // We filter out app start more than 60s. // This could be due to many different reasons. @@ -96,23 +100,23 @@ class NativeAppStartIntegration extends Integration { // If the system forked the process earlier to accelerate the app start. // And some unknown reasons that could not be reproduced. // We've seen app starts with hours, days and even months. - if (duration.inMilliseconds > _maxAppStartMillis) { + if (duration != null && duration.inMilliseconds > _maxAppStartMillis) { setAppStartInfo(null); return; } + } - final appStartInfo = AppStartInfo( - nativeAppStart.isColdStart ? AppStartType.cold : AppStartType.warm, - start: appStartDateTime, - end: appStartEndDateTime, - pluginRegistration: pluginRegistrationDateTime, - mainIsolateStart: mainIsolateStartDateTime); + final appStartInfo = AppStartInfo( + nativeAppStart.isColdStart ? AppStartType.cold : AppStartType.warm, + start: appStartDateTime, + end: appStartEndDateTime, + pluginRegistration: pluginRegistrationDateTime, + mainIsolateStart: mainIsolateStartDateTime); - setAppStartInfo(appStartInfo); - }); - } + setAppStartInfo(appStartInfo); + }); - options.addEventProcessor(NativeAppStartEventProcessor(_native)); + options.addEventProcessor(NativeAppStartEventProcessor(_native, hub: hub)); options.sdk.addIntegration('nativeAppStartIntegration'); } @@ -121,21 +125,31 @@ class NativeAppStartIntegration extends Integration { enum AppStartType { cold, warm } class AppStartInfo { - AppStartInfo(this.type, - {required this.start, - required this.end, - required this.pluginRegistration, - required this.mainIsolateStart}); + AppStartInfo( + this.type, { + required this.start, + required this.pluginRegistration, + required this.mainIsolateStart, + this.end, + }); final AppStartType type; final DateTime start; - final DateTime end; + + // We allow the end to be null, since it might be set at a later time + // with setAppStartEnd when autoAppStart is disabled + DateTime? end; + final DateTime pluginRegistration; final DateTime mainIsolateStart; - Duration get duration => end.difference(start); + Duration? get duration => end?.difference(start); - SentryMeasurement toMeasurement() { + SentryMeasurement? toMeasurement() { + final duration = this.duration; + if (duration == null) { + return null; + } return type == AppStartType.cold ? SentryMeasurement.coldAppStart(duration) : SentryMeasurement.warmAppStart(duration); diff --git a/flutter/test/integrations/native_app_start_integration_test.dart b/flutter/test/integrations/native_app_start_integration_test.dart index a6b712af12..0ebc3cb4c2 100644 --- a/flutter/test/integrations/native_app_start_integration_test.dart +++ b/flutter/test/integrations/native_app_start_integration_test.dart @@ -114,6 +114,70 @@ void main() { expect(appStartInfo?.start, DateTime.fromMillisecondsSinceEpoch(0)); expect(appStartInfo?.end, DateTime.fromMillisecondsSinceEpoch(10)); }); + + test( + 'autoAppStart is false and appStartEnd is not set does not add app start measurement', + () async { + fixture.options.autoAppStart = false; + fixture.binding.nativeAppStart = NativeAppStart( + appStartTime: 0, pluginRegistrationTime: 10, isColdStart: true); + + fixture.getNativeAppStartIntegration().call(fixture.hub, fixture.options); + + final tracer = fixture.createTracer(); + final transaction = SentryTransaction(tracer); + + final processor = fixture.options.eventProcessors.first; + final enriched = + await processor.apply(transaction, Hint()) as SentryTransaction; + + expect(enriched.measurements.isEmpty, true); + expect(enriched.spans.isEmpty, true); + }); + + test( + 'autoAppStart is false and appStartEnd is set adds app start measurement', + () async { + fixture.options.autoAppStart = false; + fixture.binding.nativeAppStart = NativeAppStart( + appStartTime: 0, pluginRegistrationTime: 10, isColdStart: true); + SentryFlutter.native = fixture.native; + + fixture.getNativeAppStartIntegration().call(fixture.hub, fixture.options); + + SentryFlutter.setAppStartEnd(DateTime.fromMillisecondsSinceEpoch(10)); + + final tracer = fixture.createTracer(); + final transaction = SentryTransaction(tracer); + + final processor = fixture.options.eventProcessors.first; + final enriched = + await processor.apply(transaction, Hint()) as SentryTransaction; + + final measurement = enriched.measurements['app_start_cold']!; + expect(measurement.value, 10); + expect(measurement.unit, DurationSentryMeasurementUnit.milliSecond); + + final appStartInfo = await NativeAppStartIntegration.getAppStartInfo(); + + final appStartSpan = enriched.spans.firstWhereOrNull((element) => + element.context.description == appStartInfo!.appStartTypeDescription); + final pluginRegistrationSpan = enriched.spans.firstWhereOrNull( + (element) => + element.context.description == + appStartInfo!.pluginRegistrationDescription); + final mainIsolateSetupSpan = enriched.spans.firstWhereOrNull((element) => + element.context.description == + appStartInfo!.mainIsolateSetupDescription); + final firstFrameRenderSpan = enriched.spans.firstWhereOrNull((element) => + element.context.description == + appStartInfo!.firstFrameRenderDescription); + + expect(appStartSpan, isNotNull); + expect(pluginRegistrationSpan, isNotNull); + expect(mainIsolateSetupSpan, isNotNull); + expect(firstFrameRenderSpan, isNotNull); + }); }); group('App start spans', () { diff --git a/flutter/test/navigation/sentry_display_widget_test.dart b/flutter/test/navigation/sentry_display_widget_test.dart index 092dc0ab65..6a0e912d5e 100644 --- a/flutter/test/navigation/sentry_display_widget_test.dart +++ b/flutter/test/navigation/sentry_display_widget_test.dart @@ -94,7 +94,7 @@ void main() { expect(tracer.measurements, hasLength(1)); final measurement = tracer.measurements['time_to_initial_display']; expect(measurement, isNotNull); - expect(measurement?.value, appStartInfo.duration.inMilliseconds); + expect(measurement?.value, appStartInfo.duration?.inMilliseconds); expect(measurement?.value, ttidSpanDuration.inMilliseconds); expect(measurement?.unit, DurationSentryMeasurementUnit.milliSecond); }); From c2c93b34ce59e38b531490220228c3c85a5e78d1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 8 May 2024 10:54:41 +0200 Subject: [PATCH 171/237] build(deps): bump subosito/flutter-action from 2.10.0 to 2.16.0 (#2020) Bumps [subosito/flutter-action](https://github.com/subosito/flutter-action) from 2.10.0 to 2.16.0. - [Release notes](https://github.com/subosito/flutter-action/releases) - [Commits](https://github.com/subosito/flutter-action/compare/v2.10.0...44ac965b96f18d999802d4b807e3256d5a3f9fa1) --- updated-dependencies: - dependency-name: subosito/flutter-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor --- .github/workflows/flutter_integration_test.yml | 4 ++-- .github/workflows/testflight.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/flutter_integration_test.yml b/.github/workflows/flutter_integration_test.yml index d6c75ba38f..162c52b5e6 100644 --- a/.github/workflows/flutter_integration_test.yml +++ b/.github/workflows/flutter_integration_test.yml @@ -38,7 +38,7 @@ jobs: distribution: "adopt" java-version: "11" - - uses: subosito/flutter-action@48cafc24713cca54bbe03cdc3a423187d413aafa # pin@v2.10.0 + - uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 # pin@v2.16.0 with: channel: ${{ matrix.sdk }} @@ -100,7 +100,7 @@ jobs: - name: checkout uses: actions/checkout@v4 - - uses: subosito/flutter-action@48cafc24713cca54bbe03cdc3a423187d413aafa # pin@v2.10.0 + - uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 # pin@v2.16.0 with: channel: ${{ matrix.sdk }} diff --git a/.github/workflows/testflight.yml b/.github/workflows/testflight.yml index 3e05b6afbb..a40d5ba02e 100644 --- a/.github/workflows/testflight.yml +++ b/.github/workflows/testflight.yml @@ -14,7 +14,7 @@ jobs: runs-on: macos-13 steps: - uses: actions/checkout@v4 - - uses: subosito/flutter-action@48cafc24713cca54bbe03cdc3a423187d413aafa # pin@v2.10.0 + - uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 # pin@v2.16.0 - run: xcodes select 15.0.1 - uses: ruby/setup-ruby@250fcd6a742febb1123a77a841497ccaa8b9e939 # pin@v1.152.0 with: From 4656f10b89fe70667fd5807037fedc9550a54d73 Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Fri, 10 May 2024 00:02:19 +0200 Subject: [PATCH 172/237] App start: native spans (#2027) * commit * Update * Remove print * Remove comments * Update * Add linting * Update CHANGELOG * Update CHANGELOG.md * Update naming * Update naming * Update naming * Update description from first frame render to initial frame render * Initial * update * dart format * Update comments * Update * Update * Update * Update * Update * Fix tests * Fix test * Add unused import * Fix tests * Update * Updaet * Update * Update * Update CHANGELOG * Update CHANGELOG * Update formatting of kotlin file * Update * Update test * format * Update SentryFlutterPlugin.kt * Update SentryFlutterPlugin.kt * Update * Update main.dart * Update * Update * Update * Updaet * Format * Update flutter/lib/src/sentry_flutter.dart Co-authored-by: Stefano --------- Co-authored-by: Stefano --- CHANGELOG.md | 1 + .../io/sentry/flutter/SentryFlutterPlugin.kt | 59 ++++++- flutter/example/android/build.gradle | 3 +- .../xcshareddata/xcschemes/Runner.xcscheme | 2 +- .../Classes/SentryFlutterPluginApple.swift | 61 ++++++- .../native_app_start_event_processor.dart | 35 +++- .../native_app_start_integration.dart | 71 ++++++-- flutter/lib/src/native/sentry_native.dart | 5 +- flutter/lib/src/sentry_flutter.dart | 7 +- .../native_app_start_integration_test.dart | 162 +++++++++++++++--- .../sentry_display_widget_test.dart | 3 +- flutter/test/sentry_native_channel_test.dart | 2 + flutter/test/sentry_native_test.dart | 6 +- .../test/sentry_navigator_observer_test.dart | 3 +- 14 files changed, 354 insertions(+), 66 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dbfcbdd00a..3de2f68fae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ ### Features +- Adds native spans to app start transaction ([#2027](https://github.com/getsentry/sentry-dart/pull/2027)) - Adds app start spans to first transaction ([#2009](https://github.com/getsentry/sentry-dart/pull/2009)) ### Fixes diff --git a/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutterPlugin.kt b/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutterPlugin.kt index 8d92c9178c..424e51c6b7 100644 --- a/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutterPlugin.kt +++ b/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutterPlugin.kt @@ -23,6 +23,7 @@ import io.sentry.android.core.LoadClass import io.sentry.android.core.SentryAndroid import io.sentry.android.core.SentryAndroidOptions import io.sentry.android.core.performance.AppStartMetrics +import io.sentry.android.core.performance.TimeSpan import io.sentry.protocol.DebugImage import io.sentry.protocol.SdkVersion import io.sentry.protocol.SentryId @@ -130,24 +131,66 @@ class SentryFlutterPlugin : FlutterPlugin, MethodCallHandler, ActivityAware { return } - val appStartTime = AppStartMetrics.getInstance().appStartTimeSpan.startTimestamp - val isColdStart = - AppStartMetrics.getInstance().appStartType == AppStartMetrics.AppStartType.COLD + val appStartMetrics = AppStartMetrics.getInstance() + + val appStartTimeSpan = appStartMetrics.appStartTimeSpan + val appStartTime = appStartTimeSpan.startTimestamp + val isColdStart = appStartMetrics.appStartType == AppStartMetrics.AppStartType.COLD if (appStartTime == null) { Log.w("Sentry", "App start won't be sent due to missing appStartTime") result.success(null) } else { val appStartTimeMillis = DateUtils.nanosToMillis(appStartTime.nanoTimestamp().toDouble()) - val item = mapOf( - "pluginRegistrationTime" to pluginRegistrationTime, - "appStartTime" to appStartTimeMillis, - "isColdStart" to isColdStart, - ) + val item = + mutableMapOf( + "pluginRegistrationTime" to pluginRegistrationTime, + "appStartTime" to appStartTimeMillis, + "isColdStart" to isColdStart, + ) + + val androidNativeSpans = mutableMapOf() + + val processInitSpan = + TimeSpan().apply { + description = "Process Initialization" + setStartUnixTimeMs(appStartTimeSpan.startTimestampMs) + setStartedAt(appStartTimeSpan.startUptimeMs) + setStoppedAt(appStartMetrics.classLoadedUptimeMs) + } + processInitSpan.addToMap(androidNativeSpans) + + val applicationOnCreateSpan = appStartMetrics.applicationOnCreateTimeSpan + applicationOnCreateSpan.addToMap(androidNativeSpans) + + val contentProviderSpans = appStartMetrics.contentProviderOnCreateTimeSpans + contentProviderSpans.forEach { span -> + span.addToMap(androidNativeSpans) + } + + appStartMetrics.activityLifecycleTimeSpans.forEach { span -> + span.onCreate.addToMap(androidNativeSpans) + span.onStart.addToMap(androidNativeSpans) + } + + item["nativeSpanTimes"] = androidNativeSpans + result.success(item) } } + private fun TimeSpan.addToMap(map: MutableMap) { + if (startTimestamp == null) return + + description?.let { description -> + map[description] = + mapOf( + "startTimestampMsSinceEpoch" to startTimestampMs, + "stopTimestampMsSinceEpoch" to projectedStopTimestampMs, + ) + } + } + private fun beginNativeFrames(result: Result) { if (!sentryFlutter.autoPerformanceTracingEnabled) { result.success(null) diff --git a/flutter/example/android/build.gradle b/flutter/example/android/build.gradle index 50bb21eda7..693111bbb3 100644 --- a/flutter/example/android/build.gradle +++ b/flutter/example/android/build.gradle @@ -7,7 +7,7 @@ buildscript { } dependencies { - classpath 'io.sentry:sentry-android-gradle-plugin:4.2.0' + classpath 'io.sentry:sentry-android-gradle-plugin:4.5.0' classpath 'com.android.tools.build:gradle:7.2.2' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath 'io.github.howardpang:androidNativeBundle:1.1.3' @@ -32,4 +32,3 @@ subprojects { tasks.register("clean", Delete) { delete rootProject.buildDir } - diff --git a/flutter/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/flutter/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 0fa7c24eb1..fee8e19903 100644 --- a/flutter/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/flutter/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ Int64 { + return Int64(self * 1000) + } +} diff --git a/flutter/lib/src/event_processor/native_app_start_event_processor.dart b/flutter/lib/src/event_processor/native_app_start_event_processor.dart index 57e2eb4ed6..f8ea23b265 100644 --- a/flutter/lib/src/event_processor/native_app_start_event_processor.dart +++ b/flutter/lib/src/event_processor/native_app_start_event_processor.dart @@ -42,7 +42,6 @@ class NativeAppStartEventProcessor implements EventProcessor { } final measurement = appStartInfo?.toMeasurement(); - if (measurement != null) { event.measurements[measurement.name] = measurement; _native.didAddAppStartMeasurement = true; @@ -72,6 +71,8 @@ class NativeAppStartEventProcessor implements EventProcessor { startTimestamp: appStartInfo.start, endTimestamp: appStartEnd); + await _attachNativeSpans(appStartInfo, transaction, appStartSpan); + final pluginRegistrationSpan = await _createAndFinishSpan( tracer: transaction, operation: appStartInfo.appStartTypeOperation, @@ -81,14 +82,14 @@ class NativeAppStartEventProcessor implements EventProcessor { startTimestamp: appStartInfo.start, endTimestamp: appStartInfo.pluginRegistration); - final mainIsolateSetupSpan = await _createAndFinishSpan( + final sentrySetupSpan = await _createAndFinishSpan( tracer: transaction, operation: appStartInfo.appStartTypeOperation, - description: appStartInfo.mainIsolateSetupDescription, + description: appStartInfo.sentrySetupDescription, parentSpanId: appStartSpan.context.spanId, traceId: transactionTraceId, startTimestamp: appStartInfo.pluginRegistration, - endTimestamp: appStartInfo.mainIsolateStart); + endTimestamp: appStartInfo.sentrySetupStart); final firstFrameRenderSpan = await _createAndFinishSpan( tracer: transaction, @@ -96,17 +97,39 @@ class NativeAppStartEventProcessor implements EventProcessor { description: appStartInfo.firstFrameRenderDescription, parentSpanId: appStartSpan.context.spanId, traceId: transactionTraceId, - startTimestamp: appStartInfo.mainIsolateStart, + startTimestamp: appStartInfo.sentrySetupStart, endTimestamp: appStartEnd); transaction.children.addAll([ appStartSpan, pluginRegistrationSpan, - mainIsolateSetupSpan, + sentrySetupSpan, firstFrameRenderSpan ]); } + Future _attachNativeSpans(AppStartInfo appStartInfo, + SentryTracer transaction, SentrySpan parent) async { + await Future.forEach(appStartInfo.nativeSpanTimes, + (timeSpan) async { + try { + final span = await _createAndFinishSpan( + tracer: transaction, + operation: appStartInfo.appStartTypeOperation, + description: timeSpan.description, + parentSpanId: parent.context.spanId, + traceId: transaction.context.traceId, + startTimestamp: timeSpan.start, + endTimestamp: timeSpan.end); + span.data.putIfAbsent('native', () => true); + transaction.children.add(span); + } catch (e) { + _hub.options.logger(SentryLevel.warning, + 'Failed to attach native span to app start transaction: $e'); + } + }); + } + Future _createAndFinishSpan({ required SentryTracer tracer, required String operation, diff --git a/flutter/lib/src/integrations/native_app_start_integration.dart b/flutter/lib/src/integrations/native_app_start_integration.dart index 7b015220a9..13ca865422 100644 --- a/flutter/lib/src/integrations/native_app_start_integration.dart +++ b/flutter/lib/src/integrations/native_app_start_integration.dart @@ -10,10 +10,13 @@ import '../event_processor/native_app_start_event_processor.dart'; /// Integration which handles communication with native frameworks in order to /// enrich [SentryTransaction] objects with app start data for mobile vitals. class NativeAppStartIntegration extends Integration { - NativeAppStartIntegration(this._native, this._frameCallbackHandler); + NativeAppStartIntegration(this._native, this._frameCallbackHandler, + {Hub? hub}) + : _hub = hub ?? HubAdapter(); final SentryNative _native; final FrameCallbackHandler _frameCallbackHandler; + final Hub _hub; /// Timeout duration to wait for the app start info to be fetched. static const _timeoutDuration = Duration(seconds: 30); @@ -55,13 +58,15 @@ class NativeAppStartIntegration extends Integration { @override void call(Hub hub, SentryFlutterOptions options) { if (isIntegrationTest) { - final appStartInfo = AppStartInfo(AppStartType.cold, - start: DateTime.now(), - end: DateTime.now().add(const Duration(milliseconds: 100)), - pluginRegistration: - DateTime.now().add(const Duration(milliseconds: 50)), - mainIsolateStart: - DateTime.now().add(const Duration(milliseconds: 60))); + final appStartInfo = AppStartInfo( + AppStartType.cold, + start: DateTime.now(), + end: DateTime.now().add(const Duration(milliseconds: 100)), + pluginRegistration: + DateTime.now().add(const Duration(milliseconds: 50)), + sentrySetupStart: DateTime.now().add(const Duration(milliseconds: 60)), + nativeSpanTimes: [], + ); setAppStartInfo(appStartInfo); return; } @@ -77,7 +82,12 @@ class NativeAppStartIntegration extends Integration { return; } - final mainIsolateStartDateTime = SentryFlutter.mainIsolateStartTime; + final sentrySetupStartDateTime = SentryFlutter.sentrySetupStartTime; + if (sentrySetupStartDateTime == null) { + setAppStartInfo(null); + return; + } + final appStartDateTime = DateTime.fromMillisecondsSinceEpoch( nativeAppStart.appStartTime.toInt()); final pluginRegistrationDateTime = DateTime.fromMillisecondsSinceEpoch( @@ -106,12 +116,37 @@ class NativeAppStartIntegration extends Integration { } } + List nativeSpanTimes = []; + for (final entry in nativeAppStart.nativeSpanTimes.entries) { + try { + final startTimestampMs = + entry.value['startTimestampMsSinceEpoch'] as int; + final endTimestampMs = + entry.value['stopTimestampMsSinceEpoch'] as int; + nativeSpanTimes.add(TimeSpan( + start: DateTime.fromMillisecondsSinceEpoch(startTimestampMs), + end: DateTime.fromMillisecondsSinceEpoch(endTimestampMs), + description: entry.key as String, + )); + } catch (e) { + // ignore: invalid_use_of_internal_member + _hub.options.logger( + SentryLevel.warning, 'Failed to parse native span times: $e'); + continue; + } + } + + // We want to sort because the native spans are not guaranteed to be in order. + // Performance wise this won't affect us since the native span amount is very low. + nativeSpanTimes.sort((a, b) => a.start.compareTo(b.start)); + final appStartInfo = AppStartInfo( nativeAppStart.isColdStart ? AppStartType.cold : AppStartType.warm, start: appStartDateTime, end: appStartEndDateTime, pluginRegistration: pluginRegistrationDateTime, - mainIsolateStart: mainIsolateStartDateTime); + sentrySetupStart: sentrySetupStartDateTime, + nativeSpanTimes: nativeSpanTimes); setAppStartInfo(appStartInfo); }); @@ -129,19 +164,21 @@ class AppStartInfo { this.type, { required this.start, required this.pluginRegistration, - required this.mainIsolateStart, + required this.sentrySetupStart, + required this.nativeSpanTimes, this.end, }); final AppStartType type; final DateTime start; + final List nativeSpanTimes; // We allow the end to be null, since it might be set at a later time // with setAppStartEnd when autoAppStart is disabled DateTime? end; final DateTime pluginRegistration; - final DateTime mainIsolateStart; + final DateTime sentrySetupStart; Duration? get duration => end?.difference(start); @@ -160,6 +197,14 @@ class AppStartInfo { String get appStartTypeDescription => type == AppStartType.cold ? 'Cold start' : 'Warm start'; final pluginRegistrationDescription = 'App start to plugin registration'; - final mainIsolateSetupDescription = 'Main isolate setup'; + final sentrySetupDescription = 'Before Sentry Init Setup'; final firstFrameRenderDescription = 'First frame render'; } + +class TimeSpan { + TimeSpan({required this.start, required this.end, required this.description}); + + final DateTime start; + final DateTime end; + final String description; +} diff --git a/flutter/lib/src/native/sentry_native.dart b/flutter/lib/src/native/sentry_native.dart index 893c55d6bc..d8d9c5a964 100644 --- a/flutter/lib/src/native/sentry_native.dart +++ b/flutter/lib/src/native/sentry_native.dart @@ -137,17 +137,20 @@ class NativeAppStart { NativeAppStart( {required this.appStartTime, required this.pluginRegistrationTime, - required this.isColdStart}); + required this.isColdStart, + required this.nativeSpanTimes}); double appStartTime; int pluginRegistrationTime; bool isColdStart; + Map nativeSpanTimes; factory NativeAppStart.fromJson(Map json) { return NativeAppStart( appStartTime: json['appStartTime'] as double, pluginRegistrationTime: json['pluginRegistrationTime'] as int, isColdStart: json['isColdStart'] as bool, + nativeSpanTimes: json['nativeSpanTimes'] as Map, ); } } diff --git a/flutter/lib/src/sentry_flutter.dart b/flutter/lib/src/sentry_flutter.dart index 9b0792c7e3..e0d4415de5 100644 --- a/flutter/lib/src/sentry_flutter.dart +++ b/flutter/lib/src/sentry_flutter.dart @@ -34,10 +34,10 @@ typedef FlutterOptionsConfiguration = FutureOr Function( mixin SentryFlutter { static const _channel = MethodChannel('sentry_flutter'); - /// Represents the time when the main isolate is set up and ready to execute. + /// Represents the time when the Sentry init set up has started. @internal // ignore: invalid_use_of_internal_member - static DateTime mainIsolateStartTime = getUtcDateTime(); + static DateTime? sentrySetupStartTime; static Future init( FlutterOptionsConfiguration optionsConfiguration, { @@ -48,6 +48,9 @@ mixin SentryFlutter { }) async { final flutterOptions = SentryFlutterOptions(); + // ignore: invalid_use_of_internal_member + sentrySetupStartTime ??= flutterOptions.clock(); + if (platformChecker != null) { flutterOptions.platformChecker = platformChecker; } diff --git a/flutter/test/integrations/native_app_start_integration_test.dart b/flutter/test/integrations/native_app_start_integration_test.dart index 0ebc3cb4c2..ce555ceb9d 100644 --- a/flutter/test/integrations/native_app_start_integration_test.dart +++ b/flutter/test/integrations/native_app_start_integration_test.dart @@ -25,7 +25,10 @@ void main() { test('native app start measurement added to first transaction', () async { fixture.native.appStartEnd = DateTime.fromMillisecondsSinceEpoch(10); fixture.binding.nativeAppStart = NativeAppStart( - appStartTime: 0, pluginRegistrationTime: 10, isColdStart: true); + appStartTime: 0, + pluginRegistrationTime: 10, + isColdStart: true, + nativeSpanTimes: {}); fixture.getNativeAppStartIntegration().call(fixture.hub, fixture.options); @@ -45,7 +48,10 @@ void main() { () async { fixture.native.appStartEnd = DateTime.fromMillisecondsSinceEpoch(10); fixture.binding.nativeAppStart = NativeAppStart( - appStartTime: 0, pluginRegistrationTime: 10, isColdStart: true); + appStartTime: 0, + pluginRegistrationTime: 10, + isColdStart: true, + nativeSpanTimes: {}); fixture.getNativeAppStartIntegration().call(fixture.hub, fixture.options); @@ -65,7 +71,10 @@ void main() { test('measurements appended', () async { fixture.native.appStartEnd = DateTime.fromMillisecondsSinceEpoch(10); fixture.binding.nativeAppStart = NativeAppStart( - appStartTime: 0, pluginRegistrationTime: 10, isColdStart: true); + appStartTime: 0, + pluginRegistrationTime: 10, + isColdStart: true, + nativeSpanTimes: {}); final measurement = SentryMeasurement.warmAppStart(Duration(seconds: 1)); fixture.getNativeAppStartIntegration().call(fixture.hub, fixture.options); @@ -88,7 +97,10 @@ void main() { test('native app start measurement not added if more than 60s', () async { fixture.native.appStartEnd = DateTime.fromMillisecondsSinceEpoch(60001); fixture.binding.nativeAppStart = NativeAppStart( - appStartTime: 0, pluginRegistrationTime: 10, isColdStart: true); + appStartTime: 0, + pluginRegistrationTime: 10, + isColdStart: true, + nativeSpanTimes: {}); fixture.getNativeAppStartIntegration().call(fixture.hub, fixture.options); @@ -106,7 +118,10 @@ void main() { () async { fixture.native.appStartEnd = DateTime.fromMillisecondsSinceEpoch(10); fixture.binding.nativeAppStart = NativeAppStart( - appStartTime: 0, pluginRegistrationTime: 10, isColdStart: true); + appStartTime: 0, + pluginRegistrationTime: 10, + isColdStart: true, + nativeSpanTimes: {}); fixture.getNativeAppStartIntegration().call(fixture.hub, fixture.options); @@ -120,7 +135,10 @@ void main() { () async { fixture.options.autoAppStart = false; fixture.binding.nativeAppStart = NativeAppStart( - appStartTime: 0, pluginRegistrationTime: 10, isColdStart: true); + appStartTime: 0, + pluginRegistrationTime: 10, + isColdStart: true, + nativeSpanTimes: {}); fixture.getNativeAppStartIntegration().call(fixture.hub, fixture.options); @@ -140,7 +158,10 @@ void main() { () async { fixture.options.autoAppStart = false; fixture.binding.nativeAppStart = NativeAppStart( - appStartTime: 0, pluginRegistrationTime: 10, isColdStart: true); + appStartTime: 0, + pluginRegistrationTime: 10, + isColdStart: true, + nativeSpanTimes: {}); SentryFlutter.native = fixture.native; fixture.getNativeAppStartIntegration().call(fixture.hub, fixture.options); @@ -166,16 +187,15 @@ void main() { (element) => element.context.description == appStartInfo!.pluginRegistrationDescription); - final mainIsolateSetupSpan = enriched.spans.firstWhereOrNull((element) => - element.context.description == - appStartInfo!.mainIsolateSetupDescription); + final sentrySetupSpan = enriched.spans.firstWhereOrNull((element) => + element.context.description == appStartInfo!.sentrySetupDescription); final firstFrameRenderSpan = enriched.spans.firstWhereOrNull((element) => element.context.description == appStartInfo!.firstFrameRenderDescription); expect(appStartSpan, isNotNull); expect(pluginRegistrationSpan, isNotNull); - expect(mainIsolateSetupSpan, isNotNull); + expect(sentrySetupSpan, isNotNull); expect(firstFrameRenderSpan, isNotNull); }); }); @@ -183,11 +203,43 @@ void main() { group('App start spans', () { late SentrySpan? coldStartSpan, pluginRegistrationSpan, - mainIsolateSetupSpan, + sentrySetupSpan, firstFrameRenderSpan; // ignore: invalid_use_of_internal_member late SentryTracer tracer; late Fixture fixture; + late SentryTransaction enriched; + + final validNativeSpanTimes = { + 'correct span description': { + 'startTimestampMsSinceEpoch': 1, + 'stopTimestampMsSinceEpoch': 2, + }, + 'correct span description 2': { + 'startTimestampMsSinceEpoch': 4, + 'stopTimestampMsSinceEpoch': 6, + }, + 'correct span description 3': { + 'startTimestampMsSinceEpoch': 3, + 'stopTimestampMsSinceEpoch': 4, + }, + }; + + final invalidNativeSpanTimes = { + 'failing span with null timestamp': { + 'startTimestampMsSinceEpoch': null, + 'stopTimestampMsSinceEpoch': 3, + }, + 'failing span with string timestamp': { + 'startTimestampMsSinceEpoch': '1', + 'stopTimestampMsSinceEpoch': 3, + }, + }; + + final allNativeSpanTimes = { + ...validNativeSpanTimes, + ...invalidNativeSpanTimes, + }; setUp(() async { TestWidgetsFlutterBinding.ensureInitialized(); @@ -197,9 +249,12 @@ void main() { fixture.native.appStartEnd = DateTime.fromMillisecondsSinceEpoch(50); fixture.binding.nativeAppStart = NativeAppStart( - appStartTime: 0, pluginRegistrationTime: 10, isColdStart: true); + appStartTime: 0, + pluginRegistrationTime: 10, + isColdStart: true, + nativeSpanTimes: allNativeSpanTimes); // dartLoadingEnd needs to be set after engine end (see MockNativeChannel) - SentryFlutter.mainIsolateStartTime = + SentryFlutter.sentrySetupStartTime = DateTime.fromMillisecondsSinceEpoch(15); fixture.getNativeAppStartIntegration().call(fixture.hub, fixture.options); @@ -207,7 +262,7 @@ void main() { final processor = fixture.options.eventProcessors.first; tracer = fixture.createTracer(); final transaction = SentryTransaction(tracer); - final enriched = + enriched = await processor.apply(transaction, Hint()) as SentryTransaction; final appStartInfo = await NativeAppStartIntegration.getAppStartInfo(); @@ -217,18 +272,68 @@ void main() { pluginRegistrationSpan = enriched.spans.firstWhereOrNull((element) => element.context.description == appStartInfo?.pluginRegistrationDescription); - mainIsolateSetupSpan = enriched.spans.firstWhereOrNull((element) => - element.context.description == - appStartInfo?.mainIsolateSetupDescription); + sentrySetupSpan = enriched.spans.firstWhereOrNull((element) => + element.context.description == appStartInfo?.sentrySetupDescription); firstFrameRenderSpan = enriched.spans.firstWhereOrNull((element) => element.context.description == appStartInfo?.firstFrameRenderDescription); }); + test('native app start spans not added to following transactions', + () async { + final processor = fixture.options.eventProcessors.first; + + final transaction = SentryTransaction(fixture.createTracer()); + + final secondEnriched = + await processor.apply(transaction, Hint()) as SentryTransaction; + + expect(secondEnriched.spans.length, 0); + }); + + test('includes only valid native spans', () async { + final spans = + enriched.spans.where((element) => element.data['native'] == true); + + expect(spans.length, validNativeSpanTimes.length); + + for (final span in spans) { + final validSpan = validNativeSpanTimes[span.context.description]; + expect(validSpan, isNotNull); + expect( + span.startTimestamp, + DateTime.fromMillisecondsSinceEpoch( + validSpan!['startTimestampMsSinceEpoch']!) + .toUtc()); + expect( + span.endTimestamp, + DateTime.fromMillisecondsSinceEpoch( + validSpan['stopTimestampMsSinceEpoch']!) + .toUtc()); + } + }); + + test('are correctly ordered', () async { + final spans = + enriched.spans.where((element) => element.data['native'] == true); + + final orderedSpans = spans.toList() + ..sort((a, b) => a.startTimestamp.compareTo(b.startTimestamp)); + + expect(spans, orderedEquals(orderedSpans)); + }); + + test('ignores invalid spans', () async { + final spans = + enriched.spans.where((element) => element.data['native'] == true); + + expect(spans, isNot(contains('failing span'))); + }); + test('are added by event processor', () async { expect(coldStartSpan, isNotNull); expect(pluginRegistrationSpan, isNotNull); - expect(mainIsolateSetupSpan, isNotNull); + expect(sentrySetupSpan, isNotNull); expect(firstFrameRenderSpan, isNotNull); }); @@ -236,7 +341,7 @@ void main() { const op = 'app.start.cold'; expect(coldStartSpan?.context.operation, op); expect(pluginRegistrationSpan?.context.operation, op); - expect(mainIsolateSetupSpan?.context.operation, op); + expect(sentrySetupSpan?.context.operation, op); expect(firstFrameRenderSpan?.context.operation, op); }); @@ -244,8 +349,8 @@ void main() { expect(coldStartSpan?.context.parentSpanId, tracer.context.spanId); expect(pluginRegistrationSpan?.context.parentSpanId, coldStartSpan?.context.spanId); - expect(mainIsolateSetupSpan?.context.parentSpanId, - coldStartSpan?.context.spanId); + expect( + sentrySetupSpan?.context.parentSpanId, coldStartSpan?.context.spanId); expect(firstFrameRenderSpan?.context.parentSpanId, coldStartSpan?.context.spanId); }); @@ -254,7 +359,7 @@ void main() { final traceId = tracer.context.traceId; expect(coldStartSpan?.context.traceId, traceId); expect(pluginRegistrationSpan?.context.traceId, traceId); - expect(mainIsolateSetupSpan?.context.traceId, traceId); + expect(sentrySetupSpan?.context.traceId, traceId); expect(firstFrameRenderSpan?.context.traceId, traceId); }); @@ -264,10 +369,10 @@ void main() { .toUtc(); expect(coldStartSpan?.startTimestamp, appStartTime); expect(pluginRegistrationSpan?.startTimestamp, appStartTime); - expect(mainIsolateSetupSpan?.startTimestamp, + expect(sentrySetupSpan?.startTimestamp, pluginRegistrationSpan?.endTimestamp); - expect(firstFrameRenderSpan?.startTimestamp, - mainIsolateSetupSpan?.endTimestamp); + expect( + firstFrameRenderSpan?.startTimestamp, sentrySetupSpan?.endTimestamp); }); test('have correct endTimestamp', () async { @@ -276,8 +381,8 @@ void main() { .toUtc(); expect(coldStartSpan?.endTimestamp, fixture.native.appStartEnd?.toUtc()); expect(pluginRegistrationSpan?.endTimestamp, engineReadyEndtime); - expect(mainIsolateSetupSpan?.endTimestamp, - SentryFlutter.mainIsolateStartTime.toUtc()); + expect(sentrySetupSpan?.endTimestamp, + SentryFlutter.sentrySetupStartTime?.toUtc()); expect(firstFrameRenderSpan?.endTimestamp, coldStartSpan?.endTimestamp); }); }); @@ -292,6 +397,7 @@ class Fixture { Fixture() { native.reset(); when(hub.options).thenReturn(options); + SentryFlutter.sentrySetupStartTime = DateTime.now().toUtc(); } NativeAppStartIntegration getNativeAppStartIntegration() { diff --git a/flutter/test/navigation/sentry_display_widget_test.dart b/flutter/test/navigation/sentry_display_widget_test.dart index 6a0e912d5e..2cafb706d5 100644 --- a/flutter/test/navigation/sentry_display_widget_test.dart +++ b/flutter/test/navigation/sentry_display_widget_test.dart @@ -62,7 +62,8 @@ void main() { start: getUtcDateTime().add(Duration(seconds: 1)), end: getUtcDateTime().add(Duration(seconds: 2)), pluginRegistration: getUtcDateTime().add(Duration(seconds: 3)), - mainIsolateStart: getUtcDateTime().add(Duration(seconds: 4)), + sentrySetupStart: getUtcDateTime().add(Duration(seconds: 4)), + nativeSpanTimes: [], ); NativeAppStartIntegration.setAppStartInfo(appStartInfo); diff --git a/flutter/test/sentry_native_channel_test.dart b/flutter/test/sentry_native_channel_test.dart index 4d5e539838..a8debae3e4 100644 --- a/flutter/test/sentry_native_channel_test.dart +++ b/flutter/test/sentry_native_channel_test.dart @@ -23,6 +23,8 @@ void main() { 'pluginRegistrationTime': 1, 'appStartTime': 0.1, 'isColdStart': true, + // ignore: inference_failure_on_collection_literal + 'nativeSpanTimes': {}, }; final future = Future.value(map); diff --git a/flutter/test/sentry_native_test.dart b/flutter/test/sentry_native_test.dart index 341c8aaad8..92b7c2e28e 100644 --- a/flutter/test/sentry_native_test.dart +++ b/flutter/test/sentry_native_test.dart @@ -1,5 +1,4 @@ @TestOn('vm') - import 'package:flutter_test/flutter_test.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:sentry_flutter/src/native/sentry_native.dart'; @@ -17,7 +16,10 @@ void main() { test('fetchNativeAppStart sets didFetchAppStart', () async { final nativeAppStart = NativeAppStart( - appStartTime: 0.0, pluginRegistrationTime: 10, isColdStart: true); + appStartTime: 0.0, + pluginRegistrationTime: 10, + isColdStart: true, + nativeSpanTimes: {}); channel.nativeAppStart = nativeAppStart; expect(sut.didFetchAppStart, false); diff --git a/flutter/test/sentry_navigator_observer_test.dart b/flutter/test/sentry_navigator_observer_test.dart index 94ce9e6107..e2b1488cca 100644 --- a/flutter/test/sentry_navigator_observer_test.dart +++ b/flutter/test/sentry_navigator_observer_test.dart @@ -502,7 +502,8 @@ void main() { start: DateTime.now().add(const Duration(seconds: 1)), end: DateTime.now().add(const Duration(seconds: 2)), pluginRegistration: DateTime.now().add(const Duration(seconds: 3)), - mainIsolateStart: DateTime.now().add(const Duration(seconds: 4)), + sentrySetupStart: DateTime.now().add(const Duration(seconds: 4)), + nativeSpanTimes: [], ), ); From 40e30e1a596c57faa68f4604affd726b8ca005ea Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Fri, 10 May 2024 12:30:43 +0200 Subject: [PATCH 173/237] App start: Create transaction when no `SentryNavigatorObserver` is present (#2017) * commit * Update * Remove print * Remove comments * Update * Add linting * Update CHANGELOG * Update CHANGELOG.md * Update naming * Update naming * Update naming * Create transaction * Update description from first frame render to initial frame render * Update * update * dart format * Update comments * Update * Update * Update * Update * Update * Fix tests * Fix test * Add unused import * Update * Update * Updat * Fix tests * Fix tests * Fix analyze * Update * Update * Updaet * Update * Add additional flag and update comment --- CHANGELOG.md | 1 + .../native_app_start_integration.dart | 27 +++++++++++++++++-- .../navigation/sentry_navigator_observer.dart | 11 +++++++- .../native_app_start_integration_test.dart | 13 +++++++++ 4 files changed, 49 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3de2f68fae..03c8908480 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ ### Features +- Create app start transaction when no `SentryNavigatorObserver` is present ([#2017](https://github.com/getsentry/sentry-dart/pull/2017)) - Adds native spans to app start transaction ([#2027](https://github.com/getsentry/sentry-dart/pull/2027)) - Adds app start spans to first transaction ([#2009](https://github.com/getsentry/sentry-dart/pull/2009)) diff --git a/flutter/lib/src/integrations/native_app_start_integration.dart b/flutter/lib/src/integrations/native_app_start_integration.dart index 13ca865422..616042406a 100644 --- a/flutter/lib/src/integrations/native_app_start_integration.dart +++ b/flutter/lib/src/integrations/native_app_start_integration.dart @@ -1,3 +1,5 @@ +// ignore_for_file: invalid_use_of_internal_member + import 'dart:async'; import 'package:meta/meta.dart'; @@ -96,7 +98,6 @@ class NativeAppStartIntegration extends Integration { if (options.autoAppStart) { // We only assign the current time if it's not already set - this is useful in tests - // ignore: invalid_use_of_internal_member _native.appStartEnd ??= options.clock(); appStartEndDateTime = _native.appStartEnd; @@ -129,7 +130,6 @@ class NativeAppStartIntegration extends Integration { description: entry.key as String, )); } catch (e) { - // ignore: invalid_use_of_internal_member _hub.options.logger( SentryLevel.warning, 'Failed to parse native span times: $e'); continue; @@ -149,6 +149,29 @@ class NativeAppStartIntegration extends Integration { nativeSpanTimes: nativeSpanTimes); setAppStartInfo(appStartInfo); + + // When we don't have a SentryNavigatorObserver, a TTID transaction + // is not created therefore we need to create a transaction ourselves. + // We detect this by checking if the currentRouteName is null. + // This is a workaround since there is no api that tells us if + // the navigator observer exists and has been attached. + // The navigator observer also triggers much earlier so if it was attached + // it would have already set the routeName and the isCreated flag. + // The currentRouteName is always set during a didPush triggered + // by the navigator observer. + if (!SentryNavigatorObserver.isCreated && + SentryNavigatorObserver.currentRouteName == null) { + const screenName = SentryNavigatorObserver.rootScreenName; + final transaction = hub.startTransaction( + screenName, SentrySpanOperations.uiLoad, + startTimestamp: appStartInfo.start); + final ttidSpan = transaction.startChild( + SentrySpanOperations.uiTimeToInitialDisplay, + description: '$screenName initial display', + startTimestamp: appStartInfo.start); + await ttidSpan.finish(endTimestamp: appStartInfo.end); + await transaction.finish(endTimestamp: appStartInfo.end); + } }); options.addEventProcessor(NativeAppStartEventProcessor(_native, hub: hub)); diff --git a/flutter/lib/src/navigation/sentry_navigator_observer.dart b/flutter/lib/src/navigation/sentry_navigator_observer.dart index aaa4c86889..fbfc12b6ee 100644 --- a/flutter/lib/src/navigation/sentry_navigator_observer.dart +++ b/flutter/lib/src/navigation/sentry_navigator_observer.dart @@ -86,6 +86,7 @@ class SentryNavigatorObserver extends RouteObserver> { _routeNameExtractor = routeNameExtractor, _additionalInfoProvider = additionalInfoProvider, _native = SentryFlutter.native { + _isCreated = true; if (enableAutoTransactions) { _hub.options.sdk.addIntegration('UINavigationTracing'); } @@ -121,6 +122,11 @@ class SentryNavigatorObserver extends RouteObserver> { static String? _currentRouteName; + static bool _isCreated = false; + + @internal + static bool get isCreated => _isCreated; + @internal static String? get currentRouteName => _currentRouteName; @@ -224,7 +230,7 @@ class SentryNavigatorObserver extends RouteObserver> { } if (name == '/') { - name = 'root /'; + name = rootScreenName; } final transactionContext = SentryTransactionContext( name, @@ -366,6 +372,9 @@ class SentryNavigatorObserver extends RouteObserver> { _completedDisplayTracking = Completer(); _timeToDisplayTracker?.clear(); } + + @internal + static const String rootScreenName = 'root /'; } /// This class makes it easier to record breadcrumbs for events of Flutters diff --git a/flutter/test/integrations/native_app_start_integration_test.dart b/flutter/test/integrations/native_app_start_integration_test.dart index ce555ceb9d..30cf621208 100644 --- a/flutter/test/integrations/native_app_start_integration_test.dart +++ b/flutter/test/integrations/native_app_start_integration_test.dart @@ -12,6 +12,16 @@ import '../mocks.dart'; import '../mocks.mocks.dart'; void main() { + void setupMocks(Fixture fixture) { + when(fixture.hub.startTransaction('root /', 'ui.load', + description: null, startTimestamp: anyNamed('startTimestamp'))) + .thenReturn(fixture.createTracer()); + when(fixture.hub.configureScope(captureAny)).thenAnswer((_) {}); + when(fixture.hub + .captureTransaction(any, traceContext: anyNamed('traceContext'))) + .thenAnswer((_) async => SentryId.empty()); + } + group('$NativeAppStartIntegration', () { late Fixture fixture; @@ -19,6 +29,8 @@ void main() { TestWidgetsFlutterBinding.ensureInitialized(); fixture = Fixture(); + setupMocks(fixture); + NativeAppStartIntegration.clearAppStartInfo(); }); @@ -257,6 +269,7 @@ void main() { SentryFlutter.sentrySetupStartTime = DateTime.fromMillisecondsSinceEpoch(15); + setupMocks(fixture); fixture.getNativeAppStartIntegration().call(fixture.hub, fixture.options); final processor = fixture.options.eventProcessors.first; From c57d3b7956abee03da2c5de84db3bb813744e511 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 10 May 2024 12:36:49 +0200 Subject: [PATCH 174/237] chore(deps): update Cocoa SDK to v8.25.2 (#2042) * chore: update flutter/scripts/update-cocoa.sh to 8.25.2 * Format --------- Co-authored-by: GitHub Co-authored-by: GIancarlo Buenaflor --- CHANGELOG.md | 6 ++++++ flutter/ios/sentry_flutter.podspec | 2 +- flutter/lib/src/native/cocoa/binding.dart | 7 +++++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 03c8908480..955b09850c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,12 @@ - Fix `PlatformException` title parsing ([#2033](https://github.com/getsentry/sentry-dart/pull/2033)) +### Dependencies + +- Bump Cocoa SDK from v8.25.0 to v8.25.2 ([#2042](https://github.com/getsentry/sentry-dart/pull/2042)) + - [changelog](https://github.com/getsentry/sentry-cocoa/blob/main/CHANGELOG.md#8252) + - [diff](https://github.com/getsentry/sentry-cocoa/compare/8.25.0...8.25.2) + ## 8.1.0 ### Features diff --git a/flutter/ios/sentry_flutter.podspec b/flutter/ios/sentry_flutter.podspec index f8085d3b35..8a27b639ca 100644 --- a/flutter/ios/sentry_flutter.podspec +++ b/flutter/ios/sentry_flutter.podspec @@ -16,7 +16,7 @@ Sentry SDK for Flutter with support to native through sentry-cocoa. :tag => s.version.to_s } s.source_files = 'Classes/**/*' s.public_header_files = 'Classes/**/*.h' - s.dependency 'Sentry/HybridSDK', '8.25.0' + s.dependency 'Sentry/HybridSDK', '8.25.2' s.ios.dependency 'Flutter' s.osx.dependency 'FlutterMacOS' s.ios.deployment_target = '12.0' diff --git a/flutter/lib/src/native/cocoa/binding.dart b/flutter/lib/src/native/cocoa/binding.dart index 51a645754b..b6667b174b 100644 --- a/flutter/lib/src/native/cocoa/binding.dart +++ b/flutter/lib/src/native/cocoa/binding.dart @@ -22996,6 +22996,8 @@ class SentryCocoa { _registerName1("prefersIncrementalDelivery"); late final _sel_setPrefersIncrementalDelivery_1 = _registerName1("setPrefersIncrementalDelivery:"); + late final _sel_getGraphQLOperationName1 = + _registerName1("getGraphQLOperationName"); late final _sel_storeCookies_forTask_1 = _registerName1("storeCookies:forTask:"); void _objc_msgSend_804( @@ -58358,6 +58360,11 @@ class NSURLSessionTask extends NSObject { return NSURLSessionTask._(_ret, _lib, retain: false, release: true); } + NSString getGraphQLOperationName() { + final _ret = _lib._objc_msgSend_20(_id, _lib._sel_getGraphQLOperationName1); + return NSString._(_ret, _lib, retain: true, release: true); + } + static NSURLSessionTask allocWithZone_( SentryCocoa _lib, ffi.Pointer<_NSZone> zone) { final _ret = _lib._objc_msgSend_3( From 3fae5532730b1f5b0615d009e40df8b41a49241a Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Fri, 10 May 2024 12:44:55 +0200 Subject: [PATCH 175/237] ci: fix codecov action (#2046) * Add codecov token * Update flutter.yml --- .github/workflows/flutter.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/flutter.yml b/.github/workflows/flutter.yml index 7940dc8a1a..f38bb81c07 100644 --- a/.github/workflows/flutter.yml +++ b/.github/workflows/flutter.yml @@ -112,6 +112,7 @@ jobs: name: sentry_flutter file: ./flutter/coverage/lcov.info functionalities: "search" # remove after https://github.com/codecov/codecov-action/issues/600 + token: ${{ secrets.CODECOV_TOKEN }} - uses: VeryGoodOpenSource/very_good_coverage@c953fca3e24a915e111cc6f55f03f756dcb3964c # pin@v3.0.0 if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' From 4fe92c5f380a34d85aa4240a48542294a580e805 Mon Sep 17 00:00:00 2001 From: Ivan Dlugos <6349682+vaind@users.noreply.github.com> Date: Fri, 10 May 2024 17:19:03 +0200 Subject: [PATCH 176/237] ci: cleanup flutter matrix (#2044) * ci: cleanup flutter matrix * flip the matrix * don't run vm tests when building android & web --- .github/workflows/flutter.yml | 85 +++++++++++++++-------------------- 1 file changed, 35 insertions(+), 50 deletions(-) diff --git a/.github/workflows/flutter.yml b/.github/workflows/flutter.yml index f38bb81c07..518ada1ca2 100644 --- a/.github/workflows/flutter.yml +++ b/.github/workflows/flutter.yml @@ -6,12 +6,12 @@ on: - release/** pull_request: paths: - - ".github/workflows/flutter.yml" - - "!**/*.md" - - "!**/class-diagram.svg" - - "dart/**" - - "flutter/**" - - "metrics/flutter.properties" + - '.github/workflows/flutter.yml' + - '!**/*.md' + - '!**/class-diagram.svg' + - 'dart/**' + - 'flutter/**' + - 'metrics/flutter.properties' jobs: cancel-previous-workflow: @@ -23,8 +23,8 @@ jobs: access_token: ${{ github.token }} build: - name: "${{ matrix.target }} | ${{ matrix.os }} | ${{ matrix.sdk }}" - runs-on: ${{ matrix.os }} + name: '${{ matrix.target }} | ${{ matrix.os }} | ${{ matrix.sdk }}' + runs-on: ${{ matrix.os }}-latest timeout-minutes: 30 defaults: run: @@ -32,38 +32,22 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest, windows-latest, macos-latest] - target: ["ios", "android", "web", "macos", "linux", "windows"] - sdk: ["stable", "beta"] - exclude: - - os: ubuntu-latest - target: ios - - os: ubuntu-latest - target: macos - - os: ubuntu-latest - target: windows - - os: windows-latest - target: ios - - os: windows-latest - target: android - - os: windows-latest - target: web - - os: windows-latest - target: macos - - os: windows-latest - target: linux - # macos-latest is taking hours due to limited resources - - os: macos-latest - target: android - - os: macos-latest - target: web - - os: macos-latest - target: linux - - os: macos-latest - target: windows - # Bad CPU type in executable - - os: macos-latest - sdk: beta + target: [android, ios, macos, linux, windows, web] + sdk: [stable, beta] + # Specify which platform to run on for each target: + include: + - target: android + os: ubuntu + - target: ios + os: macos + - target: macos + os: macos + - target: linux + os: ubuntu + - target: windows + os: windows + - target: web + os: ubuntu steps: - uses: actions/checkout@v4 @@ -71,16 +55,16 @@ jobs: - uses: actions/setup-java@v4 if: ${{ matrix.target == 'android' }} with: - java-version: "11" - distribution: "adopt" + java-version: '11' + distribution: 'adopt' # Install required dependencies for Flutter on Linux on Ubuntu - - name: "Setup Linux" + - name: 'Setup Linux' run: | sudo apt update sudo apt install -y cmake dbus libblkid-dev libgtk-3-dev liblzma-dev ninja-build pkg-config xvfb sudo apt install -y network-manager upower - if: matrix.os == 'ubuntu-latest' && matrix.target == 'linux' + if: matrix.target == 'linux' - uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 # pin@v2.16.0 with: @@ -94,20 +78,21 @@ jobs: flutter pub get - name: Test chrome - if: runner.os == 'Linux' + if: matrix.target == 'web' run: | cd flutter flutter test --platform chrome --test-randomize-ordering-seed=random --exclude-tags canvasKit - flutter test --platform chrome --test-randomize-ordering-seed=random --tags canvasKit --web-renderer canvaskit + flutter test --platform chrome --test-randomize-ordering-seed=random --tags canvasKit --web-renderer canvaskit - name: Test VM with coverage + if: matrix.target == 'linux' || matrix.target == 'macos' || matrix.target == 'windows' run: | cd flutter flutter test --coverage --test-randomize-ordering-seed=random dart run remove_from_coverage -f coverage/lcov.info -r 'binding.dart' - uses: codecov/codecov-action@5ecb98a3c6b747ed38dc09f787459979aebb39be # pin@v3 - if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' + if: matrix.sdk == 'stable' && matrix.target == 'linux' with: name: sentry_flutter file: ./flutter/coverage/lcov.info @@ -115,11 +100,11 @@ jobs: token: ${{ secrets.CODECOV_TOKEN }} - uses: VeryGoodOpenSource/very_good_coverage@c953fca3e24a915e111cc6f55f03f756dcb3964c # pin@v3.0.0 - if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' + if: matrix.sdk == 'stable' && matrix.target == 'linux' with: - path: "./flutter/coverage/lcov.info" + path: './flutter/coverage/lcov.info' min_coverage: 90 - exclude: "lib/src/native/cocoa/binding.dart" + exclude: 'lib/src/native/cocoa/binding.dart' - name: Build ${{ matrix.target }} run: | From 0f067d38500c0ab6b9e85d0b19690ba915d4fea1 Mon Sep 17 00:00:00 2001 From: Ivan Dlugos <6349682+vaind@users.noreply.github.com> Date: Sun, 12 May 2024 12:25:21 +0200 Subject: [PATCH 177/237] fixup update-android.sh (#2047) this line got here by accident from another pR --- flutter/scripts/update-android.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/flutter/scripts/update-android.sh b/flutter/scripts/update-android.sh index 60775a6eec..fc1f3460bd 100755 --- a/flutter/scripts/update-android.sh +++ b/flutter/scripts/update-android.sh @@ -20,7 +20,6 @@ get-repo) set-version) newValue="${BASH_REMATCH[1]}$2" echo "${content/${BASH_REMATCH[0]}/$newValue}" >$file - ../scripts/generate-android-bindings.sh "$2" ;; *) echo "Unknown argument $1" From 20eb554294de27e7690cab5f47ae4a44b246b29d Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Mon, 13 May 2024 15:02:20 +0200 Subject: [PATCH 178/237] Include sentry frames to enable crash detection (#2050) * Updaet * Add test * Update test * UpdatE * Add changelog * Fix analyze * Update test --- CHANGELOG.md | 4 ++++ dart/lib/src/sentry_stack_trace_factory.dart | 20 ++-------------- dart/test/sentry_client_test.dart | 25 +++++++++++++------- dart/test/stack_trace_test.dart | 5 ---- 4 files changed, 22 insertions(+), 32 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 955b09850c..54862f9474 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Enhancements + +- Include sentry frames in stacktraces to enable SDK crash detection ([#2050](https://github.com/getsentry/sentry-dart/pull/2050)) + ### Fixes - Event processor blocking transactions from being sent if `autoAppStart` is false ([#2028](https://github.com/getsentry/sentry-dart/pull/2028)) diff --git a/dart/lib/src/sentry_stack_trace_factory.dart b/dart/lib/src/sentry_stack_trace_factory.dart index b7f0504bb9..9d4a42bffc 100644 --- a/dart/lib/src/sentry_stack_trace_factory.dart +++ b/dart/lib/src/sentry_stack_trace_factory.dart @@ -15,18 +15,6 @@ class SentryStackTraceFactory { static final SentryStackFrame _asynchronousGapFrameJson = SentryStackFrame(absPath: ''); - static const _sentryPackagesIdentifier = [ - 'sentry', - 'sentry_flutter', - 'sentry_logging', - 'sentry_dio', - 'sentry_file', - 'sentry_hive', - 'sentry_isar', - 'sentry_sqflite', - 'sentry_drift', - ]; - SentryStackTraceFactory(this._options); /// returns the [SentryStackFrame] list from a stackTrace ([StackTrace] or [String]) @@ -38,13 +26,9 @@ class SentryStackTraceFactory { for (var t = 0; t < chain.traces.length; t += 1) { final trace = chain.traces[t]; + // NOTE: We want to keep the Sentry frames for crash detection + // this does not affect grouping since they're not marked as inApp for (final frame in trace.frames) { - // we don't want to add our own frames - if (frame.package != null && - _sentryPackagesIdentifier.contains(frame.package)) { - continue; - } - final stackTraceFrame = encodeStackTraceFrame(frame); if (stackTraceFrame != null) { frames.add(stackTraceFrame); diff --git a/dart/test/sentry_client_test.dart b/dart/test/sentry_client_test.dart index 89a5620acc..b10ae154f7 100644 --- a/dart/test/sentry_client_test.dart +++ b/dart/test/sentry_client_test.dart @@ -374,7 +374,7 @@ void main() { expect(capturedEvent.exceptions?[1].stackTrace, isNotNull); }); - test('should not capture sentry frames exception', () async { + test('should capture sentry frames exception', () async { fixture.options.addExceptionCauseExtractor( ExceptionWithCauseExtractor(), ); @@ -394,11 +394,11 @@ void main() { final capturedEnvelope = (fixture.transport).envelopes.first; final capturedEvent = await eventFromEnvelope(capturedEnvelope); - expect( - capturedEvent.exceptions?[1].stackTrace!.frames - .every((frame) => frame.package != 'sentry'), - true, - ); + final sentryFramesCount = capturedEvent.exceptions?[1].stackTrace!.frames + .where((frame) => frame.package == 'sentry') + .length; + + expect(sentryFramesCount, 2); }); }); @@ -494,22 +494,29 @@ void main() { expect(capturedEvent.exceptions?.first.stackTrace, isNull); }); - test('should not capture sentry frames exception', () async { + test('should capture sentry frames exception', () async { try { throw Exception('Error'); } catch (err) { exception = err; } + final stackTrace = ''' +#0 baz (file:///pathto/test.dart:50:3) + +#1 bar (file:///pathto/test.dart:46:9) +#2 capture (package:sentry/sentry.dart:46:9) + '''; + final client = fixture.getSut(); - await client.captureException(exception, stackTrace: stacktrace); + await client.captureException(exception, stackTrace: stackTrace); final capturedEnvelope = (fixture.transport).envelopes.first; final capturedEvent = await eventFromEnvelope(capturedEnvelope); expect( capturedEvent.exceptions?.first.stackTrace!.frames - .every((frame) => frame.package != 'sentry'), + .any((frame) => frame.package == 'sentry'), true, ); }); diff --git a/dart/test/stack_trace_test.dart b/dart/test/stack_trace_test.dart index 2bcf92c2c8..6524581794 100644 --- a/dart/test/stack_trace_test.dart +++ b/dart/test/stack_trace_test.dart @@ -254,11 +254,6 @@ isolate_instructions: 10fa27070, vm_instructions: 10fa21e20 final frames = Fixture() .getSut(considerInAppFramesByDefault: true) .getStackFrames(StackTrace.fromString(''' -#0 SentryClient._prepareEvent (package:sentry/src/sentry_client.dart:206:33) -#1 SentryClient.captureEvent (package:sentry/src/sentry_client.dart:74:34) -#2 Hub.captureEvent (package:sentry/src/hub.dart:97:38) - -#3 LoggingIntegration._onLog (package:sentry_logging/src/logging_integration.dart:58:7) ''')) .map((frame) => frame.toJson()); From 2a0edbaed1f13657658cda07ae7b9135fa37d745 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 13 May 2024 15:02:42 +0200 Subject: [PATCH 179/237] chore: update flutter/scripts/update-android.sh to 7.9.0 (#2049) Co-authored-by: GitHub --- CHANGELOG.md | 3 +++ flutter/android/build.gradle | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 54862f9474..26e43f6389 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,9 @@ - Bump Cocoa SDK from v8.25.0 to v8.25.2 ([#2042](https://github.com/getsentry/sentry-dart/pull/2042)) - [changelog](https://github.com/getsentry/sentry-cocoa/blob/main/CHANGELOG.md#8252) - [diff](https://github.com/getsentry/sentry-cocoa/compare/8.25.0...8.25.2) +- Bump Android SDK from v7.8.0 to v7.9.0 ([#2049](https://github.com/getsentry/sentry-dart/pull/2049)) + - [changelog](https://github.com/getsentry/sentry-java/blob/main/CHANGELOG.md#790) + - [diff](https://github.com/getsentry/sentry-java/compare/7.8.0...7.9.0) ## 8.1.0 diff --git a/flutter/android/build.gradle b/flutter/android/build.gradle index 1fa9b4f6c9..eb9411b783 100644 --- a/flutter/android/build.gradle +++ b/flutter/android/build.gradle @@ -60,7 +60,7 @@ android { } dependencies { - api 'io.sentry:sentry-android:7.8.0' + api 'io.sentry:sentry-android:7.9.0' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" // Required -- JUnit 4 framework From 92bcd807c01e59340e53efd8d5d45b720fa84044 Mon Sep 17 00:00:00 2001 From: getsentry-bot Date: Mon, 13 May 2024 15:27:44 +0000 Subject: [PATCH 180/237] release: 8.2.0 --- CHANGELOG.md | 2 +- dart/lib/src/version.dart | 2 +- dart/pubspec.yaml | 2 +- dio/lib/src/version.dart | 2 +- dio/pubspec.yaml | 4 ++-- drift/lib/src/version.dart | 2 +- drift/pubspec.yaml | 4 ++-- file/lib/src/version.dart | 2 +- file/pubspec.yaml | 4 ++-- flutter/example/pubspec.yaml | 2 +- flutter/lib/src/version.dart | 2 +- flutter/pubspec.yaml | 4 ++-- hive/lib/src/version.dart | 2 +- hive/pubspec.yaml | 4 ++-- isar/lib/src/version.dart | 2 +- isar/pubspec.yaml | 4 ++-- logging/lib/src/version.dart | 2 +- logging/pubspec.yaml | 4 ++-- sqflite/lib/src/version.dart | 2 +- sqflite/pubspec.yaml | 4 ++-- 20 files changed, 28 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 26e43f6389..9ef7608a29 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## Unreleased +## 8.2.0 ### Enhancements diff --git a/dart/lib/src/version.dart b/dart/lib/src/version.dart index 398b593f20..0b1968ecd0 100644 --- a/dart/lib/src/version.dart +++ b/dart/lib/src/version.dart @@ -9,7 +9,7 @@ library version; /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.1.0'; +const String sdkVersion = '8.2.0'; String sdkName(bool isWeb) => isWeb ? _browserSdkName : _ioSdkName; diff --git a/dart/pubspec.yaml b/dart/pubspec.yaml index 8dff6e892f..ebb883c308 100644 --- a/dart/pubspec.yaml +++ b/dart/pubspec.yaml @@ -1,5 +1,5 @@ name: sentry -version: 8.1.0 +version: 8.2.0 description: > A crash reporting library for Dart that sends crash reports to Sentry.io. This library supports Dart VM and Web. For Flutter consider sentry_flutter instead. diff --git a/dio/lib/src/version.dart b/dio/lib/src/version.dart index 927f78c9b7..b8d675e478 100644 --- a/dio/lib/src/version.dart +++ b/dio/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.1.0'; +const String sdkVersion = '8.2.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_dio'; diff --git a/dio/pubspec.yaml b/dio/pubspec.yaml index 4afea3a748..9c0c4b31a1 100644 --- a/dio/pubspec.yaml +++ b/dio/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_dio description: An integration which adds support for performance tracing for the Dio package. -version: 8.1.0 +version: 8.2.0 homepage: https://docs.sentry.io/platforms/dart/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -19,7 +19,7 @@ platforms: dependencies: dio: ^5.0.0 - sentry: 8.1.0 + sentry: 8.2.0 dev_dependencies: meta: ^1.3.0 diff --git a/drift/lib/src/version.dart b/drift/lib/src/version.dart index d34cbbe2af..9b290b4910 100644 --- a/drift/lib/src/version.dart +++ b/drift/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.1.0'; +const String sdkVersion = '8.2.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_drift'; diff --git a/drift/pubspec.yaml b/drift/pubspec.yaml index 076dc8be56..85ab6b8e0a 100644 --- a/drift/pubspec.yaml +++ b/drift/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_drift description: An integration which adds support for performance tracing for the drift package. -version: 8.1.0 +version: 8.2.0 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -17,7 +17,7 @@ platforms: web: dependencies: - sentry: 8.1.0 + sentry: 8.2.0 meta: ^1.3.0 drift: ^2.13.0 diff --git a/file/lib/src/version.dart b/file/lib/src/version.dart index 038a27750a..23dc032f51 100644 --- a/file/lib/src/version.dart +++ b/file/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.1.0'; +const String sdkVersion = '8.2.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_file'; diff --git a/file/pubspec.yaml b/file/pubspec.yaml index 60336b723e..9c0964cd80 100644 --- a/file/pubspec.yaml +++ b/file/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_file description: An integration which adds support for performance tracing for dart.io.File. -version: 8.1.0 +version: 8.2.0 homepage: https://docs.sentry.io/platforms/dart/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -17,7 +17,7 @@ platforms: windows: dependencies: - sentry: 8.1.0 + sentry: 8.2.0 meta: ^1.3.0 dev_dependencies: diff --git a/flutter/example/pubspec.yaml b/flutter/example/pubspec.yaml index 46b0031191..9ddeb4d1ad 100644 --- a/flutter/example/pubspec.yaml +++ b/flutter/example/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_flutter_example description: Demonstrates how to use the sentry_flutter plugin. -version: 8.1.0 +version: 8.2.0 publish_to: 'none' # Remove this line if you wish to publish to pub.dev diff --git a/flutter/lib/src/version.dart b/flutter/lib/src/version.dart index f050668b3d..b7453f867b 100644 --- a/flutter/lib/src/version.dart +++ b/flutter/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.1.0'; +const String sdkVersion = '8.2.0'; /// The default SDK name reported to Sentry.io in the submitted events. const String sdkName = 'sentry.dart.flutter'; diff --git a/flutter/pubspec.yaml b/flutter/pubspec.yaml index ada7c12aeb..ba6c34329c 100644 --- a/flutter/pubspec.yaml +++ b/flutter/pubspec.yaml @@ -1,5 +1,5 @@ name: sentry_flutter -version: 8.1.0 +version: 8.2.0 description: Sentry SDK for Flutter. This package aims to support different Flutter targets by relying on the many platforms supported by Sentry with native SDKs. homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart @@ -23,7 +23,7 @@ dependencies: sdk: flutter flutter_web_plugins: sdk: flutter - sentry: 8.1.0 + sentry: 8.2.0 package_info_plus: '>=1.0.0' meta: ^1.3.0 ffi: ^2.0.0 diff --git a/hive/lib/src/version.dart b/hive/lib/src/version.dart index ed1edf60f3..2bdc6f7804 100644 --- a/hive/lib/src/version.dart +++ b/hive/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.1.0'; +const String sdkVersion = '8.2.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_hive'; diff --git a/hive/pubspec.yaml b/hive/pubspec.yaml index 23473bf73f..0e982afe9c 100644 --- a/hive/pubspec.yaml +++ b/hive/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_hive description: An integration which adds support for performance tracing for the hive package. -version: 8.1.0 +version: 8.2.0 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -17,7 +17,7 @@ platforms: web: dependencies: - sentry: 8.1.0 + sentry: 8.2.0 hive: ^2.2.3 meta: ^1.3.0 diff --git a/isar/lib/src/version.dart b/isar/lib/src/version.dart index 9aa858df6f..6c11fd4a2f 100644 --- a/isar/lib/src/version.dart +++ b/isar/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.1.0'; +const String sdkVersion = '8.2.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_isar'; diff --git a/isar/pubspec.yaml b/isar/pubspec.yaml index 73b9343d39..b4beb15f59 100644 --- a/isar/pubspec.yaml +++ b/isar/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_isar description: An integration which adds support for performance tracing for the isar package. -version: 8.1.0 +version: 8.2.0 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -20,7 +20,7 @@ platforms: dependencies: isar: ^3.1.0 isar_flutter_libs: ^3.1.0 # contains Isar Core - sentry: 8.1.0 + sentry: 8.2.0 meta: ^1.3.0 path: ^1.8.3 diff --git a/logging/lib/src/version.dart b/logging/lib/src/version.dart index 5f31854913..77c049abc8 100644 --- a/logging/lib/src/version.dart +++ b/logging/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.1.0'; +const String sdkVersion = '8.2.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_logging'; diff --git a/logging/pubspec.yaml b/logging/pubspec.yaml index 4ee561b50b..235e0900f9 100644 --- a/logging/pubspec.yaml +++ b/logging/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_logging description: An integration which adds support for recording log from the logging package. -version: 8.1.0 +version: 8.2.0 homepage: https://docs.sentry.io/platforms/dart/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -19,7 +19,7 @@ platforms: dependencies: logging: ^1.0.0 - sentry: 8.1.0 + sentry: 8.2.0 dev_dependencies: lints: ^3.0.0 diff --git a/sqflite/lib/src/version.dart b/sqflite/lib/src/version.dart index 81f041236f..418ce72aad 100644 --- a/sqflite/lib/src/version.dart +++ b/sqflite/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.1.0'; +const String sdkVersion = '8.2.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_sqflite'; diff --git a/sqflite/pubspec.yaml b/sqflite/pubspec.yaml index 3146f483b1..a80b04a90b 100644 --- a/sqflite/pubspec.yaml +++ b/sqflite/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_sqflite description: An integration which adds support for performance tracing for the sqflite package. -version: 8.1.0 +version: 8.2.0 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -15,7 +15,7 @@ platforms: macos: dependencies: - sentry: 8.1.0 + sentry: 8.2.0 sqflite: ^2.0.0 sqflite_common: ^2.0.0 meta: ^1.3.0 From f2c5944c08ff4a0503b0f6728fdaa2f28987a323 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 May 2024 16:55:19 +0200 Subject: [PATCH 181/237] build(deps): bump codecov/codecov-action from 4.3.1 to 4.4.1 (#2065) Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 4.3.1 to 4.4.1. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/5ecb98a3c6b747ed38dc09f787459979aebb39be...125fc84a9a348dbcf27191600683ec096ec9021c) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/dart.yml | 2 +- .github/workflows/dio.yml | 2 +- .github/workflows/drift.yml | 2 +- .github/workflows/file.yml | 2 +- .github/workflows/flutter.yml | 2 +- .github/workflows/hive.yml | 2 +- .github/workflows/isar.yml | 2 +- .github/workflows/logging.yml | 2 +- .github/workflows/sqflite.yml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml index 09365adcfe..094707c5a8 100644 --- a/.github/workflows/dart.yml +++ b/.github/workflows/dart.yml @@ -68,7 +68,7 @@ jobs: dart pub get webdev build - - uses: codecov/codecov-action@5ecb98a3c6b747ed38dc09f787459979aebb39be # pin@v3 + - uses: codecov/codecov-action@125fc84a9a348dbcf27191600683ec096ec9021c # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: name: sentry diff --git a/.github/workflows/dio.yml b/.github/workflows/dio.yml index e441deffea..85e88e7816 100644 --- a/.github/workflows/dio.yml +++ b/.github/workflows/dio.yml @@ -52,7 +52,7 @@ jobs: dart test -p vm --coverage=coverage --test-randomize-ordering-seed=random --chain-stack-traces dart pub run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.dart_tool/package_config.json --report-on=lib - - uses: codecov/codecov-action@5ecb98a3c6b747ed38dc09f787459979aebb39be # pin@v3 + - uses: codecov/codecov-action@125fc84a9a348dbcf27191600683ec096ec9021c # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: name: sentry_dio diff --git a/.github/workflows/drift.yml b/.github/workflows/drift.yml index 198806fbf1..d728800cae 100644 --- a/.github/workflows/drift.yml +++ b/.github/workflows/drift.yml @@ -93,7 +93,7 @@ jobs: cd drift flutter test --coverage --test-randomize-ordering-seed=random - - uses: codecov/codecov-action@5ecb98a3c6b747ed38dc09f787459979aebb39be # pin@v3 + - uses: codecov/codecov-action@125fc84a9a348dbcf27191600683ec096ec9021c # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' with: name: sentry_drift diff --git a/.github/workflows/file.yml b/.github/workflows/file.yml index d59b127a9d..3f7e9986a5 100644 --- a/.github/workflows/file.yml +++ b/.github/workflows/file.yml @@ -52,7 +52,7 @@ jobs: dart test -p vm --coverage=coverage --test-randomize-ordering-seed=random --chain-stack-traces dart pub run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.dart_tool/package_config.json --report-on=lib - - uses: codecov/codecov-action@5ecb98a3c6b747ed38dc09f787459979aebb39be # pin@v3 + - uses: codecov/codecov-action@125fc84a9a348dbcf27191600683ec096ec9021c # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: name: sentry_file diff --git a/.github/workflows/flutter.yml b/.github/workflows/flutter.yml index 518ada1ca2..e1ec093c2f 100644 --- a/.github/workflows/flutter.yml +++ b/.github/workflows/flutter.yml @@ -91,7 +91,7 @@ jobs: flutter test --coverage --test-randomize-ordering-seed=random dart run remove_from_coverage -f coverage/lcov.info -r 'binding.dart' - - uses: codecov/codecov-action@5ecb98a3c6b747ed38dc09f787459979aebb39be # pin@v3 + - uses: codecov/codecov-action@125fc84a9a348dbcf27191600683ec096ec9021c # pin@v3 if: matrix.sdk == 'stable' && matrix.target == 'linux' with: name: sentry_flutter diff --git a/.github/workflows/hive.yml b/.github/workflows/hive.yml index dcc483df81..ef58388bd2 100644 --- a/.github/workflows/hive.yml +++ b/.github/workflows/hive.yml @@ -51,7 +51,7 @@ jobs: dart test -p vm --coverage=coverage --test-randomize-ordering-seed=random --chain-stack-traces dart pub run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.dart_tool/package_config.json --report-on=lib - - uses: codecov/codecov-action@5ecb98a3c6b747ed38dc09f787459979aebb39be # pin@v3 + - uses: codecov/codecov-action@125fc84a9a348dbcf27191600683ec096ec9021c # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: name: sentry_hive diff --git a/.github/workflows/isar.yml b/.github/workflows/isar.yml index d2ba1d37e7..54d69b7a4c 100644 --- a/.github/workflows/isar.yml +++ b/.github/workflows/isar.yml @@ -93,7 +93,7 @@ jobs: cd isar flutter test -j 1 --coverage --test-randomize-ordering-seed=random - - uses: codecov/codecov-action@5ecb98a3c6b747ed38dc09f787459979aebb39be # pin@v3 + - uses: codecov/codecov-action@125fc84a9a348dbcf27191600683ec096ec9021c # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' with: name: sentry_isar diff --git a/.github/workflows/logging.yml b/.github/workflows/logging.yml index 5561719acb..1b004ad4a1 100644 --- a/.github/workflows/logging.yml +++ b/.github/workflows/logging.yml @@ -52,7 +52,7 @@ jobs: dart test -p vm --coverage=coverage --test-randomize-ordering-seed=random --chain-stack-traces dart pub run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.dart_tool/package_config.json --report-on=lib - - uses: codecov/codecov-action@5ecb98a3c6b747ed38dc09f787459979aebb39be # pin@v3 + - uses: codecov/codecov-action@125fc84a9a348dbcf27191600683ec096ec9021c # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: name: sentry_logging diff --git a/.github/workflows/sqflite.yml b/.github/workflows/sqflite.yml index 3e44664474..df44cac6d4 100644 --- a/.github/workflows/sqflite.yml +++ b/.github/workflows/sqflite.yml @@ -93,7 +93,7 @@ jobs: cd sqflite flutter test --coverage --test-randomize-ordering-seed=random - - uses: codecov/codecov-action@5ecb98a3c6b747ed38dc09f787459979aebb39be # pin@v3 + - uses: codecov/codecov-action@125fc84a9a348dbcf27191600683ec096ec9021c # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' with: name: sentry_sqflite From 7edff9bcf5f5722c922f95ef8a1e462fe8f6ad28 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 27 May 2024 16:55:57 +0200 Subject: [PATCH 182/237] chore(deps): update Cocoa SDK to v8.26.0 (#2060) * chore: update flutter/scripts/update-cocoa.sh to 8.26.0 * UpdatE --------- Co-authored-by: GitHub Co-authored-by: GIancarlo Buenaflor --- CHANGELOG.md | 8 ++++++++ flutter/ios/sentry_flutter.podspec | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ef7608a29..778d474a9f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## Unreleased + +### Dependencies + +- Bump Cocoa SDK from v8.25.2 to v8.26.0 ([#2060](https://github.com/getsentry/sentry-dart/pull/2060)) + - [changelog](https://github.com/getsentry/sentry-cocoa/blob/main/CHANGELOG.md#8260) + - [diff](https://github.com/getsentry/sentry-cocoa/compare/8.25.2...8.26.0) + ## 8.2.0 ### Enhancements diff --git a/flutter/ios/sentry_flutter.podspec b/flutter/ios/sentry_flutter.podspec index 8a27b639ca..5a37c01cf9 100644 --- a/flutter/ios/sentry_flutter.podspec +++ b/flutter/ios/sentry_flutter.podspec @@ -16,7 +16,7 @@ Sentry SDK for Flutter with support to native through sentry-cocoa. :tag => s.version.to_s } s.source_files = 'Classes/**/*' s.public_header_files = 'Classes/**/*.h' - s.dependency 'Sentry/HybridSDK', '8.25.2' + s.dependency 'Sentry/HybridSDK', '8.26.0' s.ios.dependency 'Flutter' s.osx.dependency 'FlutterMacOS' s.ios.deployment_target = '12.0' From b8562d01376a7efe9af802ab0abd9d8226eb4bd7 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 27 May 2024 16:56:18 +0200 Subject: [PATCH 183/237] chore: update metrics/flutter.properties to 3.22.0 (#2059) Co-authored-by: GitHub --- metrics/flutter.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/metrics/flutter.properties b/metrics/flutter.properties index 4bb0b5513e..8c5d1516b6 100644 --- a/metrics/flutter.properties +++ b/metrics/flutter.properties @@ -1,2 +1,2 @@ -version = 3.19.6 +version = 3.22.0 repo = https://github.com/flutter/flutter From be173fa4303b8b6dbd940568953214b4f5e60992 Mon Sep 17 00:00:00 2001 From: Philipp Hofmann Date: Tue, 28 May 2024 10:42:49 +0200 Subject: [PATCH 184/237] ref: Add getCurrentStackTrace (#2072) Add the wrapper method getCurrentStackTrace so the SDK crash detection can ignore it. --- dart/lib/src/sentry_client.dart | 3 ++- dart/lib/src/sentry_exception_factory.dart | 4 +++- dart/lib/src/utils/stacktrace_utils.dart | 10 ++++++++++ 3 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 dart/lib/src/utils/stacktrace_utils.dart diff --git a/dart/lib/src/sentry_client.dart b/dart/lib/src/sentry_client.dart index 59610993ad..a1f20ded61 100644 --- a/dart/lib/src/sentry_client.dart +++ b/dart/lib/src/sentry_client.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'dart:math'; import 'package:meta/meta.dart'; +import 'utils/stacktrace_utils.dart'; import 'metrics/metric.dart'; import 'metrics/metrics_aggregator.dart'; import 'sentry_baggage.dart'; @@ -235,7 +236,7 @@ class SentryClient { // therefore add it to the threads. // https://develop.sentry.dev/sdk/event-payloads/stacktrace/ if (stackTrace != null || _options.attachStacktrace) { - stackTrace ??= StackTrace.current; + stackTrace ??= getCurrentStackTrace(); final frames = _stackTraceFactory.getStackFrames(stackTrace); if (frames.isNotEmpty) { diff --git a/dart/lib/src/sentry_exception_factory.dart b/dart/lib/src/sentry_exception_factory.dart index 0e4eb25cc3..a8e1a80498 100644 --- a/dart/lib/src/sentry_exception_factory.dart +++ b/dart/lib/src/sentry_exception_factory.dart @@ -1,3 +1,5 @@ +import 'utils/stacktrace_utils.dart'; + import 'recursive_exception_cause_extractor.dart'; import 'protocol.dart'; import 'sentry_options.dart'; @@ -40,7 +42,7 @@ class SentryExceptionFactory { if (_options.attachStacktrace) { if (stackTrace == null || stackTrace == StackTrace.empty) { snapshot = true; - stackTrace = StackTrace.current; + stackTrace = getCurrentStackTrace(); } } diff --git a/dart/lib/src/utils/stacktrace_utils.dart b/dart/lib/src/utils/stacktrace_utils.dart new file mode 100644 index 0000000000..acc1cccf44 --- /dev/null +++ b/dart/lib/src/utils/stacktrace_utils.dart @@ -0,0 +1,10 @@ +import 'package:meta/meta.dart'; + +// A wrapper function around StackTrace.current so we can ignore it in the SDK +// crash detection. Otherwise, the SDK crash detection would have to ignore the +// method calling StackTrace.current, and it can't detect crashes in that +// method. +// You can read about the SDK crash detection here: +// https://github.com/getsentry/sentry/blob/master/src/sentry/utils/sdk_crashes/README.rst +@internal +StackTrace getCurrentStackTrace() => StackTrace.current; From e29d359634cf77ebfb11389d8b5f48a305a09200 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 28 May 2024 12:47:24 +0200 Subject: [PATCH 185/237] build(deps): bump reactivecircus/android-emulator-runner (#2071) Bumps [reactivecircus/android-emulator-runner](https://github.com/reactivecircus/android-emulator-runner) from 2.30.1 to 2.31.0. - [Release notes](https://github.com/reactivecircus/android-emulator-runner/releases) - [Changelog](https://github.com/ReactiveCircus/android-emulator-runner/blob/main/CHANGELOG.md) - [Commits](https://github.com/reactivecircus/android-emulator-runner/compare/6b0df4b0efb23bb0ec63d881db79aefbc976e4b2...77986be26589807b8ebab3fde7bbf5c60dabec32) --- updated-dependencies: - dependency-name: reactivecircus/android-emulator-runner dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/flutter_integration_test.yml | 4 ++-- .github/workflows/flutter_test.yml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/flutter_integration_test.yml b/.github/workflows/flutter_integration_test.yml index 162c52b5e6..b396b4f809 100644 --- a/.github/workflows/flutter_integration_test.yml +++ b/.github/workflows/flutter_integration_test.yml @@ -62,7 +62,7 @@ jobs: - name: create AVD and generate snapshot for caching if: steps.avd-cache.outputs.cache-hit != 'true' - uses: reactivecircus/android-emulator-runner@6b0df4b0efb23bb0ec63d881db79aefbc976e4b2 #pin@v2.30.1 + uses: reactivecircus/android-emulator-runner@77986be26589807b8ebab3fde7bbf5c60dabec32 #pin@v2.31.0 with: working-directory: ./flutter/example api-level: 21 @@ -74,7 +74,7 @@ jobs: script: echo 'Generated AVD snapshot for caching.' - name: launch android emulator & run android integration test - uses: reactivecircus/android-emulator-runner@6b0df4b0efb23bb0ec63d881db79aefbc976e4b2 #pin@v2.30.1 + uses: reactivecircus/android-emulator-runner@77986be26589807b8ebab3fde7bbf5c60dabec32 #pin@v2.31.0 with: working-directory: ./flutter/example api-level: 21 diff --git a/.github/workflows/flutter_test.yml b/.github/workflows/flutter_test.yml index 594570857f..8e1f20a50e 100644 --- a/.github/workflows/flutter_test.yml +++ b/.github/workflows/flutter_test.yml @@ -67,7 +67,7 @@ jobs: - name: create AVD and generate snapshot for caching if: steps.avd-cache.outputs.cache-hit != 'true' - uses: reactivecircus/android-emulator-runner@6b0df4b0efb23bb0ec63d881db79aefbc976e4b2 #pin@v2.30.1 + uses: reactivecircus/android-emulator-runner@77986be26589807b8ebab3fde7bbf5c60dabec32 #pin@v2.31.0 with: working-directory: ./flutter/example api-level: 31 @@ -84,7 +84,7 @@ jobs: run: flutter build apk --debug - name: launch android emulator & run android native test - uses: reactivecircus/android-emulator-runner@6b0df4b0efb23bb0ec63d881db79aefbc976e4b2 #pin@v2.30.1 + uses: reactivecircus/android-emulator-runner@77986be26589807b8ebab3fde7bbf5c60dabec32 #pin@v2.31.0 with: working-directory: ./flutter/example/android api-level: 31 @@ -97,7 +97,7 @@ jobs: script: ./gradlew testDebugUnitTest - name: launch android emulator & run android integration test - uses: reactivecircus/android-emulator-runner@6b0df4b0efb23bb0ec63d881db79aefbc976e4b2 #pin@v2.30.1 + uses: reactivecircus/android-emulator-runner@77986be26589807b8ebab3fde7bbf5c60dabec32 #pin@v2.31.0 with: working-directory: ./flutter/example api-level: 31 From fec92cc66e26e4c4884781314753c8f4e739539d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 28 May 2024 12:47:40 +0200 Subject: [PATCH 186/237] chore: update metrics/flutter.properties to 3.22.1 (#2069) Co-authored-by: GitHub --- metrics/flutter.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/metrics/flutter.properties b/metrics/flutter.properties index 8c5d1516b6..ac97c1a7db 100644 --- a/metrics/flutter.properties +++ b/metrics/flutter.properties @@ -1,2 +1,2 @@ -version = 3.22.0 +version = 3.22.1 repo = https://github.com/flutter/flutter From ed9caea7c8f10b300b240e8995c8680441aa312f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 28 May 2024 14:47:55 +0200 Subject: [PATCH 187/237] build(deps): bump lints from 3.0.0 to 4.0.0 in /dart (#2058) * build(deps): bump lints from 3.0.0 to 4.0.0 in /dart Bumps [lints](https://github.com/dart-lang/lints) from 3.0.0 to 4.0.0. - [Release notes](https://github.com/dart-lang/lints/releases) - [Changelog](https://github.com/dart-lang/lints/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/lints/compare/v3.0.0...v4.0.0) --- updated-dependencies: - dependency-name: lints dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] * Update * Update --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: GIancarlo Buenaflor --- dart/pubspec.yaml | 2 +- dart/test/event_processor/enricher/io_enricher_test.dart | 1 + dart/test/event_processor/enricher/web_enricher_test.dart | 2 ++ .../exception/io_exception_event_processor_test.dart | 1 + dart/test/example_web_compile_test.dart | 2 ++ dart/test/initialization_test.dart | 1 + dart/test/run_zoned_guarded_integration_test.dart | 1 + dart/test/sentry_attachment_io_test.dart | 1 + dart/test/sentry_browser_test.dart | 2 ++ dart/test/sentry_envelope_vm_test.dart | 2 ++ dart/test/sentry_io_client_test.dart | 2 ++ dart/test/sentry_isolate_extension_test.dart | 2 ++ dart/test/sentry_isolate_test.dart | 1 + dart/test/version_test.dart | 1 + 14 files changed, 20 insertions(+), 1 deletion(-) diff --git a/dart/pubspec.yaml b/dart/pubspec.yaml index ebb883c308..efef9ca103 100644 --- a/dart/pubspec.yaml +++ b/dart/pubspec.yaml @@ -28,7 +28,7 @@ dependencies: dev_dependencies: build_runner: ^2.4.2 mockito: ^5.1.0 - lints: ^3.0.0 + lints: ^4.0.0 test: ^1.21.1 yaml: ^3.1.0 # needed for version match (code and pubspec) collection: ^1.16.0 diff --git a/dart/test/event_processor/enricher/io_enricher_test.dart b/dart/test/event_processor/enricher/io_enricher_test.dart index 72080cba3f..bdc6da2e4e 100644 --- a/dart/test/event_processor/enricher/io_enricher_test.dart +++ b/dart/test/event_processor/enricher/io_enricher_test.dart @@ -1,4 +1,5 @@ @TestOn('vm') +library dart_test; import 'package:sentry/sentry.dart'; import 'package:sentry/src/event_processor/enricher/io_enricher_event_processor.dart'; diff --git a/dart/test/event_processor/enricher/web_enricher_test.dart b/dart/test/event_processor/enricher/web_enricher_test.dart index e5d5b2efec..cdc7310fab 100644 --- a/dart/test/event_processor/enricher/web_enricher_test.dart +++ b/dart/test/event_processor/enricher/web_enricher_test.dart @@ -1,4 +1,6 @@ @TestOn('browser') +library dart_test; + import 'dart:html' as html; import 'package:sentry/sentry.dart'; diff --git a/dart/test/event_processor/exception/io_exception_event_processor_test.dart b/dart/test/event_processor/exception/io_exception_event_processor_test.dart index 5d4d771a08..9523038638 100644 --- a/dart/test/event_processor/exception/io_exception_event_processor_test.dart +++ b/dart/test/event_processor/exception/io_exception_event_processor_test.dart @@ -1,4 +1,5 @@ @TestOn('vm') +library dart_test; import 'dart:io'; diff --git a/dart/test/example_web_compile_test.dart b/dart/test/example_web_compile_test.dart index d327dcaed1..4199a47dda 100644 --- a/dart/test/example_web_compile_test.dart +++ b/dart/test/example_web_compile_test.dart @@ -1,4 +1,6 @@ @TestOn('vm') +library dart_test; + import 'dart:async'; import 'dart:convert'; import 'dart:io'; diff --git a/dart/test/initialization_test.dart b/dart/test/initialization_test.dart index 7eb8c15265..e6f9ddea23 100644 --- a/dart/test/initialization_test.dart +++ b/dart/test/initialization_test.dart @@ -1,4 +1,5 @@ @TestOn('vm') +library dart_test; import 'package:sentry/sentry.dart'; import 'package:test/test.dart'; diff --git a/dart/test/run_zoned_guarded_integration_test.dart b/dart/test/run_zoned_guarded_integration_test.dart index 13b102d7da..dd3c2aa0f3 100644 --- a/dart/test/run_zoned_guarded_integration_test.dart +++ b/dart/test/run_zoned_guarded_integration_test.dart @@ -1,4 +1,5 @@ @TestOn('vm') +library dart_test; import 'package:sentry/sentry.dart'; import 'package:test/test.dart'; diff --git a/dart/test/sentry_attachment_io_test.dart b/dart/test/sentry_attachment_io_test.dart index 2752355a2b..29a0076bfe 100644 --- a/dart/test/sentry_attachment_io_test.dart +++ b/dart/test/sentry_attachment_io_test.dart @@ -1,4 +1,5 @@ @TestOn('vm') +library dart_test; import 'dart:io'; diff --git a/dart/test/sentry_browser_test.dart b/dart/test/sentry_browser_test.dart index 8524019467..eaccfa1d03 100644 --- a/dart/test/sentry_browser_test.dart +++ b/dart/test/sentry_browser_test.dart @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @TestOn('browser') +library dart_test; + import 'package:test/test.dart'; import 'test_utils.dart'; diff --git a/dart/test/sentry_envelope_vm_test.dart b/dart/test/sentry_envelope_vm_test.dart index a000c0c4e6..7854ffccb0 100644 --- a/dart/test/sentry_envelope_vm_test.dart +++ b/dart/test/sentry_envelope_vm_test.dart @@ -1,4 +1,6 @@ @TestOn('vm') +library dart_test; + import 'dart:convert'; import 'dart:io'; diff --git a/dart/test/sentry_io_client_test.dart b/dart/test/sentry_io_client_test.dart index b2479a27c8..9ffe1f319c 100644 --- a/dart/test/sentry_io_client_test.dart +++ b/dart/test/sentry_io_client_test.dart @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @TestOn('vm') +library dart_test; + import 'dart:io'; import 'package:test/test.dart'; diff --git a/dart/test/sentry_isolate_extension_test.dart b/dart/test/sentry_isolate_extension_test.dart index 415f67c797..626d7e525c 100644 --- a/dart/test/sentry_isolate_extension_test.dart +++ b/dart/test/sentry_isolate_extension_test.dart @@ -1,4 +1,6 @@ @TestOn('vm') +library dart_test; + import 'dart:isolate'; import 'package:sentry/src/sentry_isolate_extension.dart'; diff --git a/dart/test/sentry_isolate_test.dart b/dart/test/sentry_isolate_test.dart index 7cebc3e5e4..6d41636303 100644 --- a/dart/test/sentry_isolate_test.dart +++ b/dart/test/sentry_isolate_test.dart @@ -1,4 +1,5 @@ @TestOn('vm') +library dart_test; import 'package:sentry/src/hub.dart'; import 'package:sentry/src/protocol/sentry_level.dart'; diff --git a/dart/test/version_test.dart b/dart/test/version_test.dart index f1ff8574a8..f2022bbba2 100644 --- a/dart/test/version_test.dart +++ b/dart/test/version_test.dart @@ -3,6 +3,7 @@ // found in the LICENSE file. @TestOn('vm') +library dart_test; import 'dart:io'; From 31e875c164436fe9d6211ac5dbb38a8b1403da55 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 28 May 2024 14:52:18 +0200 Subject: [PATCH 188/237] build(deps): bump ruby/setup-ruby from 1.152.0 to 1.176.0 (#2038) Bumps [ruby/setup-ruby](https://github.com/ruby/setup-ruby) from 1.152.0 to 1.176.0. - [Release notes](https://github.com/ruby/setup-ruby/releases) - [Commits](https://github.com/ruby/setup-ruby/compare/250fcd6a742febb1123a77a841497ccaa8b9e939...cacc9f1c0b3f4eb8a16a6bb0ed10897b43b9de49) --- updated-dependencies: - dependency-name: ruby/setup-ruby dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor --- .github/workflows/testflight.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/testflight.yml b/.github/workflows/testflight.yml index a40d5ba02e..77dab66fe6 100644 --- a/.github/workflows/testflight.yml +++ b/.github/workflows/testflight.yml @@ -16,7 +16,7 @@ jobs: - uses: actions/checkout@v4 - uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 # pin@v2.16.0 - run: xcodes select 15.0.1 - - uses: ruby/setup-ruby@250fcd6a742febb1123a77a841497ccaa8b9e939 # pin@v1.152.0 + - uses: ruby/setup-ruby@cacc9f1c0b3f4eb8a16a6bb0ed10897b43b9de49 # pin@v1.176.0 with: ruby-version: '2.7.5' bundler-cache: true From 5baa2016731c3fe306570ee40d6f18206cf63791 Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Tue, 28 May 2024 15:59:56 +0200 Subject: [PATCH 189/237] fix(app-start): `Cold start` should be `Cold Start` (#2076) * fix description * update --- CHANGELOG.md | 4 ++++ .../lib/src/integrations/native_app_start_integration.dart | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 778d474a9f..db67a7706d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Fixes + +- Change app start span description from `Cold start` to `Cold Start` and `Warm start` to `Warm Start` ([#2076](https://github.com/getsentry/sentry-dart/pull/2076)) + ### Dependencies - Bump Cocoa SDK from v8.25.2 to v8.26.0 ([#2060](https://github.com/getsentry/sentry-dart/pull/2060)) diff --git a/flutter/lib/src/integrations/native_app_start_integration.dart b/flutter/lib/src/integrations/native_app_start_integration.dart index 616042406a..d3be7b4a0f 100644 --- a/flutter/lib/src/integrations/native_app_start_integration.dart +++ b/flutter/lib/src/integrations/native_app_start_integration.dart @@ -218,7 +218,7 @@ class AppStartInfo { String get appStartTypeOperation => 'app.start.${type.name}'; String get appStartTypeDescription => - type == AppStartType.cold ? 'Cold start' : 'Warm start'; + type == AppStartType.cold ? 'Cold Start' : 'Warm Start'; final pluginRegistrationDescription = 'App start to plugin registration'; final sentrySetupDescription = 'Before Sentry Init Setup'; final firstFrameRenderDescription = 'First frame render'; From 586d7d26492d8edb74aba74047a51370fc992f25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20Andra=C5=A1ec?= Date: Fri, 31 May 2024 12:35:59 +0000 Subject: [PATCH 190/237] Parse PlatformException from details instead of message (#2052) --- CHANGELOG.md | 1 + ...id_platform_exception_event_processor.dart | 26 ++- ...atform_exception_event_processor_test.dart | 178 +++++++++++------- flutter/test/jvm/jvm_exception_test.dart | 41 ++++ 4 files changed, 171 insertions(+), 75 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index db67a7706d..de3a68db32 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### Fixes - Change app start span description from `Cold start` to `Cold Start` and `Warm start` to `Warm Start` ([#2076](https://github.com/getsentry/sentry-dart/pull/2076)) +- Parse `PlatformException` from details instead of message ([#2052](https://github.com/getsentry/sentry-dart/pull/2052)) ### Dependencies diff --git a/flutter/lib/src/event_processor/android_platform_exception_event_processor.dart b/flutter/lib/src/event_processor/android_platform_exception_event_processor.dart index bffc6707b7..d939f4b90e 100644 --- a/flutter/lib/src/event_processor/android_platform_exception_event_processor.dart +++ b/flutter/lib/src/event_processor/android_platform_exception_event_processor.dart @@ -21,8 +21,8 @@ class AndroidPlatformExceptionEventProcessor implements EventProcessor { return event; } - final plaformException = event.throwable; - if (plaformException is! PlatformException) { + final platformException = event.throwable; + if (platformException is! PlatformException) { return event; } @@ -31,18 +31,24 @@ class AndroidPlatformExceptionEventProcessor implements EventProcessor { final packageInfo = await PackageInfo.fromPlatform(); final nativeStackTrace = - _tryParse(plaformException.stacktrace, packageInfo.packageName); - final messageStackTrace = - _tryParse(plaformException.message, packageInfo.packageName); + _tryParse(platformException.stacktrace, packageInfo.packageName); - if (nativeStackTrace == null && messageStackTrace == null) { + final details = platformException.details; + String? detailsString; + if (details is String) { + detailsString = details; + } + final detailsStackTrace = + _tryParse(detailsString, packageInfo.packageName); + + if (nativeStackTrace == null && detailsStackTrace == null) { return event; } return _processPlatformException( event, nativeStackTrace, - messageStackTrace, + detailsStackTrace, ); } catch (e, stackTrace) { _options.logger( @@ -71,18 +77,18 @@ class AndroidPlatformExceptionEventProcessor implements EventProcessor { SentryEvent _processPlatformException( SentryEvent event, List>? nativeStackTrace, - List>? messageStackTrace, + List>? detailsStackTrace, ) { final threads = _markDartThreadsAsNonCrashed(event.threads); final jvmExceptions = [ ...?nativeStackTrace?.map((e) => e.key), - ...?messageStackTrace?.map((e) => e.key) + ...?detailsStackTrace?.map((e) => e.key) ]; var jvmThreads = [ ...?nativeStackTrace?.map((e) => e.value), - ...?messageStackTrace?.map((e) => e.value), + ...?detailsStackTrace?.map((e) => e.value), ]; if (jvmThreads.isNotEmpty) { diff --git a/flutter/test/android_platform_exception_event_processor_test.dart b/flutter/test/android_platform_exception_event_processor_test.dart index 060ada138c..4085d8215c 100644 --- a/flutter/test/android_platform_exception_event_processor_test.dart +++ b/flutter/test/android_platform_exception_event_processor_test.dart @@ -25,21 +25,22 @@ void main() { }); group(AndroidPlatformExceptionEventProcessor, () { - test('exception is correctly parsed', () async { + test('platform exception with details and stackTrace is correctly parsed', + () async { final platformExceptionEvent = await fixture.processor - .apply(fixture.eventWithPlatformStackTrace, Hint()); + .apply(fixture.eventWithPlatformDetailsAndStackTrace, Hint()); final exceptions = platformExceptionEvent!.exceptions!; expect(exceptions.length, 3); - final platformException = exceptions[1]; + final platformException_1 = exceptions[1]; - expect(platformException.type, 'IllegalArgumentException'); + expect(platformException_1.type, 'IllegalArgumentException'); expect( - platformException.value, + platformException_1.value, "Unsupported value: '[Ljava.lang.StackTraceElement;@ba6feed' of type 'class [Ljava.lang.StackTraceElement;'", ); - expect(platformException.stackTrace!.frames.length, 18); + expect(platformException_1.stackTrace!.frames.length, 18); final platformException_2 = exceptions[2]; @@ -51,37 +52,47 @@ void main() { expect(platformException_2.stackTrace!.frames.length, 18); }); - test('platform exception is correctly parsed', () async { + test('platform exception with details correctly parsed', () async { final platformExceptionEvent = await fixture.processor - .apply(fixture.eventWithFailingPlatformStackTrace, Hint()); + .apply(fixture.eventWithPlatformDetails, Hint()); final exceptions = platformExceptionEvent!.exceptions!; - expect(exceptions.length, 3); + expect(exceptions.length, 2); - final platformException = exceptions[1]; + final platformException_1 = exceptions[1]; - expect(platformException.type, 'PlatformException'); + expect(platformException_1.type, 'Resources\$NotFoundException'); + expect(platformException_1.module, 'android.content.res'); expect( - platformException.value, - "PlatformException(getNotificationChannelsError, Unable to find resource ID #0x7f14000d, android.content.res.Resources\$NotFoundException: Unable to find resource ID #0x7f14000d", + platformException_1.value, + "Unable to find resource ID #0x7f14000d", ); - expect(platformException.stackTrace!.frames.length, 20); + expect(platformException_1.stackTrace!.frames.length, 19); + }); - final platformException_2 = exceptions[2]; + test('platform exception with stackTrace correctly parsed', () async { + final platformExceptionEvent = await fixture.processor + .apply(fixture.eventWithPlatformStackTrace, Hint()); + + final exceptions = platformExceptionEvent!.exceptions!; + expect(exceptions.length, 2); - expect(platformException_2.type, 'PlatformException'); + final platformException_1 = exceptions[1]; + + expect(platformException_1.type, 'IllegalArgumentException'); + expect(platformException_1.module, 'java.lang'); expect( - platformException_2.value, - "PlatformException(getNotificationChannelsError, Unable to find resource ID #0x7f14000d, android.content.res.Resources\$NotFoundException: Unable to find resource ID #0x7f14000d", + platformException_1.value, + "Not supported, use openfile", ); - expect(platformException_2.stackTrace!.frames.length, 20); + expect(platformException_1.stackTrace!.frames.length, 22); }); test( 'Dart thread is current and not crashed if Android exception is present', () async { final platformExceptionEvent = await fixture.processor - .apply(fixture.eventWithPlatformStackTrace, Hint()); + .apply(fixture.eventWithPlatformDetailsAndStackTrace, Hint()); final exceptions = platformExceptionEvent!.exceptions!; expect(exceptions.length, 3); @@ -92,7 +103,7 @@ void main() { test('platformexception has Android thread attached', () async { final platformExceptionEvent = await fixture.processor - .apply(fixture.eventWithPlatformStackTrace, Hint()); + .apply(fixture.eventWithPlatformDetailsAndStackTrace, Hint()); final exceptions = platformExceptionEvent!.exceptions!; expect(exceptions.length, 3); @@ -109,10 +120,11 @@ void main() { test('platformexception has no Android thread attached if disabled', () async { fixture.options.attachThreads = false; - final threadCount = fixture.eventWithPlatformStackTrace.threads?.length; + final threadCount = + fixture.eventWithPlatformDetailsAndStackTrace.threads?.length; final platformExceptionEvent = await fixture.processor - .apply(fixture.eventWithPlatformStackTrace, Hint()); + .apply(fixture.eventWithPlatformDetailsAndStackTrace, Hint()); final exceptions = platformExceptionEvent!.exceptions!; expect(exceptions.length, 3); @@ -122,7 +134,7 @@ void main() { test('does nothing if no PlatformException is there', () async { final exception = fixture.options.exceptionFactory - .getSentryException(testPlatformException); + .getSentryException(detailsAndStackTracePlatformException); final event = SentryEvent( exceptions: [exception], @@ -136,10 +148,10 @@ void main() { }); test('does nothing if PlatformException has no stackTrace', () async { - final platformExceptionEvent = await fixture.processor - .apply(fixture.eventWithoutPlatformStackTrace, Hint()); + final platformExceptionEvent = + await fixture.processor.apply(fixture.eventWithPlatformEmpty, Hint()); - expect(fixture.eventWithoutPlatformStackTrace, platformExceptionEvent); + expect(fixture.eventWithPlatformEmpty, platformExceptionEvent); }); }); } @@ -148,33 +160,44 @@ class Fixture { late AndroidPlatformExceptionEventProcessor processor = AndroidPlatformExceptionEventProcessor(options); - late SentryException withPlatformStackTrace = options.exceptionFactory - .getSentryException(testPlatformException) + late SentryException withPlatformDetailsAndStackTrace = options + .exceptionFactory + .getSentryException(detailsAndStackTracePlatformException) .copyWith(threadId: 1); - late SentryException withoutPlatformStackTrace = options.exceptionFactory - .getSentryException(emptyPlatformException) + late SentryEvent eventWithPlatformDetailsAndStackTrace = SentryEvent( + exceptions: [withPlatformDetailsAndStackTrace], + throwable: detailsAndStackTracePlatformException, + threads: [dartThread], + ); + + late SentryException withPlatformDetails = options.exceptionFactory + .getSentryException(detailsPlatformException) .copyWith(threadId: 1); - late SentryEvent eventWithPlatformStackTrace = SentryEvent( - exceptions: [withPlatformStackTrace], - throwable: testPlatformException, + late SentryEvent eventWithPlatformDetails = SentryEvent( + exceptions: [withPlatformDetails], + throwable: detailsPlatformException, threads: [dartThread], ); - late SentryEvent eventWithoutPlatformStackTrace = SentryEvent( - exceptions: [withoutPlatformStackTrace], - throwable: emptyPlatformException, + late SentryException withPlatformStackTrace = options.exceptionFactory + .getSentryException(stackTracePlatformException) + .copyWith(threadId: 1); + + late SentryEvent eventWithPlatformStackTrace = SentryEvent( + exceptions: [withPlatformDetails], + throwable: stackTracePlatformException, threads: [dartThread], ); - late SentryException withFailingPlatformStackTrace = options.exceptionFactory - .getSentryException(failingPlatformException) + late SentryException withPlatformEmpty = options.exceptionFactory + .getSentryException(emptyPlatformException) .copyWith(threadId: 1); - late SentryEvent eventWithFailingPlatformStackTrace = SentryEvent( - exceptions: [withFailingPlatformStackTrace], - throwable: failingPlatformException, + late SentryEvent eventWithPlatformEmpty = SentryEvent( + exceptions: [withPlatformEmpty], + throwable: emptyPlatformException, threads: [dartThread], ); @@ -189,30 +212,14 @@ class Fixture { ..attachThreads = true; } -final testPlatformException = PlatformException( +final detailsAndStackTracePlatformException = PlatformException( code: 'error', - details: + message: "Unsupported value: '[Ljava.lang.StackTraceElement;@fa902f1' of type 'class [Ljava.lang.StackTraceElement;'", - message: _jvmStackTrace, + details: _jvmStackTrace, stacktrace: _jvmStackTrace, ); -final emptyPlatformException = PlatformException( - code: 'error', - details: - "Unsupported value: '[Ljava.lang.StackTraceElement;@fa902f1' of type 'class [Ljava.lang.StackTraceElement;'", - message: null, - stacktrace: null, -); - -final failingPlatformException = PlatformException( - code: 'error', - details: - "PlatformException: PlatformException(getNotificationChannelsError, Unable to find resource ID #0x7f14000d, android.content.res.Resources\$NotFoundException: Unable to find resource ID #0x7f14000d", - message: _failingStackTrace, - stacktrace: _failingStackTrace, -); - const _jvmStackTrace = """java.lang.IllegalArgumentException: Unsupported value: '[Ljava.lang.StackTraceElement;@ba6feed' of type 'class [Ljava.lang.StackTraceElement;' at io.flutter.plugin.common.StandardMessageCodec.writeValue(StandardMessageCodec.java:292) @@ -234,8 +241,11 @@ const _jvmStackTrace = at com.android.internal.os.RuntimeInit\$MethodAndArgsCaller.run(RuntimeInit.java:556) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1037)"""; -const _failingStackTrace = - """PlatformException: PlatformException(getNotificationChannelsError, Unable to find resource ID #0x7f14000d, android.content.res.Resources\$NotFoundException: Unable to find resource ID #0x7f14000d +final detailsPlatformException = PlatformException( + code: 'getNotificationChannelsError', + message: 'Unable to find resource ID #0x7f14000d', + details: + """android.content.res.Resources\$NotFoundException: Unable to find resource ID #0x7f14000d at android.content.res.ResourcesImpl.getResourceEntryName(ResourcesImpl.java:493) at android.content.res.Resources.getResourceEntryName(Resources.java:2441) at com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin.getMappedNotificationChannel(FlutterLocalNotificationsPlugin.java:170) @@ -254,5 +264,43 @@ const _failingStackTrace = at android.app.ActivityThread.main(ActivityThread.java:9821) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit\$MethodAndArgsCaller.run(RuntimeInit.java:586) - at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1201) -, null)"""; + at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1201)""", + stacktrace: null, +); + +final stackTracePlatformException = PlatformException( + code: "error", + message: "Not supported, use openfile", + details: null, + stacktrace: """java.lang.IllegalArgumentException: Not supported, use openfile + at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:172) + at android.database.DatabaseUtils.readExceptionWithFileNotFoundExceptionFromParcel(DatabaseUtils.java:153) + at android.content.ContentProviderProxy.openTypedAssetFile(ContentProviderNative.java:814) + at android.content.ContentResolver.openTypedAssetFileDescriptor(ContentResolver.java:2043) + at android.content.ContentResolver.openTypedAssetFileDescriptor(ContentResolver.java:1981) + at io.flutter.plugin.platform.f.q(PlatformPlugin.java:57) + at io.flutter.plugin.platform.f.c(PlatformPlugin.java:1) + at io.flutter.plugin.platform.f\$a.g(PlatformPlugin.java:3) + at lb.j\$a.onMethodCall(PlatformChannel.java:294) + at mb.j\$a.a(MethodChannel.java:18) + at za.c.l(DartMessenger.java:19) + at za.c.m(DartMessenger.java:41) + at za.c.i(Unknown Source:0) + at za.b.run(Unknown Source:12) + at android.os.Handler.handleCallback(Handler.java:958) + at android.os.Handler.dispatchMessage(Handler.java:99) + at android.os.Looper.loopOnce(Looper.java:230) + at android.os.Looper.loop(Looper.java:319) + at android.app.ActivityThread.main(ActivityThread.java:8893) + at java.lang.reflect.Method.invoke(Native Method) + at com.android.internal.os.RuntimeInit\$MethodAndArgsCaller.run(RuntimeInit.java:608) + at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1103)""", +); + +final emptyPlatformException = PlatformException( + code: 'error', + message: + "Unsupported value: '[Ljava.lang.StackTraceElement;@fa902f1' of type 'class [Ljava.lang.StackTraceElement;'", + details: null, + stacktrace: null, +); diff --git a/flutter/test/jvm/jvm_exception_test.dart b/flutter/test/jvm/jvm_exception_test.dart index de8a3b4e29..9f3f0d2ef9 100644 --- a/flutter/test/jvm/jvm_exception_test.dart +++ b/flutter/test/jvm/jvm_exception_test.dart @@ -86,6 +86,25 @@ void main() { expect(exception.stackTrace[0].lineNumber, 292); }); + test('parse other Flutter Android PlatformException', () { + final exception = JvmException.parse(otherFlutterAndroidPlatformException); + expect( + exception.description, + "Unable to find resource ID #0x7f14000d", + ); + expect(exception.thread, null); + expect(exception.type, 'android.content.res.Resources\$NotFoundException'); + expect(exception.stackTrace.length, 19); + expect(exception.causes, null); + expect(exception.suppressed, null); + + expect( + exception.stackTrace[0].className, 'android.content.res.ResourcesImpl'); + expect(exception.stackTrace[0].method, 'getResourceEntryName'); + expect(exception.stackTrace[0].fileName, 'ResourcesImpl.java'); + expect(exception.stackTrace[0].lineNumber, 493); + }); + test('parse drops empty frames', () { final exception = JvmException.parse(platformExceptionWithEmptyStackFrames); expect(exception.stackTrace.length, 13); @@ -205,6 +224,28 @@ java.lang.IllegalArgumentException: Unsupported value: '[Ljava.lang.StackTraceEl at com.android.internal.os.RuntimeInit\$MethodAndArgsCaller.run(RuntimeInit.java:556) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1037)'''; +const otherFlutterAndroidPlatformException = ''' +android.content.res.Resources\$NotFoundException: Unable to find resource ID #0x7f14000d + at android.content.res.ResourcesImpl.getResourceEntryName(ResourcesImpl.java:493) + at android.content.res.Resources.getResourceEntryName(Resources.java:2441) + at com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin.getMappedNotificationChannel(FlutterLocalNotificationsPlugin.java:170) + at com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin.getNotificationChannels(FlutterLocalNotificationsPlugin.java:32) + at com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin.onMethodCall(FlutterLocalNotificationsPlugin.java:399) + at be.j\$a.a(MethodChannel.java:18) + at pd.c.l(DartMessenger.java:19) + at pd.c.m(DartMessenger.java:42) + at pd.c.h(Unknown Source:0) + at pd.b.run(Unknown Source:12) + at android.os.Handler.handleCallback(Handler.java:966) + at android.os.Handler.dispatchMessage(Handler.java:110) + at android.os.Looper.loopOnce(Looper.java:205) + at android.os.Looper.loop(Looper.java:293) + at android.app.ActivityThread.loopProcess(ActivityThread.java:9832) + at android.app.ActivityThread.main(ActivityThread.java:9821) + at java.lang.reflect.Method.invoke(Native Method) + at com.android.internal.os.RuntimeInit\$MethodAndArgsCaller.run(RuntimeInit.java:586) + at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1201)'''; + const platformExceptionWithEmptyStackFrames = ''' java.lang.RuntimeException: Catch this platform exception! at io.sentry.samples.flutter.MainActivity\$configureFlutterEngine\$1.onMethodCall(MainActivity.kt:40) From df03cd542034aa12f6af29d0b05babdce8f50a8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20Andra=C5=A1ec?= Date: Mon, 3 Jun 2024 13:28:03 +0000 Subject: [PATCH 191/237] =?UTF-8?q?=20Testflight:=20build=20with=20?= =?UTF-8?q?=E2=80=94obfuscate=20--split-debug-info=20flags=20(#2061)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/testflight.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/testflight.yml b/.github/workflows/testflight.yml index 77dab66fe6..2d91861174 100644 --- a/.github/workflows/testflight.yml +++ b/.github/workflows/testflight.yml @@ -26,7 +26,7 @@ jobs: run: | flutter upgrade flutter pub get - flutter build ios --no-codesign + flutter build ios --no-codesign --obfuscate --split-debug-info=. - name: Install Fastlane working-directory: ./flutter/example/ios From 85accd7e0720ff63dac779b64bcb74182cf6de7b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Jun 2024 16:28:16 +0200 Subject: [PATCH 192/237] build(deps): bump lints from 3.0.0 to 4.0.0 in /logging (#2057) * build(deps): bump lints from 3.0.0 to 4.0.0 in /logging Bumps [lints](https://github.com/dart-lang/lints) from 3.0.0 to 4.0.0. - [Release notes](https://github.com/dart-lang/lints/releases) - [Changelog](https://github.com/dart-lang/lints/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/lints/compare/v3.0.0...v4.0.0) --- updated-dependencies: - dependency-name: lints dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] * fix --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor --- logging/pubspec.yaml | 2 +- logging/test/version_test.dart | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/logging/pubspec.yaml b/logging/pubspec.yaml index 235e0900f9..1f759c9588 100644 --- a/logging/pubspec.yaml +++ b/logging/pubspec.yaml @@ -22,7 +22,7 @@ dependencies: sentry: 8.2.0 dev_dependencies: - lints: ^3.0.0 + lints: ^4.0.0 test: ^1.21.1 yaml: ^3.1.0 # needed for version match (code and pubspec) coverage: ^1.3.0 diff --git a/logging/test/version_test.dart b/logging/test/version_test.dart index f27d675c7d..316a1caaff 100644 --- a/logging/test/version_test.dart +++ b/logging/test/version_test.dart @@ -1,4 +1,5 @@ @TestOn('vm') +library dart_test; import 'dart:io'; From 69c47de05527b1b04eb26b3eb17bfbf9c182b735 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Jun 2024 16:41:08 +0200 Subject: [PATCH 193/237] build(deps): bump ruby/setup-ruby from 1.176.0 to 1.179.0 (#2083) Bumps [ruby/setup-ruby](https://github.com/ruby/setup-ruby) from 1.176.0 to 1.179.0. - [Release notes](https://github.com/ruby/setup-ruby/releases) - [Commits](https://github.com/ruby/setup-ruby/compare/cacc9f1c0b3f4eb8a16a6bb0ed10897b43b9de49...d5fb7a202fc07872cb44f00ba8e6197b70cb0c55) --- updated-dependencies: - dependency-name: ruby/setup-ruby dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/testflight.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/testflight.yml b/.github/workflows/testflight.yml index 2d91861174..5ba54d043c 100644 --- a/.github/workflows/testflight.yml +++ b/.github/workflows/testflight.yml @@ -16,7 +16,7 @@ jobs: - uses: actions/checkout@v4 - uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 # pin@v2.16.0 - run: xcodes select 15.0.1 - - uses: ruby/setup-ruby@cacc9f1c0b3f4eb8a16a6bb0ed10897b43b9de49 # pin@v1.176.0 + - uses: ruby/setup-ruby@d5fb7a202fc07872cb44f00ba8e6197b70cb0c55 # pin@v1.179.0 with: ruby-version: '2.7.5' bundler-cache: true From 72c2a90e85fe2b821cfa3d92edb4469d4b73c01d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Jun 2024 14:19:16 +0200 Subject: [PATCH 194/237] build(deps): bump lints from 3.0.0 to 4.0.0 in /file (#2054) * build(deps): bump lints from 3.0.0 to 4.0.0 in /file Bumps [lints](https://github.com/dart-lang/lints) from 3.0.0 to 4.0.0. - [Release notes](https://github.com/dart-lang/lints/releases) - [Changelog](https://github.com/dart-lang/lints/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/lints/compare/v3.0.0...v4.0.0) --- updated-dependencies: - dependency-name: lints dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] * Update --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: GIancarlo Buenaflor --- file/pubspec.yaml | 2 +- file/test/sentry_file_extension_test.dart | 1 + file/test/sentry_file_test.dart | 1 + file/test/version_test.dart | 1 + 4 files changed, 4 insertions(+), 1 deletion(-) diff --git a/file/pubspec.yaml b/file/pubspec.yaml index 9c0964cd80..7f2c554647 100644 --- a/file/pubspec.yaml +++ b/file/pubspec.yaml @@ -21,7 +21,7 @@ dependencies: meta: ^1.3.0 dev_dependencies: - lints: ^3.0.0 + lints: ^4.0.0 test: ^1.21.1 coverage: ^1.3.0 mockito: ^5.1.0 diff --git a/file/test/sentry_file_extension_test.dart b/file/test/sentry_file_extension_test.dart index 73eb94beff..d6a0bff5bc 100644 --- a/file/test/sentry_file_extension_test.dart +++ b/file/test/sentry_file_extension_test.dart @@ -1,4 +1,5 @@ @TestOn('vm') +library file_test; import 'dart:io'; diff --git a/file/test/sentry_file_test.dart b/file/test/sentry_file_test.dart index 3f7135de54..48cf9b5175 100644 --- a/file/test/sentry_file_test.dart +++ b/file/test/sentry_file_test.dart @@ -1,6 +1,7 @@ // ignore_for_file: invalid_use_of_internal_member @TestOn('vm') +library file_test; import 'dart:io'; diff --git a/file/test/version_test.dart b/file/test/version_test.dart index 8bba9116b9..a21aeea800 100644 --- a/file/test/version_test.dart +++ b/file/test/version_test.dart @@ -1,4 +1,5 @@ @TestOn('vm') +library file_test; import 'dart:io'; From 8ffc6d8bd906adaf897eadd5dcbcee2a4c3ffca7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Jun 2024 14:20:51 +0200 Subject: [PATCH 195/237] build(deps): bump lints from 3.0.0 to 4.0.0 in /dio (#2053) * build(deps): bump lints from 3.0.0 to 4.0.0 in /dio Bumps [lints](https://github.com/dart-lang/lints) from 3.0.0 to 4.0.0. - [Release notes](https://github.com/dart-lang/lints/releases) - [Changelog](https://github.com/dart-lang/lints/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/lints/compare/v3.0.0...v4.0.0) --- updated-dependencies: - dependency-name: lints dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] * Update --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: GIancarlo Buenaflor --- dio/pubspec.yaml | 2 +- dio/test/version_test.dart | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/dio/pubspec.yaml b/dio/pubspec.yaml index 9c0c4b31a1..c174f3ffd2 100644 --- a/dio/pubspec.yaml +++ b/dio/pubspec.yaml @@ -23,7 +23,7 @@ dependencies: dev_dependencies: meta: ^1.3.0 - lints: ^3.0.0 + lints: ^4.0.0 test: ^1.21.1 coverage: ^1.3.0 mockito: ^5.1.0 diff --git a/dio/test/version_test.dart b/dio/test/version_test.dart index 551d07a4c3..2e0c6a8b14 100644 --- a/dio/test/version_test.dart +++ b/dio/test/version_test.dart @@ -1,4 +1,5 @@ @TestOn('vm') +library dio_test; import 'dart:io'; From e6b16cd4aa51b0236a52f4c6380d53b6d1a1aee9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Jun 2024 14:42:34 +0200 Subject: [PATCH 196/237] build(deps): bump flutter_lints from 3.0.2 to 4.0.0 in /flutter (#2055) * build(deps): bump flutter_lints from 3.0.2 to 4.0.0 in /flutter Bumps [flutter_lints](https://github.com/flutter/packages/tree/main/packages) from 3.0.2 to 4.0.0. - [Release notes](https://github.com/flutter/packages/releases) - [Commits](https://github.com/flutter/packages/commits/flutter_lints-v4.0.0/packages) --- updated-dependencies: - dependency-name: flutter_lints dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] * Update --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor --- flutter/pubspec.yaml | 2 +- .../test/android_platform_exception_event_processor_test.dart | 1 + .../test/event_processor/screenshot_event_processor_test.dart | 1 + flutter/test/file_system_transport_test.dart | 1 + flutter/test/initialization_test.dart | 1 + flutter/test/integrations/init_native_sdk_test.dart | 1 + flutter/test/integrations/load_contexts_integration_test.dart | 1 + flutter/test/integrations/load_contexts_integrations_test.dart | 1 + flutter/test/integrations/load_image_list_test.dart | 1 + .../test/integrations/native_app_start_integration_test.dart | 2 ++ flutter/test/integrations/native_sdk_integration_test.dart | 1 + flutter/test/load_image_list_test.dart | 1 + flutter/test/native_scope_observer_test.dart | 1 + flutter/test/profiling_test.dart | 1 + flutter/test/screenshot/sentry_screenshot_widget_test.dart | 1 + flutter/test/sentry_native_channel_test.dart | 1 + flutter/test/sentry_native_test.dart | 2 ++ .../user_interaction/sentry_user_interaction_widget_test.dart | 1 + flutter/test/version_test.dart | 1 + .../test/view_hierarchy/view_hierarchy_integration_test.dart | 1 + 20 files changed, 22 insertions(+), 1 deletion(-) diff --git a/flutter/pubspec.yaml b/flutter/pubspec.yaml index ba6c34329c..b356cea210 100644 --- a/flutter/pubspec.yaml +++ b/flutter/pubspec.yaml @@ -34,7 +34,7 @@ dev_dependencies: sdk: flutter mockito: ^5.1.0 yaml: ^3.1.0 # needed for version match (code and pubspec) - flutter_lints: ^3.0.0 + flutter_lints: ^4.0.0 collection: ^1.16.0 remove_from_coverage: ^2.0.0 flutter_localizations: diff --git a/flutter/test/android_platform_exception_event_processor_test.dart b/flutter/test/android_platform_exception_event_processor_test.dart index 4085d8215c..9ebae071c7 100644 --- a/flutter/test/android_platform_exception_event_processor_test.dart +++ b/flutter/test/android_platform_exception_event_processor_test.dart @@ -1,4 +1,5 @@ @TestOn('vm') +library flutter_test; // ignore_for_file: invalid_use_of_internal_member import 'package:flutter/services.dart'; diff --git a/flutter/test/event_processor/screenshot_event_processor_test.dart b/flutter/test/event_processor/screenshot_event_processor_test.dart index 2c1d0a4adc..3a00f10ced 100644 --- a/flutter/test/event_processor/screenshot_event_processor_test.dart +++ b/flutter/test/event_processor/screenshot_event_processor_test.dart @@ -1,4 +1,5 @@ @Tags(['canvasKit']) // Web renderer where this test can run +library flutter_test; import 'dart:math'; import 'dart:ui'; diff --git a/flutter/test/file_system_transport_test.dart b/flutter/test/file_system_transport_test.dart index ba6d3d3bf8..aa948e56fb 100644 --- a/flutter/test/file_system_transport_test.dart +++ b/flutter/test/file_system_transport_test.dart @@ -1,4 +1,5 @@ @TestOn('vm') +library flutter_test; import 'dart:convert'; // backcompatibility for Flutter < 3.3 diff --git a/flutter/test/initialization_test.dart b/flutter/test/initialization_test.dart index 29d5e42c96..7b59c173bf 100644 --- a/flutter/test/initialization_test.dart +++ b/flutter/test/initialization_test.dart @@ -1,4 +1,5 @@ @TestOn('vm') +library flutter_test; import 'package:flutter_test/flutter_test.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; diff --git a/flutter/test/integrations/init_native_sdk_test.dart b/flutter/test/integrations/init_native_sdk_test.dart index fa3b76f153..6d3bd57e22 100644 --- a/flutter/test/integrations/init_native_sdk_test.dart +++ b/flutter/test/integrations/init_native_sdk_test.dart @@ -1,4 +1,5 @@ @TestOn('vm') +library flutter_test; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; diff --git a/flutter/test/integrations/load_contexts_integration_test.dart b/flutter/test/integrations/load_contexts_integration_test.dart index 7b57eb572a..926d8e09b1 100644 --- a/flutter/test/integrations/load_contexts_integration_test.dart +++ b/flutter/test/integrations/load_contexts_integration_test.dart @@ -1,4 +1,5 @@ @TestOn('vm') +library flutter_test; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; diff --git a/flutter/test/integrations/load_contexts_integrations_test.dart b/flutter/test/integrations/load_contexts_integrations_test.dart index 6de2d32e8d..8c7ae456e0 100644 --- a/flutter/test/integrations/load_contexts_integrations_test.dart +++ b/flutter/test/integrations/load_contexts_integrations_test.dart @@ -1,4 +1,5 @@ @TestOn('vm') +library flutter_test; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; diff --git a/flutter/test/integrations/load_image_list_test.dart b/flutter/test/integrations/load_image_list_test.dart index b02acc94f3..f7c72fc95e 100644 --- a/flutter/test/integrations/load_image_list_test.dart +++ b/flutter/test/integrations/load_image_list_test.dart @@ -1,4 +1,5 @@ @TestOn('vm') +library flutter_test; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; diff --git a/flutter/test/integrations/native_app_start_integration_test.dart b/flutter/test/integrations/native_app_start_integration_test.dart index 30cf621208..eb13b41a8d 100644 --- a/flutter/test/integrations/native_app_start_integration_test.dart +++ b/flutter/test/integrations/native_app_start_integration_test.dart @@ -1,4 +1,6 @@ @TestOn('vm') +library flutter_test; + import 'package:collection/collection.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/mockito.dart'; diff --git a/flutter/test/integrations/native_sdk_integration_test.dart b/flutter/test/integrations/native_sdk_integration_test.dart index b67eccbe0e..1826bd38f2 100644 --- a/flutter/test/integrations/native_sdk_integration_test.dart +++ b/flutter/test/integrations/native_sdk_integration_test.dart @@ -1,4 +1,5 @@ @TestOn('vm') +library flutter_test; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; diff --git a/flutter/test/load_image_list_test.dart b/flutter/test/load_image_list_test.dart index 345d913887..472aac0947 100644 --- a/flutter/test/load_image_list_test.dart +++ b/flutter/test/load_image_list_test.dart @@ -1,4 +1,5 @@ @TestOn('vm') +library flutter_test; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; diff --git a/flutter/test/native_scope_observer_test.dart b/flutter/test/native_scope_observer_test.dart index 916bd4b7be..980449b11f 100644 --- a/flutter/test/native_scope_observer_test.dart +++ b/flutter/test/native_scope_observer_test.dart @@ -1,4 +1,5 @@ @TestOn('vm') +library flutter_test; import 'package:flutter_test/flutter_test.dart'; import 'package:sentry/sentry.dart'; diff --git a/flutter/test/profiling_test.dart b/flutter/test/profiling_test.dart index eddb391313..adf88e0f2e 100644 --- a/flutter/test/profiling_test.dart +++ b/flutter/test/profiling_test.dart @@ -1,4 +1,5 @@ @TestOn('vm') +library flutter_test; import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/mockito.dart'; diff --git a/flutter/test/screenshot/sentry_screenshot_widget_test.dart b/flutter/test/screenshot/sentry_screenshot_widget_test.dart index fd4603c794..57379387d0 100644 --- a/flutter/test/screenshot/sentry_screenshot_widget_test.dart +++ b/flutter/test/screenshot/sentry_screenshot_widget_test.dart @@ -1,4 +1,5 @@ @TestOn('vm') +library flutter_test; // ignore_for_file: invalid_use_of_internal_member import 'package:flutter/material.dart'; diff --git a/flutter/test/sentry_native_channel_test.dart b/flutter/test/sentry_native_channel_test.dart index a8debae3e4..050693cc8a 100644 --- a/flutter/test/sentry_native_channel_test.dart +++ b/flutter/test/sentry_native_channel_test.dart @@ -1,6 +1,7 @@ // ignore_for_file: inference_failure_on_function_invocation @TestOn('vm') +library flutter_test; import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/mockito.dart'; diff --git a/flutter/test/sentry_native_test.dart b/flutter/test/sentry_native_test.dart index 92b7c2e28e..8d30312f6f 100644 --- a/flutter/test/sentry_native_test.dart +++ b/flutter/test/sentry_native_test.dart @@ -1,4 +1,6 @@ @TestOn('vm') +library flutter_test; + import 'package:flutter_test/flutter_test.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:sentry_flutter/src/native/sentry_native.dart'; diff --git a/flutter/test/user_interaction/sentry_user_interaction_widget_test.dart b/flutter/test/user_interaction/sentry_user_interaction_widget_test.dart index 0fb73cb930..8f326579f4 100644 --- a/flutter/test/user_interaction/sentry_user_interaction_widget_test.dart +++ b/flutter/test/user_interaction/sentry_user_interaction_widget_test.dart @@ -1,4 +1,5 @@ @TestOn('vm') +library flutter_test; // ignore_for_file: invalid_use_of_internal_member import 'dart:async'; diff --git a/flutter/test/version_test.dart b/flutter/test/version_test.dart index 5beaf24622..b97fd250b4 100644 --- a/flutter/test/version_test.dart +++ b/flutter/test/version_test.dart @@ -3,6 +3,7 @@ // found in the LICENSE file. @TestOn('vm') +library flutter_test; import 'dart:io'; diff --git a/flutter/test/view_hierarchy/view_hierarchy_integration_test.dart b/flutter/test/view_hierarchy/view_hierarchy_integration_test.dart index 580d2672ca..bef4050c6e 100644 --- a/flutter/test/view_hierarchy/view_hierarchy_integration_test.dart +++ b/flutter/test/view_hierarchy/view_hierarchy_integration_test.dart @@ -1,4 +1,5 @@ @TestOn('vm') +library flutter_test; import 'package:flutter_test/flutter_test.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; From 43abc4fd929361a54f3e4ba1570914ec882272fa Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 7 Jun 2024 10:55:25 +0200 Subject: [PATCH 197/237] chore: update metrics/flutter.properties to 3.22.2 (#2091) Co-authored-by: GitHub --- metrics/flutter.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/metrics/flutter.properties b/metrics/flutter.properties index ac97c1a7db..a218c6f206 100644 --- a/metrics/flutter.properties +++ b/metrics/flutter.properties @@ -1,2 +1,2 @@ -version = 3.22.1 +version = 3.22.2 repo = https://github.com/flutter/flutter From 56884880239f163a7b829a154e888e04ff976260 Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Mon, 10 Jun 2024 11:44:53 +0200 Subject: [PATCH 198/237] fix: sqflite min version (#2075) * Update * Update CHANGELOG * update * Update CHANGELOG * test * Update * Update * Update --- CHANGELOG.md | 2 ++ sqflite/pubspec.yaml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index de3a68db32..84be6e52b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ ### Dependencies +- Bump `sqflite` minimum version from `^2.0.0` to `^2.2.8` ([#2075](https://github.com/getsentry/sentry-dart/pull/2075)) + - This is not a breaking change since we are using api internally that is only valid from that version. - Bump Cocoa SDK from v8.25.2 to v8.26.0 ([#2060](https://github.com/getsentry/sentry-dart/pull/2060)) - [changelog](https://github.com/getsentry/sentry-cocoa/blob/main/CHANGELOG.md#8260) - [diff](https://github.com/getsentry/sentry-cocoa/compare/8.25.2...8.26.0) diff --git a/sqflite/pubspec.yaml b/sqflite/pubspec.yaml index a80b04a90b..dfef6ff496 100644 --- a/sqflite/pubspec.yaml +++ b/sqflite/pubspec.yaml @@ -16,7 +16,7 @@ platforms: dependencies: sentry: 8.2.0 - sqflite: ^2.0.0 + sqflite: ^2.2.8 sqflite_common: ^2.0.0 meta: ^1.3.0 path: ^1.8.3 From 997379dad4250457cb83e1df37aacefdafbba769 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 10 Jun 2024 11:45:37 +0200 Subject: [PATCH 199/237] chore(deps): update Cocoa SDK to v8.28.0 (#2092) * chore: update flutter/scripts/update-cocoa.sh to 8.28.0 * Format --------- Co-authored-by: GitHub Co-authored-by: GIancarlo Buenaflor --- CHANGELOG.md | 6 +- flutter/ios/sentry_flutter.podspec | 2 +- flutter/lib/src/native/cocoa/binding.dart | 219 ++++++++++------------ 3 files changed, 106 insertions(+), 121 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 84be6e52b4..053569f3e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,9 +11,9 @@ - Bump `sqflite` minimum version from `^2.0.0` to `^2.2.8` ([#2075](https://github.com/getsentry/sentry-dart/pull/2075)) - This is not a breaking change since we are using api internally that is only valid from that version. -- Bump Cocoa SDK from v8.25.2 to v8.26.0 ([#2060](https://github.com/getsentry/sentry-dart/pull/2060)) - - [changelog](https://github.com/getsentry/sentry-cocoa/blob/main/CHANGELOG.md#8260) - - [diff](https://github.com/getsentry/sentry-cocoa/compare/8.25.2...8.26.0) +- Bump Cocoa SDK from v8.25.2 to v8.28.0 ([#2060](https://github.com/getsentry/sentry-dart/pull/2060), [#2092](https://github.com/getsentry/sentry-dart/pull/2092)) + - [changelog](https://github.com/getsentry/sentry-cocoa/blob/main/CHANGELOG.md#8280) + - [diff](https://github.com/getsentry/sentry-cocoa/compare/8.25.2...8.28.0) ## 8.2.0 diff --git a/flutter/ios/sentry_flutter.podspec b/flutter/ios/sentry_flutter.podspec index 5a37c01cf9..72c362696d 100644 --- a/flutter/ios/sentry_flutter.podspec +++ b/flutter/ios/sentry_flutter.podspec @@ -16,7 +16,7 @@ Sentry SDK for Flutter with support to native through sentry-cocoa. :tag => s.version.to_s } s.source_files = 'Classes/**/*' s.public_header_files = 'Classes/**/*.h' - s.dependency 'Sentry/HybridSDK', '8.26.0' + s.dependency 'Sentry/HybridSDK', '8.28.0' s.ios.dependency 'Flutter' s.osx.dependency 'FlutterMacOS' s.ios.deployment_target = '12.0' diff --git a/flutter/lib/src/native/cocoa/binding.dart b/flutter/lib/src/native/cocoa/binding.dart index b6667b174b..b044047dc1 100644 --- a/flutter/lib/src/native/cocoa/binding.dart +++ b/flutter/lib/src/native/cocoa/binding.dart @@ -6038,19 +6038,41 @@ class SentryCocoa { _registerName1("fileSystemRepresentation"); late final _sel_isFileURL1 = _registerName1("isFileURL"); late final _sel_standardizedURL1 = _registerName1("standardizedURL"); + late final _sel_checkResourceIsReachableAndReturnError_1 = + _registerName1("checkResourceIsReachableAndReturnError:"); + bool _objc_msgSend_225( + ffi.Pointer obj, + ffi.Pointer sel, + ffi.Pointer> error, + ) { + return __objc_msgSend_225( + obj, + sel, + error, + ); + } + + late final __objc_msgSend_225Ptr = _lookup< + ffi.NativeFunction< + ffi.Bool Function(ffi.Pointer, ffi.Pointer, + ffi.Pointer>)>>('objc_msgSend'); + late final __objc_msgSend_225 = __objc_msgSend_225Ptr.asFunction< + bool Function(ffi.Pointer, ffi.Pointer, + ffi.Pointer>)>(); + late final _sel_isFileReferenceURL1 = _registerName1("isFileReferenceURL"); late final _sel_fileReferenceURL1 = _registerName1("fileReferenceURL"); late final _sel_filePathURL1 = _registerName1("filePathURL"); late final _sel_getResourceValue_forKey_error_1 = _registerName1("getResourceValue:forKey:error:"); - bool _objc_msgSend_225( + bool _objc_msgSend_226( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer> value, ffi.Pointer key, ffi.Pointer> error, ) { - return __objc_msgSend_225( + return __objc_msgSend_226( obj, sel, value, @@ -6059,7 +6081,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_225Ptr = _lookup< + late final __objc_msgSend_226Ptr = _lookup< ffi.NativeFunction< ffi.Bool Function( ffi.Pointer, @@ -6067,7 +6089,7 @@ class SentryCocoa { ffi.Pointer>, ffi.Pointer, ffi.Pointer>)>>('objc_msgSend'); - late final __objc_msgSend_225 = __objc_msgSend_225Ptr.asFunction< + late final __objc_msgSend_226 = __objc_msgSend_226Ptr.asFunction< bool Function( ffi.Pointer, ffi.Pointer, @@ -6077,13 +6099,13 @@ class SentryCocoa { late final _sel_resourceValuesForKeys_error_1 = _registerName1("resourceValuesForKeys:error:"); - ffi.Pointer _objc_msgSend_226( + ffi.Pointer _objc_msgSend_227( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer keys, ffi.Pointer> error, ) { - return __objc_msgSend_226( + return __objc_msgSend_227( obj, sel, keys, @@ -6091,14 +6113,14 @@ class SentryCocoa { ); } - late final __objc_msgSend_226Ptr = _lookup< + late final __objc_msgSend_227Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer>)>>('objc_msgSend'); - late final __objc_msgSend_226 = __objc_msgSend_226Ptr.asFunction< + late final __objc_msgSend_227 = __objc_msgSend_227Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, @@ -6107,14 +6129,14 @@ class SentryCocoa { late final _sel_setResourceValue_forKey_error_1 = _registerName1("setResourceValue:forKey:error:"); - bool _objc_msgSend_227( + bool _objc_msgSend_228( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer value, ffi.Pointer key, ffi.Pointer> error, ) { - return __objc_msgSend_227( + return __objc_msgSend_228( obj, sel, value, @@ -6123,7 +6145,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_227Ptr = _lookup< + late final __objc_msgSend_228Ptr = _lookup< ffi.NativeFunction< ffi.Bool Function( ffi.Pointer, @@ -6131,7 +6153,7 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Pointer>)>>('objc_msgSend'); - late final __objc_msgSend_227 = __objc_msgSend_227Ptr.asFunction< + late final __objc_msgSend_228 = __objc_msgSend_228Ptr.asFunction< bool Function( ffi.Pointer, ffi.Pointer, @@ -6141,13 +6163,13 @@ class SentryCocoa { late final _sel_setResourceValues_error_1 = _registerName1("setResourceValues:error:"); - bool _objc_msgSend_228( + bool _objc_msgSend_229( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer keyedValues, ffi.Pointer> error, ) { - return __objc_msgSend_228( + return __objc_msgSend_229( obj, sel, keyedValues, @@ -6155,14 +6177,14 @@ class SentryCocoa { ); } - late final __objc_msgSend_228Ptr = _lookup< + late final __objc_msgSend_229Ptr = _lookup< ffi.NativeFunction< ffi.Bool Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer>)>>('objc_msgSend'); - late final __objc_msgSend_228 = __objc_msgSend_228Ptr.asFunction< + late final __objc_msgSend_229 = __objc_msgSend_229Ptr.asFunction< bool Function(ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer>)>(); @@ -6175,7 +6197,7 @@ class SentryCocoa { late final _sel_bookmarkDataWithOptions_includingResourceValuesForKeys_relativeToURL_error_1 = _registerName1( "bookmarkDataWithOptions:includingResourceValuesForKeys:relativeToURL:error:"); - ffi.Pointer _objc_msgSend_229( + ffi.Pointer _objc_msgSend_230( ffi.Pointer obj, ffi.Pointer sel, int options, @@ -6183,7 +6205,7 @@ class SentryCocoa { ffi.Pointer relativeURL, ffi.Pointer> error, ) { - return __objc_msgSend_229( + return __objc_msgSend_230( obj, sel, options, @@ -6193,7 +6215,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_229Ptr = _lookup< + late final __objc_msgSend_230Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, @@ -6202,7 +6224,7 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Pointer>)>>('objc_msgSend'); - late final __objc_msgSend_229 = __objc_msgSend_229Ptr.asFunction< + late final __objc_msgSend_230 = __objc_msgSend_230Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, @@ -6214,7 +6236,7 @@ class SentryCocoa { late final _sel_initByResolvingBookmarkData_options_relativeToURL_bookmarkDataIsStale_error_1 = _registerName1( "initByResolvingBookmarkData:options:relativeToURL:bookmarkDataIsStale:error:"); - instancetype _objc_msgSend_230( + instancetype _objc_msgSend_231( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer bookmarkData, @@ -6223,7 +6245,7 @@ class SentryCocoa { ffi.Pointer isStale, ffi.Pointer> error, ) { - return __objc_msgSend_230( + return __objc_msgSend_231( obj, sel, bookmarkData, @@ -6234,7 +6256,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_230Ptr = _lookup< + late final __objc_msgSend_231Ptr = _lookup< ffi.NativeFunction< instancetype Function( ffi.Pointer, @@ -6244,7 +6266,7 @@ class SentryCocoa { ffi.Pointer, ffi.Pointer, ffi.Pointer>)>>('objc_msgSend'); - late final __objc_msgSend_230 = __objc_msgSend_230Ptr.asFunction< + late final __objc_msgSend_231 = __objc_msgSend_231Ptr.asFunction< instancetype Function( ffi.Pointer, ffi.Pointer, @@ -6259,13 +6281,13 @@ class SentryCocoa { "URLByResolvingBookmarkData:options:relativeToURL:bookmarkDataIsStale:error:"); late final _sel_resourceValuesForKeys_fromBookmarkData_1 = _registerName1("resourceValuesForKeys:fromBookmarkData:"); - ffi.Pointer _objc_msgSend_231( + ffi.Pointer _objc_msgSend_232( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer keys, ffi.Pointer bookmarkData, ) { - return __objc_msgSend_231( + return __objc_msgSend_232( obj, sel, keys, @@ -6273,14 +6295,14 @@ class SentryCocoa { ); } - late final __objc_msgSend_231Ptr = _lookup< + late final __objc_msgSend_232Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer)>>('objc_msgSend'); - late final __objc_msgSend_231 = __objc_msgSend_231Ptr.asFunction< + late final __objc_msgSend_232 = __objc_msgSend_232Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, @@ -6289,7 +6311,7 @@ class SentryCocoa { late final _sel_writeBookmarkData_toURL_options_error_1 = _registerName1("writeBookmarkData:toURL:options:error:"); - bool _objc_msgSend_232( + bool _objc_msgSend_233( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer bookmarkData, @@ -6297,7 +6319,7 @@ class SentryCocoa { int options, ffi.Pointer> error, ) { - return __objc_msgSend_232( + return __objc_msgSend_233( obj, sel, bookmarkData, @@ -6307,7 +6329,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_232Ptr = _lookup< + late final __objc_msgSend_233Ptr = _lookup< ffi.NativeFunction< ffi.Bool Function( ffi.Pointer, @@ -6316,7 +6338,7 @@ class SentryCocoa { ffi.Pointer, ffi.UnsignedLong, ffi.Pointer>)>>('objc_msgSend'); - late final __objc_msgSend_232 = __objc_msgSend_232Ptr.asFunction< + late final __objc_msgSend_233 = __objc_msgSend_233Ptr.asFunction< bool Function( ffi.Pointer, ffi.Pointer, @@ -6327,13 +6349,13 @@ class SentryCocoa { late final _sel_bookmarkDataWithContentsOfURL_error_1 = _registerName1("bookmarkDataWithContentsOfURL:error:"); - ffi.Pointer _objc_msgSend_233( + ffi.Pointer _objc_msgSend_234( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer bookmarkFileURL, ffi.Pointer> error, ) { - return __objc_msgSend_233( + return __objc_msgSend_234( obj, sel, bookmarkFileURL, @@ -6341,14 +6363,14 @@ class SentryCocoa { ); } - late final __objc_msgSend_233Ptr = _lookup< + late final __objc_msgSend_234Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer>)>>('objc_msgSend'); - late final __objc_msgSend_233 = __objc_msgSend_233Ptr.asFunction< + late final __objc_msgSend_234 = __objc_msgSend_234Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, @@ -6357,14 +6379,14 @@ class SentryCocoa { late final _sel_URLByResolvingAliasFileAtURL_options_error_1 = _registerName1("URLByResolvingAliasFileAtURL:options:error:"); - instancetype _objc_msgSend_234( + instancetype _objc_msgSend_235( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer url, int options, ffi.Pointer> error, ) { - return __objc_msgSend_234( + return __objc_msgSend_235( obj, sel, url, @@ -6373,7 +6395,7 @@ class SentryCocoa { ); } - late final __objc_msgSend_234Ptr = _lookup< + late final __objc_msgSend_235Ptr = _lookup< ffi.NativeFunction< instancetype Function( ffi.Pointer, @@ -6381,7 +6403,7 @@ class SentryCocoa { ffi.Pointer, ffi.Int32, ffi.Pointer>)>>('objc_msgSend'); - late final __objc_msgSend_234 = __objc_msgSend_234Ptr.asFunction< + late final __objc_msgSend_235 = __objc_msgSend_235Ptr.asFunction< instancetype Function( ffi.Pointer, ffi.Pointer, @@ -6397,13 +6419,13 @@ class SentryCocoa { _registerName1("getPromisedItemResourceValue:forKey:error:"); late final _sel_promisedItemResourceValuesForKeys_error_1 = _registerName1("promisedItemResourceValuesForKeys:error:"); - ffi.Pointer _objc_msgSend_235( + ffi.Pointer _objc_msgSend_236( ffi.Pointer obj, ffi.Pointer sel, ffi.Pointer keys, ffi.Pointer> error, ) { - return __objc_msgSend_235( + return __objc_msgSend_236( obj, sel, keys, @@ -6411,14 +6433,14 @@ class SentryCocoa { ); } - late final __objc_msgSend_235Ptr = _lookup< + late final __objc_msgSend_236Ptr = _lookup< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, ffi.Pointer>)>>('objc_msgSend'); - late final __objc_msgSend_235 = __objc_msgSend_235Ptr.asFunction< + late final __objc_msgSend_236 = __objc_msgSend_236Ptr.asFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, @@ -6427,26 +6449,6 @@ class SentryCocoa { late final _sel_checkPromisedItemIsReachableAndReturnError_1 = _registerName1("checkPromisedItemIsReachableAndReturnError:"); - bool _objc_msgSend_236( - ffi.Pointer obj, - ffi.Pointer sel, - ffi.Pointer> error, - ) { - return __objc_msgSend_236( - obj, - sel, - error, - ); - } - - late final __objc_msgSend_236Ptr = _lookup< - ffi.NativeFunction< - ffi.Bool Function(ffi.Pointer, ffi.Pointer, - ffi.Pointer>)>>('objc_msgSend'); - late final __objc_msgSend_236 = __objc_msgSend_236Ptr.asFunction< - bool Function(ffi.Pointer, ffi.Pointer, - ffi.Pointer>)>(); - late final _sel_fileURLWithPathComponents_1 = _registerName1("fileURLWithPathComponents:"); ffi.Pointer _objc_msgSend_237( @@ -6482,8 +6484,6 @@ class SentryCocoa { _registerName1("URLByAppendingPathExtension:"); late final _sel_URLByDeletingPathExtension1 = _registerName1("URLByDeletingPathExtension"); - late final _sel_checkResourceIsReachableAndReturnError_1 = - _registerName1("checkResourceIsReachableAndReturnError:"); late final _sel_URLByStandardizingPath1 = _registerName1("URLByStandardizingPath"); late final _sel_URLByResolvingSymlinksInPath1 = @@ -22996,8 +22996,6 @@ class SentryCocoa { _registerName1("prefersIncrementalDelivery"); late final _sel_setPrefersIncrementalDelivery_1 = _registerName1("setPrefersIncrementalDelivery:"); - late final _sel_getGraphQLOperationName1 = - _registerName1("getGraphQLOperationName"); late final _sel_storeCookies_forTask_1 = _registerName1("storeCookies:forTask:"); void _objc_msgSend_804( @@ -28723,10 +28721,6 @@ class SentryCocoa { late final _sel_currentDirectoryURL1 = _registerName1("currentDirectoryURL"); late final _sel_setCurrentDirectoryURL_1 = _registerName1("setCurrentDirectoryURL:"); - late final _sel_launchRequirementData1 = - _registerName1("launchRequirementData"); - late final _sel_setLaunchRequirementData_1 = - _registerName1("setLaunchRequirementData:"); late final _sel_standardInput1 = _registerName1("standardInput"); late final _sel_setStandardInput_1 = _registerName1("setStandardInput:"); late final _sel_standardOutput1 = _registerName1("standardOutput"); @@ -30071,6 +30065,8 @@ class SentryCocoa { _registerName1("appStartMeasurementHybridSDKMode"); late final _sel_setAppStartMeasurementHybridSDKMode_1 = _registerName1("setAppStartMeasurementHybridSDKMode:"); + late final _sel_appStartMeasurementWithSpans1 = + _registerName1("appStartMeasurementWithSpans"); late final _class_SentryUser1 = _getClass1("SentryUser"); late final _sel_userWithDictionary_1 = _registerName1("userWithDictionary:"); ffi.Pointer _objc_msgSend_1060( @@ -30664,7 +30660,7 @@ class NSObject extends _ObjCWrapper { bool validateValue_forKey_error_(ffi.Pointer> ioValue, NSString? inKey, ffi.Pointer> outError) { - return _lib._objc_msgSend_225(_id, _lib._sel_validateValue_forKey_error_1, + return _lib._objc_msgSend_226(_id, _lib._sel_validateValue_forKey_error_1, ioValue, inKey?._id ?? ffi.nullptr, outError); } @@ -30701,7 +30697,7 @@ class NSObject extends _ObjCWrapper { ffi.Pointer> ioValue, NSString? inKeyPath, ffi.Pointer> outError) { - return _lib._objc_msgSend_225( + return _lib._objc_msgSend_226( _id, _lib._sel_validateValue_forKeyPath_error_1, ioValue, @@ -34813,6 +34809,12 @@ class NSURL extends NSObject { : NSURL._(_ret, _lib, retain: true, release: true); } + bool checkResourceIsReachableAndReturnError_( + ffi.Pointer> error) { + return _lib._objc_msgSend_225( + _id, _lib._sel_checkResourceIsReachableAndReturnError_1, error); + } + bool isFileReferenceURL() { return _lib._objc_msgSend_12(_id, _lib._sel_isFileReferenceURL1); } @@ -34833,13 +34835,13 @@ class NSURL extends NSObject { ffi.Pointer> value, NSString key, ffi.Pointer> error) { - return _lib._objc_msgSend_225( + return _lib._objc_msgSend_226( _id, _lib._sel_getResourceValue_forKey_error_1, value, key._id, error); } NSObject resourceValuesForKeys_error_( NSArray? keys, ffi.Pointer> error) { - final _ret = _lib._objc_msgSend_226( + final _ret = _lib._objc_msgSend_227( _id, _lib._sel_resourceValuesForKeys_error_1, keys?._id ?? ffi.nullptr, @@ -34849,13 +34851,13 @@ class NSURL extends NSObject { bool setResourceValue_forKey_error_(NSObject value, NSString key, ffi.Pointer> error) { - return _lib._objc_msgSend_227(_id, + return _lib._objc_msgSend_228(_id, _lib._sel_setResourceValue_forKey_error_1, value._id, key._id, error); } bool setResourceValues_error_( NSObject? keyedValues, ffi.Pointer> error) { - return _lib._objc_msgSend_228(_id, _lib._sel_setResourceValues_error_1, + return _lib._objc_msgSend_229(_id, _lib._sel_setResourceValues_error_1, keyedValues?._id ?? ffi.nullptr, error); } @@ -34879,7 +34881,7 @@ class NSURL extends NSObject { NSArray? keys, NSURL? relativeURL, ffi.Pointer> error) { - final _ret = _lib._objc_msgSend_229( + final _ret = _lib._objc_msgSend_230( _id, _lib._sel_bookmarkDataWithOptions_includingResourceValuesForKeys_relativeToURL_error_1, options, @@ -34896,7 +34898,7 @@ class NSURL extends NSObject { NSURL? relativeURL, ffi.Pointer isStale, ffi.Pointer> error) { - final _ret = _lib._objc_msgSend_230( + final _ret = _lib._objc_msgSend_231( _id, _lib._sel_initByResolvingBookmarkData_options_relativeToURL_bookmarkDataIsStale_error_1, bookmarkData?._id ?? ffi.nullptr, @@ -34915,7 +34917,7 @@ class NSURL extends NSObject { NSURL? relativeURL, ffi.Pointer isStale, ffi.Pointer> error) { - final _ret = _lib._objc_msgSend_230( + final _ret = _lib._objc_msgSend_231( _lib._class_NSURL1, _lib._sel_URLByResolvingBookmarkData_options_relativeToURL_bookmarkDataIsStale_error_1, bookmarkData?._id ?? ffi.nullptr, @@ -34928,7 +34930,7 @@ class NSURL extends NSObject { static NSObject resourceValuesForKeys_fromBookmarkData_( SentryCocoa _lib, NSArray? keys, NSData? bookmarkData) { - final _ret = _lib._objc_msgSend_231( + final _ret = _lib._objc_msgSend_232( _lib._class_NSURL1, _lib._sel_resourceValuesForKeys_fromBookmarkData_1, keys?._id ?? ffi.nullptr, @@ -34942,7 +34944,7 @@ class NSURL extends NSObject { NSURL? bookmarkFileURL, int options, ffi.Pointer> error) { - return _lib._objc_msgSend_232( + return _lib._objc_msgSend_233( _lib._class_NSURL1, _lib._sel_writeBookmarkData_toURL_options_error_1, bookmarkData?._id ?? ffi.nullptr, @@ -34953,7 +34955,7 @@ class NSURL extends NSObject { static NSData bookmarkDataWithContentsOfURL_error_(SentryCocoa _lib, NSURL? bookmarkFileURL, ffi.Pointer> error) { - final _ret = _lib._objc_msgSend_233( + final _ret = _lib._objc_msgSend_234( _lib._class_NSURL1, _lib._sel_bookmarkDataWithContentsOfURL_error_1, bookmarkFileURL?._id ?? ffi.nullptr, @@ -34963,7 +34965,7 @@ class NSURL extends NSObject { static NSURL URLByResolvingAliasFileAtURL_options_error_(SentryCocoa _lib, NSURL? url, int options, ffi.Pointer> error) { - final _ret = _lib._objc_msgSend_234( + final _ret = _lib._objc_msgSend_235( _lib._class_NSURL1, _lib._sel_URLByResolvingAliasFileAtURL_options_error_1, url?._id ?? ffi.nullptr, @@ -34985,7 +34987,7 @@ class NSURL extends NSObject { ffi.Pointer> value, NSString key, ffi.Pointer> error) { - return _lib._objc_msgSend_225( + return _lib._objc_msgSend_226( _id, _lib._sel_getPromisedItemResourceValue_forKey_error_1, value, @@ -34995,7 +34997,7 @@ class NSURL extends NSObject { NSDictionary promisedItemResourceValuesForKeys_error_( NSArray? keys, ffi.Pointer> error) { - final _ret = _lib._objc_msgSend_235( + final _ret = _lib._objc_msgSend_236( _id, _lib._sel_promisedItemResourceValuesForKeys_error_1, keys?._id ?? ffi.nullptr, @@ -35005,7 +35007,7 @@ class NSURL extends NSObject { bool checkPromisedItemIsReachableAndReturnError_( ffi.Pointer> error) { - return _lib._objc_msgSend_236( + return _lib._objc_msgSend_225( _id, _lib._sel_checkPromisedItemIsReachableAndReturnError_1, error); } @@ -35079,12 +35081,6 @@ class NSURL extends NSObject { : NSURL._(_ret, _lib, retain: true, release: true); } - bool checkResourceIsReachableAndReturnError_( - ffi.Pointer> error) { - return _lib._objc_msgSend_236( - _id, _lib._sel_checkResourceIsReachableAndReturnError_1, error); - } - NSURL? get URLByStandardizingPath { final _ret = _lib._objc_msgSend_40(_id, _lib._sel_URLByStandardizingPath1); return _ret.address == 0 @@ -52181,12 +52177,12 @@ class NSBundle extends NSObject { } bool preflightAndReturnError_(ffi.Pointer> error) { - return _lib._objc_msgSend_236( + return _lib._objc_msgSend_225( _id, _lib._sel_preflightAndReturnError_1, error); } bool loadAndReturnError_(ffi.Pointer> error) { - return _lib._objc_msgSend_236(_id, _lib._sel_loadAndReturnError_1, error); + return _lib._objc_msgSend_225(_id, _lib._sel_loadAndReturnError_1, error); } NSURL? get bundleURL { @@ -57375,12 +57371,12 @@ class NSFileHandle extends NSObject { } bool synchronizeAndReturnError_(ffi.Pointer> error) { - return _lib._objc_msgSend_236( + return _lib._objc_msgSend_225( _id, _lib._sel_synchronizeAndReturnError_1, error); } bool closeAndReturnError_(ffi.Pointer> error) { - return _lib._objc_msgSend_236(_id, _lib._sel_closeAndReturnError_1, error); + return _lib._objc_msgSend_225(_id, _lib._sel_closeAndReturnError_1, error); } static NSFileHandle? getFileHandleWithStandardInput(SentryCocoa _lib) { @@ -58360,11 +58356,6 @@ class NSURLSessionTask extends NSObject { return NSURLSessionTask._(_ret, _lib, retain: false, release: true); } - NSString getGraphQLOperationName() { - final _ret = _lib._objc_msgSend_20(_id, _lib._sel_getGraphQLOperationName1); - return NSString._(_ret, _lib, retain: true, release: true); - } - static NSURLSessionTask allocWithZone_( SentryCocoa _lib, ffi.Pointer<_NSZone> zone) { final _ret = _lib._objc_msgSend_3( @@ -68296,18 +68287,6 @@ class NSTask extends NSObject { _id, _lib._sel_setCurrentDirectoryURL_1, value?._id ?? ffi.nullptr); } - NSData? get launchRequirementData { - final _ret = _lib._objc_msgSend_39(_id, _lib._sel_launchRequirementData1); - return _ret.address == 0 - ? null - : NSData._(_ret, _lib, retain: true, release: true); - } - - set launchRequirementData(NSData? value) { - return _lib._objc_msgSend_939( - _id, _lib._sel_setLaunchRequirementData_1, value?._id ?? ffi.nullptr); - } - NSObject get standardInput { final _ret = _lib._objc_msgSend_2(_id, _lib._sel_standardInput1); return NSObject._(_ret, _lib, retain: true, release: true); @@ -68337,7 +68316,7 @@ class NSTask extends NSObject { } bool launchAndReturnError_(ffi.Pointer> error) { - return _lib._objc_msgSend_236(_id, _lib._sel_launchAndReturnError_1, error); + return _lib._objc_msgSend_225(_id, _lib._sel_launchAndReturnError_1, error); } void interrupt() { @@ -69754,7 +69733,7 @@ class NSXMLDocument extends NSXMLNode { } bool validateAndReturnError_(ffi.Pointer> error) { - return _lib._objc_msgSend_236( + return _lib._objc_msgSend_225( _id, _lib._sel_validateAndReturnError_1, error); } @@ -70898,6 +70877,12 @@ class PrivateSentrySDKOnly extends NSObject { _lib._sel_setAppStartMeasurementHybridSDKMode_1, value); } + static NSDictionary appStartMeasurementWithSpans(SentryCocoa _lib) { + final _ret = _lib._objc_msgSend_170(_lib._class_PrivateSentrySDKOnly1, + _lib._sel_appStartMeasurementWithSpans1); + return NSDictionary._(_ret, _lib, retain: true, release: true); + } + static SentryUser userWithDictionary_( SentryCocoa _lib, NSDictionary? dictionary) { final _ret = _lib._objc_msgSend_1060(_lib._class_PrivateSentrySDKOnly1, From 5f443ded4b165e2ece43e774c26e16e1eb5f0b97 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 10 Jun 2024 11:56:37 +0200 Subject: [PATCH 200/237] chore: update flutter/scripts/update-android.sh to 7.10.0 (#2090) Co-authored-by: GitHub --- CHANGELOG.md | 3 +++ flutter/android/build.gradle | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 053569f3e4..993efc93f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,9 @@ - Bump Cocoa SDK from v8.25.2 to v8.28.0 ([#2060](https://github.com/getsentry/sentry-dart/pull/2060), [#2092](https://github.com/getsentry/sentry-dart/pull/2092)) - [changelog](https://github.com/getsentry/sentry-cocoa/blob/main/CHANGELOG.md#8280) - [diff](https://github.com/getsentry/sentry-cocoa/compare/8.25.2...8.28.0) +- Bump Android SDK from v7.9.0 to v7.10.0 ([#2090](https://github.com/getsentry/sentry-dart/pull/2090)) + - [changelog](https://github.com/getsentry/sentry-java/blob/main/CHANGELOG.md#7100) + - [diff](https://github.com/getsentry/sentry-java/compare/7.9.0...7.10.0) ## 8.2.0 diff --git a/flutter/android/build.gradle b/flutter/android/build.gradle index eb9411b783..89146e73ff 100644 --- a/flutter/android/build.gradle +++ b/flutter/android/build.gradle @@ -60,7 +60,7 @@ android { } dependencies { - api 'io.sentry:sentry-android:7.9.0' + api 'io.sentry:sentry-android:7.10.0' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" // Required -- JUnit 4 framework From d979c86b139b28dfeb5aa719230cd0c68d8b74e3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 10 Jun 2024 11:56:45 +0200 Subject: [PATCH 201/237] chore: update scripts/update-symbol-collector.sh to 1.18.0 (#2081) Co-authored-by: GitHub --- .../flutter_symbol_collector/lib/src/symbol_collector_cli.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/flutter_symbol_collector/lib/src/symbol_collector_cli.dart b/scripts/flutter_symbol_collector/lib/src/symbol_collector_cli.dart index 4308921cdc..c67b0208bc 100644 --- a/scripts/flutter_symbol_collector/lib/src/symbol_collector_cli.dart +++ b/scripts/flutter_symbol_collector/lib/src/symbol_collector_cli.dart @@ -19,7 +19,7 @@ class SymbolCollectorCli { // https://github.com/getsentry/symbol-collector/releases @internal - static const version = '1.17.0'; + static const version = '1.18.0'; @internal late final String cli; From 71ba27c29d43edbc717247e0ec4f0a48e34434d1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:06:55 +0200 Subject: [PATCH 202/237] build(deps): bump lints from 3.0.0 to 4.0.0 in /sqflite (#2056) * build(deps): bump lints from 3.0.0 to 4.0.0 in /sqflite Bumps [lints](https://github.com/dart-lang/lints) from 3.0.0 to 4.0.0. - [Release notes](https://github.com/dart-lang/lints/releases) - [Changelog](https://github.com/dart-lang/lints/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/lints/compare/v3.0.0...v4.0.0) --- updated-dependencies: - dependency-name: lints dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] * Update --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: GIancarlo Buenaflor --- sqflite/pubspec.yaml | 2 +- sqflite/test/sentry_batch_test.dart | 1 + sqflite/test/sentry_database_test.dart | 1 + sqflite/test/sentry_sqflite_database_factory_dart_test.dart | 1 + sqflite/test/sentry_sqflite_test.dart | 1 + sqflite/test/version_test.dart | 1 + 6 files changed, 6 insertions(+), 1 deletion(-) diff --git a/sqflite/pubspec.yaml b/sqflite/pubspec.yaml index dfef6ff496..491b0b2016 100644 --- a/sqflite/pubspec.yaml +++ b/sqflite/pubspec.yaml @@ -22,7 +22,7 @@ dependencies: path: ^1.8.3 dev_dependencies: - lints: ^3.0.0 + lints: ^4.0.0 flutter_test: sdk: flutter coverage: ^1.3.0 diff --git a/sqflite/test/sentry_batch_test.dart b/sqflite/test/sentry_batch_test.dart index b9c53b8762..4a5062f2a2 100644 --- a/sqflite/test/sentry_batch_test.dart +++ b/sqflite/test/sentry_batch_test.dart @@ -1,4 +1,5 @@ @TestOn('vm') +library sqflite_test; import 'package:sentry/sentry.dart'; import 'package:sentry_sqflite/sentry_sqflite.dart'; diff --git a/sqflite/test/sentry_database_test.dart b/sqflite/test/sentry_database_test.dart index 492da311df..93b258b20f 100644 --- a/sqflite/test/sentry_database_test.dart +++ b/sqflite/test/sentry_database_test.dart @@ -1,4 +1,5 @@ @TestOn('vm') +library sqflite_test; import 'package:sentry/sentry.dart'; import 'package:sentry/src/sentry_tracer.dart'; diff --git a/sqflite/test/sentry_sqflite_database_factory_dart_test.dart b/sqflite/test/sentry_sqflite_database_factory_dart_test.dart index 9eeac66734..061660884f 100644 --- a/sqflite/test/sentry_sqflite_database_factory_dart_test.dart +++ b/sqflite/test/sentry_sqflite_database_factory_dart_test.dart @@ -1,4 +1,5 @@ @TestOn('vm') +library sqflite_test; import 'package:sentry/sentry.dart'; import 'package:sentry/src/sentry_tracer.dart'; diff --git a/sqflite/test/sentry_sqflite_test.dart b/sqflite/test/sentry_sqflite_test.dart index 27851881b0..41aa3277b9 100644 --- a/sqflite/test/sentry_sqflite_test.dart +++ b/sqflite/test/sentry_sqflite_test.dart @@ -1,4 +1,5 @@ @TestOn('vm') +library sqflite_test; import 'package:sentry/sentry.dart'; import 'package:sentry_sqflite/sentry_sqflite.dart'; diff --git a/sqflite/test/version_test.dart b/sqflite/test/version_test.dart index fbe3aa0a93..98e02ca499 100644 --- a/sqflite/test/version_test.dart +++ b/sqflite/test/version_test.dart @@ -1,4 +1,5 @@ @TestOn('vm') +library sqflite_test; import 'dart:io'; From 7c827cf855c6bbb87e63b70b7c05d313b43c38a3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 14 Jun 2024 11:21:44 +0200 Subject: [PATCH 203/237] chore: update flutter/scripts/update-cocoa.sh to 8.29.0 (#2100) Co-authored-by: GitHub --- flutter/ios/sentry_flutter.podspec | 2 +- flutter/lib/src/native/cocoa/binding.dart | 27 ++++++++++++++--------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/flutter/ios/sentry_flutter.podspec b/flutter/ios/sentry_flutter.podspec index 72c362696d..bd76cc2f2f 100644 --- a/flutter/ios/sentry_flutter.podspec +++ b/flutter/ios/sentry_flutter.podspec @@ -16,7 +16,7 @@ Sentry SDK for Flutter with support to native through sentry-cocoa. :tag => s.version.to_s } s.source_files = 'Classes/**/*' s.public_header_files = 'Classes/**/*.h' - s.dependency 'Sentry/HybridSDK', '8.28.0' + s.dependency 'Sentry/HybridSDK', '8.29.0' s.ios.dependency 'Flutter' s.osx.dependency 'FlutterMacOS' s.ios.deployment_target = '12.0' diff --git a/flutter/lib/src/native/cocoa/binding.dart b/flutter/lib/src/native/cocoa/binding.dart index b044047dc1..de07238260 100644 --- a/flutter/lib/src/native/cocoa/binding.dart +++ b/flutter/lib/src/native/cocoa/binding.dart @@ -37669,7 +37669,8 @@ class ObjCBlock_bool_ObjCObject_ffiUnsignedLong_bool extends _ObjCBlockBase { ObjCBlock_bool_ObjCObject_ffiUnsignedLong_bool.fromFunctionPointer( SentryCocoa lib, ffi.Pointer< - ffi.NativeFunction< + ffi + .NativeFunction< ffi.Bool Function(ffi.Pointer arg0, ffi.UnsignedLong arg1, ffi.Pointer arg2)>> ptr) @@ -42113,15 +42114,17 @@ class ObjCBlock_bool_ObjCObject_bool extends _ObjCBlockBase { ffi.Pointer arg1)>> ptr) : this._( - lib._newBlock1( - _cFuncTrampoline ??= ffi.Pointer.fromFunction< - ffi.Bool Function( - ffi.Pointer<_ObjCBlock> block, - ffi.Pointer arg0, - ffi.Pointer arg1)>( - _ObjCBlock_bool_ObjCObject_bool_fnPtrTrampoline, false) - .cast(), - ptr.cast()), + lib + ._newBlock1( + _cFuncTrampoline ??= ffi.Pointer.fromFunction< + ffi.Bool Function( + ffi.Pointer<_ObjCBlock> block, + ffi.Pointer arg0, + ffi.Pointer arg1)>( + _ObjCBlock_bool_ObjCObject_bool_fnPtrTrampoline, + false) + .cast(), + ptr.cast()), lib); static ffi.Pointer? _cFuncTrampoline; @@ -71270,6 +71273,10 @@ class SentryCurrentDateProvider extends NSObject { return _lib._objc_msgSend_1062(_id, _lib._sel_systemTime1); } + double systemUptime() { + return _lib._objc_msgSend_155(_id, _lib._sel_systemUptime1); + } + @override SentryCurrentDateProvider init() { final _ret = _lib._objc_msgSend_2(_id, _lib._sel_init1); From fb389711fbf49f835e0e9480da0d663ec62a071f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Jun 2024 10:23:12 +0200 Subject: [PATCH 204/237] build(deps): bump ScaCap/action-ktlint from 1.8.2 to 1.8.3 (#2095) * build(deps): bump ScaCap/action-ktlint from 1.8.2 to 1.8.3 Bumps [ScaCap/action-ktlint](https://github.com/scacap/action-ktlint) from 1.8.2 to 1.8.3. - [Release notes](https://github.com/scacap/action-ktlint/releases) - [Commits](https://github.com/scacap/action-ktlint/compare/5fdeb923cb8de70cb3ef2cfd853799d430946a5d...7bfa4928cf705b83700c91fecc0e1a3a4c0e99ad) --- updated-dependencies: - dependency-name: ScaCap/action-ktlint dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * format --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor --- .github/workflows/flutter.yml | 2 +- flutter/lib/src/native/cocoa/binding.dart | 23 ++++++++++------------- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/.github/workflows/flutter.yml b/.github/workflows/flutter.yml index e1ec093c2f..f5ef50963a 100644 --- a/.github/workflows/flutter.yml +++ b/.github/workflows/flutter.yml @@ -174,7 +174,7 @@ jobs: - uses: actions/checkout@v4 - name: ktlint - uses: ScaCap/action-ktlint@5fdeb923cb8de70cb3ef2cfd853799d430946a5d # pin@1.8.2 + uses: ScaCap/action-ktlint@7bfa4928cf705b83700c91fecc0e1a3a4c0e99ad # pin@1.8.3 with: github_token: ${{ secrets.github_token }} reporter: github-pr-review diff --git a/flutter/lib/src/native/cocoa/binding.dart b/flutter/lib/src/native/cocoa/binding.dart index de07238260..4af31cfc57 100644 --- a/flutter/lib/src/native/cocoa/binding.dart +++ b/flutter/lib/src/native/cocoa/binding.dart @@ -37669,8 +37669,7 @@ class ObjCBlock_bool_ObjCObject_ffiUnsignedLong_bool extends _ObjCBlockBase { ObjCBlock_bool_ObjCObject_ffiUnsignedLong_bool.fromFunctionPointer( SentryCocoa lib, ffi.Pointer< - ffi - .NativeFunction< + ffi.NativeFunction< ffi.Bool Function(ffi.Pointer arg0, ffi.UnsignedLong arg1, ffi.Pointer arg2)>> ptr) @@ -42114,17 +42113,15 @@ class ObjCBlock_bool_ObjCObject_bool extends _ObjCBlockBase { ffi.Pointer arg1)>> ptr) : this._( - lib - ._newBlock1( - _cFuncTrampoline ??= ffi.Pointer.fromFunction< - ffi.Bool Function( - ffi.Pointer<_ObjCBlock> block, - ffi.Pointer arg0, - ffi.Pointer arg1)>( - _ObjCBlock_bool_ObjCObject_bool_fnPtrTrampoline, - false) - .cast(), - ptr.cast()), + lib._newBlock1( + _cFuncTrampoline ??= ffi.Pointer.fromFunction< + ffi.Bool Function( + ffi.Pointer<_ObjCBlock> block, + ffi.Pointer arg0, + ffi.Pointer arg1)>( + _ObjCBlock_bool_ObjCObject_bool_fnPtrTrampoline, false) + .cast(), + ptr.cast()), lib); static ffi.Pointer? _cFuncTrampoline; From 9e35ce9043a79919c5137346dd707260b99bd418 Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Mon, 17 Jun 2024 10:43:36 +0200 Subject: [PATCH 205/237] Disable (#2101) --- .github/workflows/flutter.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/flutter.yml b/.github/workflows/flutter.yml index f5ef50963a..45bc61a4f8 100644 --- a/.github/workflows/flutter.yml +++ b/.github/workflows/flutter.yml @@ -48,6 +48,10 @@ jobs: os: windows - target: web os: ubuntu + # Exclude beta for windows for now until the flutter set up action does not fail anymore + exclude: + - target: windows + sdk: beta steps: - uses: actions/checkout@v4 From 0b22d2dc91f72a4d74a59ad2290361d4745e6992 Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Mon, 17 Jun 2024 11:21:18 +0200 Subject: [PATCH 206/237] Disable (#2102) --- .github/workflows/drift.yml | 3 +++ .github/workflows/isar.yml | 3 +++ .github/workflows/sqflite.yml | 3 +++ 3 files changed, 9 insertions(+) diff --git a/.github/workflows/drift.yml b/.github/workflows/drift.yml index d728800cae..a07d7e0677 100644 --- a/.github/workflows/drift.yml +++ b/.github/workflows/drift.yml @@ -59,6 +59,9 @@ jobs: # Bad CPU type in executable - os: macos-latest sdk: beta + # Exclude beta for windows for now until the flutter set up action does not fail anymore + - os: windows-latest + sdk: beta steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/isar.yml b/.github/workflows/isar.yml index 54d69b7a4c..35c6ee6540 100644 --- a/.github/workflows/isar.yml +++ b/.github/workflows/isar.yml @@ -59,6 +59,9 @@ jobs: # Bad CPU type in executable - os: macos-latest sdk: beta + # Exclude beta for windows for now until the flutter set up action does not fail anymore + - os: windows-latest + sdk: beta steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/sqflite.yml b/.github/workflows/sqflite.yml index df44cac6d4..77ab71a1db 100644 --- a/.github/workflows/sqflite.yml +++ b/.github/workflows/sqflite.yml @@ -59,6 +59,9 @@ jobs: # Bad CPU type in executable - os: macos-latest sdk: beta + # Exclude beta for windows for now until the flutter set up action does not fail anymore + - os: windows-latest + sdk: beta steps: - uses: actions/checkout@v4 From 3cac5bf6a1ba2d5812330debb5c7b87404609daf Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Mon, 17 Jun 2024 13:31:20 +0200 Subject: [PATCH 207/237] fix: load contexts not setting the user (#2089) * Update * Update CHANGELOG * add test * Update * Add test * Apply formatting --- CHANGELOG.md | 1 + dart/lib/src/sentry_client.dart | 4 +- dart/test/sentry_client_test.dart | 2 + .../load_contexts_integration_test.dart | 39 +++++++++++++++++++ 4 files changed, 44 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 993efc93f9..05bbf107b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### Fixes +- Load contexts integration not setting `SentryUser` ([#2089](https://github.com/getsentry/sentry-dart/pull/2089)) - Change app start span description from `Cold start` to `Cold Start` and `Warm start` to `Warm Start` ([#2076](https://github.com/getsentry/sentry-dart/pull/2076)) - Parse `PlatformException` from details instead of message ([#2052](https://github.com/getsentry/sentry-dart/pull/2052)) diff --git a/dart/lib/src/sentry_client.dart b/dart/lib/src/sentry_client.dart index a1f20ded61..63fcbfb421 100644 --- a/dart/lib/src/sentry_client.dart +++ b/dart/lib/src/sentry_client.dart @@ -119,6 +119,8 @@ class SentryClient { return _sentryId; } + preparedEvent = _createUserOrSetDefaultIpAddress(preparedEvent); + preparedEvent = await _runBeforeSend( preparedEvent, hint, @@ -176,8 +178,6 @@ class SentryClient { platform: event.platform ?? sdkPlatform(_options.platformChecker.isWeb), ); - event = _createUserOrSetDefaultIpAddress(event); - if (event is SentryTransaction) { return event; } diff --git a/dart/test/sentry_client_test.dart b/dart/test/sentry_client_test.dart index b10ae154f7..b8c6bee716 100644 --- a/dart/test/sentry_client_test.dart +++ b/dart/test/sentry_client_test.dart @@ -1684,6 +1684,7 @@ class Fixture { class ExceptionWithCause { ExceptionWithCause(this.cause, this.stackTrace); + final dynamic cause; final dynamic stackTrace; } @@ -1698,6 +1699,7 @@ class ExceptionWithCauseExtractor class ExceptionWithStackTrace { ExceptionWithStackTrace(this.stackTrace); + final StackTrace stackTrace; } diff --git a/flutter/test/integrations/load_contexts_integration_test.dart b/flutter/test/integrations/load_contexts_integration_test.dart index 926d8e09b1..a3bbbcbab7 100644 --- a/flutter/test/integrations/load_contexts_integration_test.dart +++ b/flutter/test/integrations/load_contexts_integration_test.dart @@ -128,6 +128,45 @@ void main() { expect(event.breadcrumbs!.length, 1); expect(event.breadcrumbs!.first.message, 'native-mutated-applied'); }); + + test('apply default IP to user during captureEvent after loading context', + () async { + fixture.options.enableScopeSync = true; + + const expectedIp = '{{auto}}'; + String? actualIp; + + const expectedId = '1'; + String? actualId; + + fixture.options.beforeSend = (event, hint) { + actualIp = event.user?.ipAddress; + actualId = event.user?.id; + return event; + }; + + final options = fixture.options; + + final user = SentryUser(id: expectedId); + Map loadContexts = {'user': user.toJson()}; + final future = Future.value(loadContexts); + when(fixture.methodChannel.invokeMethod('loadContexts')) + .thenAnswer((_) => future); + // ignore: deprecated_member_use + _channel.setMockMethodCallHandler((MethodCall methodCall) async {}); + + final integration = LoadContextsIntegration(fixture.methodChannel); + options.addIntegration(integration); + options.integrations.first.call(fixture.hub, options); + + final client = SentryClient(options); + final event = SentryEvent(); + + await client.captureEvent(event); + + expect(expectedIp, actualIp); + expect(expectedId, actualId); + }); }); } From 292a0a7e3de67e4f8ab39eb35b53245ef2dc0743 Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Mon, 17 Jun 2024 14:32:27 +0200 Subject: [PATCH 208/237] Update CHANGELOG.md (fix ios dep entry) (#2105) --- CHANGELOG.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 05bbf107b6..73e512e794 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,9 +12,9 @@ - Bump `sqflite` minimum version from `^2.0.0` to `^2.2.8` ([#2075](https://github.com/getsentry/sentry-dart/pull/2075)) - This is not a breaking change since we are using api internally that is only valid from that version. -- Bump Cocoa SDK from v8.25.2 to v8.28.0 ([#2060](https://github.com/getsentry/sentry-dart/pull/2060), [#2092](https://github.com/getsentry/sentry-dart/pull/2092)) - - [changelog](https://github.com/getsentry/sentry-cocoa/blob/main/CHANGELOG.md#8280) - - [diff](https://github.com/getsentry/sentry-cocoa/compare/8.25.2...8.28.0) +- Bump Cocoa SDK from v8.25.2 to v8.29.0 ([#2060](https://github.com/getsentry/sentry-dart/pull/2060), [#2092](https://github.com/getsentry/sentry-dart/pull/2092), [#2100](https://github.com/getsentry/sentry-dart/pull/2100)) + - [changelog](https://github.com/getsentry/sentry-cocoa/blob/main/CHANGELOG.md#8290) + - [diff](https://github.com/getsentry/sentry-cocoa/compare/8.25.2...8.29.0) - Bump Android SDK from v7.9.0 to v7.10.0 ([#2090](https://github.com/getsentry/sentry-dart/pull/2090)) - [changelog](https://github.com/getsentry/sentry-java/blob/main/CHANGELOG.md#7100) - [diff](https://github.com/getsentry/sentry-java/compare/7.9.0...7.10.0) From fe0623e4a6b5ccd570dbc388cd86b9ffd38276d6 Mon Sep 17 00:00:00 2001 From: getsentry-bot Date: Mon, 17 Jun 2024 13:22:10 +0000 Subject: [PATCH 209/237] release: 8.3.0 --- CHANGELOG.md | 2 +- dart/lib/src/version.dart | 2 +- dart/pubspec.yaml | 2 +- dio/lib/src/version.dart | 2 +- dio/pubspec.yaml | 4 ++-- drift/lib/src/version.dart | 2 +- drift/pubspec.yaml | 4 ++-- file/lib/src/version.dart | 2 +- file/pubspec.yaml | 4 ++-- flutter/example/pubspec.yaml | 2 +- flutter/lib/src/version.dart | 2 +- flutter/pubspec.yaml | 4 ++-- hive/lib/src/version.dart | 2 +- hive/pubspec.yaml | 4 ++-- isar/lib/src/version.dart | 2 +- isar/pubspec.yaml | 4 ++-- logging/lib/src/version.dart | 2 +- logging/pubspec.yaml | 4 ++-- sqflite/lib/src/version.dart | 2 +- sqflite/pubspec.yaml | 4 ++-- 20 files changed, 28 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 73e512e794..75b24a6314 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## Unreleased +## 8.3.0 ### Fixes diff --git a/dart/lib/src/version.dart b/dart/lib/src/version.dart index 0b1968ecd0..961566fdc3 100644 --- a/dart/lib/src/version.dart +++ b/dart/lib/src/version.dart @@ -9,7 +9,7 @@ library version; /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.2.0'; +const String sdkVersion = '8.3.0'; String sdkName(bool isWeb) => isWeb ? _browserSdkName : _ioSdkName; diff --git a/dart/pubspec.yaml b/dart/pubspec.yaml index efef9ca103..41aa1b7d0c 100644 --- a/dart/pubspec.yaml +++ b/dart/pubspec.yaml @@ -1,5 +1,5 @@ name: sentry -version: 8.2.0 +version: 8.3.0 description: > A crash reporting library for Dart that sends crash reports to Sentry.io. This library supports Dart VM and Web. For Flutter consider sentry_flutter instead. diff --git a/dio/lib/src/version.dart b/dio/lib/src/version.dart index b8d675e478..4b219aa09a 100644 --- a/dio/lib/src/version.dart +++ b/dio/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.2.0'; +const String sdkVersion = '8.3.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_dio'; diff --git a/dio/pubspec.yaml b/dio/pubspec.yaml index c174f3ffd2..b4865df495 100644 --- a/dio/pubspec.yaml +++ b/dio/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_dio description: An integration which adds support for performance tracing for the Dio package. -version: 8.2.0 +version: 8.3.0 homepage: https://docs.sentry.io/platforms/dart/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -19,7 +19,7 @@ platforms: dependencies: dio: ^5.0.0 - sentry: 8.2.0 + sentry: 8.3.0 dev_dependencies: meta: ^1.3.0 diff --git a/drift/lib/src/version.dart b/drift/lib/src/version.dart index 9b290b4910..f56b0af46f 100644 --- a/drift/lib/src/version.dart +++ b/drift/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.2.0'; +const String sdkVersion = '8.3.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_drift'; diff --git a/drift/pubspec.yaml b/drift/pubspec.yaml index 85ab6b8e0a..b3a529de9c 100644 --- a/drift/pubspec.yaml +++ b/drift/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_drift description: An integration which adds support for performance tracing for the drift package. -version: 8.2.0 +version: 8.3.0 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -17,7 +17,7 @@ platforms: web: dependencies: - sentry: 8.2.0 + sentry: 8.3.0 meta: ^1.3.0 drift: ^2.13.0 diff --git a/file/lib/src/version.dart b/file/lib/src/version.dart index 23dc032f51..6e9dc3050c 100644 --- a/file/lib/src/version.dart +++ b/file/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.2.0'; +const String sdkVersion = '8.3.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_file'; diff --git a/file/pubspec.yaml b/file/pubspec.yaml index 7f2c554647..9a2027e8c7 100644 --- a/file/pubspec.yaml +++ b/file/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_file description: An integration which adds support for performance tracing for dart.io.File. -version: 8.2.0 +version: 8.3.0 homepage: https://docs.sentry.io/platforms/dart/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -17,7 +17,7 @@ platforms: windows: dependencies: - sentry: 8.2.0 + sentry: 8.3.0 meta: ^1.3.0 dev_dependencies: diff --git a/flutter/example/pubspec.yaml b/flutter/example/pubspec.yaml index 9ddeb4d1ad..1f53f5d1c3 100644 --- a/flutter/example/pubspec.yaml +++ b/flutter/example/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_flutter_example description: Demonstrates how to use the sentry_flutter plugin. -version: 8.2.0 +version: 8.3.0 publish_to: 'none' # Remove this line if you wish to publish to pub.dev diff --git a/flutter/lib/src/version.dart b/flutter/lib/src/version.dart index b7453f867b..0a431dd2de 100644 --- a/flutter/lib/src/version.dart +++ b/flutter/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.2.0'; +const String sdkVersion = '8.3.0'; /// The default SDK name reported to Sentry.io in the submitted events. const String sdkName = 'sentry.dart.flutter'; diff --git a/flutter/pubspec.yaml b/flutter/pubspec.yaml index b356cea210..d2a244f171 100644 --- a/flutter/pubspec.yaml +++ b/flutter/pubspec.yaml @@ -1,5 +1,5 @@ name: sentry_flutter -version: 8.2.0 +version: 8.3.0 description: Sentry SDK for Flutter. This package aims to support different Flutter targets by relying on the many platforms supported by Sentry with native SDKs. homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart @@ -23,7 +23,7 @@ dependencies: sdk: flutter flutter_web_plugins: sdk: flutter - sentry: 8.2.0 + sentry: 8.3.0 package_info_plus: '>=1.0.0' meta: ^1.3.0 ffi: ^2.0.0 diff --git a/hive/lib/src/version.dart b/hive/lib/src/version.dart index 2bdc6f7804..18932a8818 100644 --- a/hive/lib/src/version.dart +++ b/hive/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.2.0'; +const String sdkVersion = '8.3.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_hive'; diff --git a/hive/pubspec.yaml b/hive/pubspec.yaml index 0e982afe9c..a065329ce4 100644 --- a/hive/pubspec.yaml +++ b/hive/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_hive description: An integration which adds support for performance tracing for the hive package. -version: 8.2.0 +version: 8.3.0 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -17,7 +17,7 @@ platforms: web: dependencies: - sentry: 8.2.0 + sentry: 8.3.0 hive: ^2.2.3 meta: ^1.3.0 diff --git a/isar/lib/src/version.dart b/isar/lib/src/version.dart index 6c11fd4a2f..c215620372 100644 --- a/isar/lib/src/version.dart +++ b/isar/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.2.0'; +const String sdkVersion = '8.3.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_isar'; diff --git a/isar/pubspec.yaml b/isar/pubspec.yaml index b4beb15f59..cbafa2af80 100644 --- a/isar/pubspec.yaml +++ b/isar/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_isar description: An integration which adds support for performance tracing for the isar package. -version: 8.2.0 +version: 8.3.0 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -20,7 +20,7 @@ platforms: dependencies: isar: ^3.1.0 isar_flutter_libs: ^3.1.0 # contains Isar Core - sentry: 8.2.0 + sentry: 8.3.0 meta: ^1.3.0 path: ^1.8.3 diff --git a/logging/lib/src/version.dart b/logging/lib/src/version.dart index 77c049abc8..58dbea03c7 100644 --- a/logging/lib/src/version.dart +++ b/logging/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.2.0'; +const String sdkVersion = '8.3.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_logging'; diff --git a/logging/pubspec.yaml b/logging/pubspec.yaml index 1f759c9588..80b484da48 100644 --- a/logging/pubspec.yaml +++ b/logging/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_logging description: An integration which adds support for recording log from the logging package. -version: 8.2.0 +version: 8.3.0 homepage: https://docs.sentry.io/platforms/dart/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -19,7 +19,7 @@ platforms: dependencies: logging: ^1.0.0 - sentry: 8.2.0 + sentry: 8.3.0 dev_dependencies: lints: ^4.0.0 diff --git a/sqflite/lib/src/version.dart b/sqflite/lib/src/version.dart index 418ce72aad..a74f25cdbd 100644 --- a/sqflite/lib/src/version.dart +++ b/sqflite/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.2.0'; +const String sdkVersion = '8.3.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_sqflite'; diff --git a/sqflite/pubspec.yaml b/sqflite/pubspec.yaml index 491b0b2016..b8449f13f7 100644 --- a/sqflite/pubspec.yaml +++ b/sqflite/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_sqflite description: An integration which adds support for performance tracing for the sqflite package. -version: 8.2.0 +version: 8.3.0 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -15,7 +15,7 @@ platforms: macos: dependencies: - sentry: 8.2.0 + sentry: 8.3.0 sqflite: ^2.2.8 sqflite_common: ^2.0.0 meta: ^1.3.0 From 4bdbba571fe71d65950fda5281675c35c6d1d14e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 Jun 2024 11:16:31 +0200 Subject: [PATCH 210/237] build(deps): bump codecov/codecov-action from 4.4.1 to 4.5.0 (#2107) Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 4.4.1 to 4.5.0. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/125fc84a9a348dbcf27191600683ec096ec9021c...e28ff129e5465c2c0dcc6f003fc735cb6ae0c673) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/dart.yml | 2 +- .github/workflows/dio.yml | 2 +- .github/workflows/drift.yml | 2 +- .github/workflows/file.yml | 2 +- .github/workflows/flutter.yml | 2 +- .github/workflows/hive.yml | 2 +- .github/workflows/isar.yml | 2 +- .github/workflows/logging.yml | 2 +- .github/workflows/sqflite.yml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml index 094707c5a8..625dcf9c86 100644 --- a/.github/workflows/dart.yml +++ b/.github/workflows/dart.yml @@ -68,7 +68,7 @@ jobs: dart pub get webdev build - - uses: codecov/codecov-action@125fc84a9a348dbcf27191600683ec096ec9021c # pin@v3 + - uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: name: sentry diff --git a/.github/workflows/dio.yml b/.github/workflows/dio.yml index 85e88e7816..e096e3a10e 100644 --- a/.github/workflows/dio.yml +++ b/.github/workflows/dio.yml @@ -52,7 +52,7 @@ jobs: dart test -p vm --coverage=coverage --test-randomize-ordering-seed=random --chain-stack-traces dart pub run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.dart_tool/package_config.json --report-on=lib - - uses: codecov/codecov-action@125fc84a9a348dbcf27191600683ec096ec9021c # pin@v3 + - uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: name: sentry_dio diff --git a/.github/workflows/drift.yml b/.github/workflows/drift.yml index a07d7e0677..075cdacddf 100644 --- a/.github/workflows/drift.yml +++ b/.github/workflows/drift.yml @@ -96,7 +96,7 @@ jobs: cd drift flutter test --coverage --test-randomize-ordering-seed=random - - uses: codecov/codecov-action@125fc84a9a348dbcf27191600683ec096ec9021c # pin@v3 + - uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' with: name: sentry_drift diff --git a/.github/workflows/file.yml b/.github/workflows/file.yml index 3f7e9986a5..34e2e42ba4 100644 --- a/.github/workflows/file.yml +++ b/.github/workflows/file.yml @@ -52,7 +52,7 @@ jobs: dart test -p vm --coverage=coverage --test-randomize-ordering-seed=random --chain-stack-traces dart pub run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.dart_tool/package_config.json --report-on=lib - - uses: codecov/codecov-action@125fc84a9a348dbcf27191600683ec096ec9021c # pin@v3 + - uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: name: sentry_file diff --git a/.github/workflows/flutter.yml b/.github/workflows/flutter.yml index 45bc61a4f8..cec1edecab 100644 --- a/.github/workflows/flutter.yml +++ b/.github/workflows/flutter.yml @@ -95,7 +95,7 @@ jobs: flutter test --coverage --test-randomize-ordering-seed=random dart run remove_from_coverage -f coverage/lcov.info -r 'binding.dart' - - uses: codecov/codecov-action@125fc84a9a348dbcf27191600683ec096ec9021c # pin@v3 + - uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # pin@v3 if: matrix.sdk == 'stable' && matrix.target == 'linux' with: name: sentry_flutter diff --git a/.github/workflows/hive.yml b/.github/workflows/hive.yml index ef58388bd2..2855960115 100644 --- a/.github/workflows/hive.yml +++ b/.github/workflows/hive.yml @@ -51,7 +51,7 @@ jobs: dart test -p vm --coverage=coverage --test-randomize-ordering-seed=random --chain-stack-traces dart pub run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.dart_tool/package_config.json --report-on=lib - - uses: codecov/codecov-action@125fc84a9a348dbcf27191600683ec096ec9021c # pin@v3 + - uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: name: sentry_hive diff --git a/.github/workflows/isar.yml b/.github/workflows/isar.yml index 35c6ee6540..b1237202c8 100644 --- a/.github/workflows/isar.yml +++ b/.github/workflows/isar.yml @@ -96,7 +96,7 @@ jobs: cd isar flutter test -j 1 --coverage --test-randomize-ordering-seed=random - - uses: codecov/codecov-action@125fc84a9a348dbcf27191600683ec096ec9021c # pin@v3 + - uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' with: name: sentry_isar diff --git a/.github/workflows/logging.yml b/.github/workflows/logging.yml index 1b004ad4a1..a8e08fd172 100644 --- a/.github/workflows/logging.yml +++ b/.github/workflows/logging.yml @@ -52,7 +52,7 @@ jobs: dart test -p vm --coverage=coverage --test-randomize-ordering-seed=random --chain-stack-traces dart pub run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.dart_tool/package_config.json --report-on=lib - - uses: codecov/codecov-action@125fc84a9a348dbcf27191600683ec096ec9021c # pin@v3 + - uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' with: name: sentry_logging diff --git a/.github/workflows/sqflite.yml b/.github/workflows/sqflite.yml index 77ab71a1db..7515d9d4b1 100644 --- a/.github/workflows/sqflite.yml +++ b/.github/workflows/sqflite.yml @@ -96,7 +96,7 @@ jobs: cd sqflite flutter test --coverage --test-randomize-ordering-seed=random - - uses: codecov/codecov-action@125fc84a9a348dbcf27191600683ec096ec9021c # pin@v3 + - uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # pin@v3 if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' with: name: sentry_sqflite From c3b8a985721f539dfc49fe25eb700cddc2d6076d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 Jun 2024 11:16:47 +0200 Subject: [PATCH 211/237] build(deps): bump gradle/gradle-build-action from 3.3.2 to 3.4.1 (#2108) Bumps [gradle/gradle-build-action](https://github.com/gradle/gradle-build-action) from 3.3.2 to 3.4.1. - [Release notes](https://github.com/gradle/gradle-build-action/releases) - [Commits](https://github.com/gradle/gradle-build-action/compare/4c39dd82cd5e1ec7c6fa0173bb41b4b6bb3b86ff...04b20c065cf1ab708c96e64a8811018d0a1fbc88) --- updated-dependencies: - dependency-name: gradle/gradle-build-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/flutter_integration_test.yml | 2 +- .github/workflows/flutter_test.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/flutter_integration_test.yml b/.github/workflows/flutter_integration_test.yml index b396b4f809..25a88a9291 100644 --- a/.github/workflows/flutter_integration_test.yml +++ b/.github/workflows/flutter_integration_test.yml @@ -49,7 +49,7 @@ jobs: run: flutter pub get - name: Gradle cache - uses: gradle/gradle-build-action@4c39dd82cd5e1ec7c6fa0173bb41b4b6bb3b86ff # pin@v3.3.2 + uses: gradle/gradle-build-action@04b20c065cf1ab708c96e64a8811018d0a1fbc88 # pin@v3.4.1 - name: AVD cache uses: actions/cache@v4 diff --git a/.github/workflows/flutter_test.yml b/.github/workflows/flutter_test.yml index 8e1f20a50e..4d355a7310 100644 --- a/.github/workflows/flutter_test.yml +++ b/.github/workflows/flutter_test.yml @@ -54,7 +54,7 @@ jobs: run: flutter pub get - name: Gradle cache - uses: gradle/gradle-build-action@4c39dd82cd5e1ec7c6fa0173bb41b4b6bb3b86ff # pin@v3.0.0 + uses: gradle/gradle-build-action@04b20c065cf1ab708c96e64a8811018d0a1fbc88 # pin@v3.0.0 - name: AVD cache uses: actions/cache@v4 From beeb73dbd078432c4ddf1093feecd3034663137a Mon Sep 17 00:00:00 2001 From: Ivan Dlugos <6349682+vaind@users.noreply.github.com> Date: Wed, 19 Jun 2024 13:05:32 +0200 Subject: [PATCH 212/237] refactor: move all native calls to SentryNativeBinding (#2097) * refactor: move all native calls to SentryNativeBinding [wip] * refactor tests * fix tests * cleanup * fix tests * fix tests * code coverage * fix tests post merge --- .../native_app_start_event_processor.dart | 13 +- flutter/lib/src/file_system_transport.dart | 11 +- .../load_contexts_integration.dart | 18 +- .../load_image_list_integration.dart | 52 +- .../native_app_start_integration.dart | 38 +- .../integrations/native_sdk_integration.dart | 4 +- .../src/native/cocoa/sentry_native_cocoa.dart | 16 +- flutter/lib/src/native/factory_real.dart | 14 +- flutter/lib/src/native/factory_web.dart | 3 +- .../src/native/java/sentry_native_java.dart | 2 +- flutter/lib/src/native/native_app_start.dart | 24 + flutter/lib/src/native/native_frames.dart | 18 + .../lib/src/native/native_scope_observer.dart | 24 +- flutter/lib/src/native/sentry_native.dart | 172 ------ .../lib/src/native/sentry_native_binding.dart | 11 +- .../lib/src/native/sentry_native_channel.dart | 125 +++-- .../lib/src/native/sentry_native_invoker.dart | 47 ++ .../native/sentry_safe_method_channel.dart | 35 ++ .../navigation/sentry_navigator_observer.dart | 11 +- flutter/lib/src/profiling.dart | 8 +- flutter/lib/src/sentry_flutter.dart | 58 +- flutter/test/file_system_transport_test.dart | 47 +- flutter/test/integrations/fixture.dart | 26 + .../integrations/init_native_sdk_test.dart | 14 +- .../load_contexts_integration_test.dart | 98 +--- .../load_contexts_integrations_test.dart | 25 +- .../integrations/load_image_list_test.dart | 244 +++------ .../native_app_start_integration_test.dart | 138 ++--- .../native_sdk_integration_test.dart | 84 +-- flutter/test/load_image_list_test.dart | 183 ------- flutter/test/mocks.dart | 267 +--------- flutter/test/mocks.mocks.dart | 423 ++++++++++++--- flutter/test/native_scope_observer_test.dart | 55 +- .../sentry_display_widget_test.dart | 1 - .../time_to_display_tracker_test.dart | 2 - flutter/test/profiling_test.dart | 31 +- flutter/test/sentry_flutter_test.dart | 3 +- flutter/test/sentry_native_channel_test.dart | 503 ++++++++++-------- flutter/test/sentry_native_test.dart | 120 ----- .../test/sentry_navigator_observer_test.dart | 27 +- 40 files changed, 1234 insertions(+), 1761 deletions(-) create mode 100644 flutter/lib/src/native/native_app_start.dart create mode 100644 flutter/lib/src/native/native_frames.dart delete mode 100644 flutter/lib/src/native/sentry_native.dart create mode 100644 flutter/lib/src/native/sentry_native_invoker.dart create mode 100644 flutter/lib/src/native/sentry_safe_method_channel.dart create mode 100644 flutter/test/integrations/fixture.dart delete mode 100644 flutter/test/load_image_list_test.dart delete mode 100644 flutter/test/sentry_native_test.dart diff --git a/flutter/lib/src/event_processor/native_app_start_event_processor.dart b/flutter/lib/src/event_processor/native_app_start_event_processor.dart index f8ea23b265..87066aa271 100644 --- a/flutter/lib/src/event_processor/native_app_start_event_processor.dart +++ b/flutter/lib/src/event_processor/native_app_start_event_processor.dart @@ -4,7 +4,6 @@ import 'dart:async'; import '../../sentry_flutter.dart'; import '../integrations/integrations.dart'; -import '../native/sentry_native.dart'; // ignore: implementation_imports import 'package:sentry/src/sentry_tracer.dart'; @@ -12,18 +11,14 @@ import 'package:sentry/src/sentry_tracer.dart'; /// EventProcessor that enriches [SentryTransaction] objects with app start /// measurement. class NativeAppStartEventProcessor implements EventProcessor { - final SentryNative _native; final Hub _hub; - NativeAppStartEventProcessor( - this._native, { - Hub? hub, - }) : _hub = hub ?? HubAdapter(); + NativeAppStartEventProcessor({Hub? hub}) : _hub = hub ?? HubAdapter(); @override Future apply(SentryEvent event, Hint hint) async { final options = _hub.options; - if (_native.didAddAppStartMeasurement || + if (NativeAppStartIntegration.didAddAppStartMeasurement || event is! SentryTransaction || options is! SentryFlutterOptions) { return event; @@ -31,8 +26,8 @@ class NativeAppStartEventProcessor implements EventProcessor { final appStartInfo = await NativeAppStartIntegration.getAppStartInfo(); - final appStartEnd = _native.appStartEnd; if (!options.autoAppStart) { + final appStartEnd = NativeAppStartIntegration.appStartEnd; if (appStartEnd != null) { appStartInfo?.end = appStartEnd; } else { @@ -44,7 +39,7 @@ class NativeAppStartEventProcessor implements EventProcessor { final measurement = appStartInfo?.toMeasurement(); if (measurement != null) { event.measurements[measurement.name] = measurement; - _native.didAddAppStartMeasurement = true; + NativeAppStartIntegration.didAddAppStartMeasurement = true; } if (appStartInfo != null) { diff --git a/flutter/lib/src/file_system_transport.dart b/flutter/lib/src/file_system_transport.dart index cf073a38ea..9b7ace7dee 100644 --- a/flutter/lib/src/file_system_transport.dart +++ b/flutter/lib/src/file_system_transport.dart @@ -5,20 +5,21 @@ import 'dart:typed_data'; import 'package:flutter/services.dart'; import 'package:sentry/sentry.dart'; +import 'native/sentry_native_binding.dart'; + class FileSystemTransport implements Transport { - FileSystemTransport(this._channel, this._options); + FileSystemTransport(this._native, this._options); - final MethodChannel _channel; + final SentryNativeBinding _native; final SentryOptions _options; @override Future send(SentryEnvelope envelope) async { final envelopeData = []; await envelope.envelopeStream(_options).forEach(envelopeData.addAll); - // https://flutter.dev/docs/development/platform-integration/platform-channels#codec - final args = [Uint8List.fromList(envelopeData)]; try { - await _channel.invokeMethod('captureEnvelope', args); + // TODO avoid copy + await _native.captureEnvelope(Uint8List.fromList(envelopeData)); } catch (exception, stackTrace) { _options.logger( SentryLevel.error, diff --git a/flutter/lib/src/integrations/load_contexts_integration.dart b/flutter/lib/src/integrations/load_contexts_integration.dart index df8b52b97a..a6ed4effcc 100644 --- a/flutter/lib/src/integrations/load_contexts_integration.dart +++ b/flutter/lib/src/integrations/load_contexts_integration.dart @@ -1,7 +1,7 @@ import 'dart:async'; -import 'package:flutter/services.dart'; import 'package:sentry/sentry.dart'; +import '../native/sentry_native_binding.dart'; import '../sentry_flutter_options.dart'; /// Load Device's Contexts from the iOS & Android SDKs. @@ -15,32 +15,30 @@ import '../sentry_flutter_options.dart'; /// /// This integration is only executed on iOS, macOS & Android Apps. class LoadContextsIntegration extends Integration { - final MethodChannel _channel; + final SentryNativeBinding _native; - LoadContextsIntegration(this._channel); + LoadContextsIntegration(this._native); @override void call(Hub hub, SentryFlutterOptions options) { options.addEventProcessor( - _LoadContextsIntegrationEventProcessor(_channel, options), + _LoadContextsIntegrationEventProcessor(_native, options), ); options.sdk.addIntegration('loadContextsIntegration'); } } class _LoadContextsIntegrationEventProcessor implements EventProcessor { - _LoadContextsIntegrationEventProcessor(this._channel, this._options); + _LoadContextsIntegrationEventProcessor(this._native, this._options); - final MethodChannel _channel; + final SentryNativeBinding _native; final SentryFlutterOptions _options; @override Future apply(SentryEvent event, Hint hint) async { + // TODO don't copy everything (i.e. avoid unnecessary Map.from()) try { - final loadContexts = await _channel.invokeMethod('loadContexts'); - - final infos = - Map.from(loadContexts is Map ? loadContexts : {}); + final infos = await _native.loadContexts() ?? {}; final contextsMap = infos['contexts'] as Map?; if (contextsMap != null && contextsMap.isNotEmpty) { final contexts = Contexts.fromJson( diff --git a/flutter/lib/src/integrations/load_image_list_integration.dart b/flutter/lib/src/integrations/load_image_list_integration.dart index ae08d93946..a3a1c9fc9d 100644 --- a/flutter/lib/src/integrations/load_image_list_integration.dart +++ b/flutter/lib/src/integrations/load_image_list_integration.dart @@ -1,19 +1,19 @@ import 'dart:async'; -import 'package:flutter/services.dart'; import 'package:sentry/sentry.dart'; +import '../native/sentry_native_binding.dart'; import '../sentry_flutter_options.dart'; /// Loads the native debug image list for stack trace symbolication. class LoadImageListIntegration extends Integration { - final MethodChannel _channel; + final SentryNativeBinding _native; - LoadImageListIntegration(this._channel); + LoadImageListIntegration(this._native); @override void call(Hub hub, SentryFlutterOptions options) { options.addEventProcessor( - _LoadImageListIntegrationEventProcessor(_channel, options), + _LoadImageListIntegrationEventProcessor(_native), ); options.sdk.addIntegration('loadImageListIntegration'); @@ -32,7 +32,7 @@ extension _NeedsSymbolication on SentryEvent { return frames.any((frame) => 'native' == frame?.platform); } - List? _getStacktraceFrames() { + Iterable? _getStacktraceFrames() { if (exceptions?.isNotEmpty == true) { return exceptions?.first.stackTrace?.frames; } @@ -40,56 +40,26 @@ extension _NeedsSymbolication on SentryEvent { var stacktraces = threads?.map((e) => e.stacktrace); return stacktraces ?.where((element) => element != null) - .expand((element) => element!.frames) - .toList(); + .expand((element) => element!.frames); } return null; } } class _LoadImageListIntegrationEventProcessor implements EventProcessor { - _LoadImageListIntegrationEventProcessor(this._channel, this._options); + _LoadImageListIntegrationEventProcessor(this._native); - final MethodChannel _channel; - final SentryFlutterOptions _options; + final SentryNativeBinding _native; @override Future apply(SentryEvent event, Hint hint) async { if (event.needsSymbolication()) { - try { - // we call on every event because the loaded image list is cached - // and it could be changed on the Native side. - final loadImageList = await _channel.invokeMethod('loadImageList'); - final imageList = List>.from( - loadImageList is List ? loadImageList : [], - ); - return copyWithDebugImages(event, imageList); - } catch (exception, stackTrace) { - _options.logger( - SentryLevel.error, - 'loadImageList failed', - exception: exception, - stackTrace: stackTrace, - ); + final images = await _native.loadDebugImages(); + if (images != null) { + return event.copyWith(debugMeta: DebugMeta(images: images)); } } return event; } - - static SentryEvent copyWithDebugImages( - SentryEvent event, List imageList) { - if (imageList.isEmpty) { - return event; - } - - final newDebugImages = []; - for (final obj in imageList) { - final jsonMap = Map.from(obj as Map); - final image = DebugImage.fromJson(jsonMap); - newDebugImages.add(image); - } - - return event.copyWith(debugMeta: DebugMeta(images: newDebugImages)); - } } diff --git a/flutter/lib/src/integrations/native_app_start_integration.dart b/flutter/lib/src/integrations/native_app_start_integration.dart index d3be7b4a0f..c76874d19f 100644 --- a/flutter/lib/src/integrations/native_app_start_integration.dart +++ b/flutter/lib/src/integrations/native_app_start_integration.dart @@ -6,7 +6,7 @@ import 'package:meta/meta.dart'; import '../../sentry_flutter.dart'; import '../frame_callback_handler.dart'; -import '../native/sentry_native.dart'; +import '../native/sentry_native_binding.dart'; import '../event_processor/native_app_start_event_processor.dart'; /// Integration which handles communication with native frameworks in order to @@ -16,10 +16,23 @@ class NativeAppStartIntegration extends Integration { {Hub? hub}) : _hub = hub ?? HubAdapter(); - final SentryNative _native; + final SentryNativeBinding _native; final FrameCallbackHandler _frameCallbackHandler; final Hub _hub; + /// This timestamp marks the end of app startup. Either set automatically when + /// [SentryFlutterOptions.autoAppStart] is true, or by calling + /// [SentryFlutter.setAppStartEnd] + @internal + static DateTime? appStartEnd; + + /// Flag indicating if app start was already fetched. + static bool _didFetchAppStart = false; + + /// Flag indicating if app start measurement was added to the first transaction. + @internal + static bool didAddAppStartMeasurement = false; + /// Timeout duration to wait for the app start info to be fetched. static const _timeoutDuration = Duration(seconds: 30); @@ -55,6 +68,14 @@ class NativeAppStartIntegration extends Integration { static void clearAppStartInfo() { _appStartInfo = null; _appStartCompleter = Completer(); + didAddAppStartMeasurement = false; + } + + /// Reset state + @visibleForTesting + static void reset() { + appStartEnd = null; + _didFetchAppStart = false; } @override @@ -73,11 +94,12 @@ class NativeAppStartIntegration extends Integration { return; } - if (_native.didFetchAppStart) { + if (_didFetchAppStart) { return; } _frameCallbackHandler.addPostFrameCallback((timeStamp) async { + _didFetchAppStart = true; final nativeAppStart = await _native.fetchNativeAppStart(); if (nativeAppStart == null) { setAppStartInfo(null); @@ -94,14 +116,12 @@ class NativeAppStartIntegration extends Integration { nativeAppStart.appStartTime.toInt()); final pluginRegistrationDateTime = DateTime.fromMillisecondsSinceEpoch( nativeAppStart.pluginRegistrationTime); - DateTime? appStartEndDateTime; if (options.autoAppStart) { // We only assign the current time if it's not already set - this is useful in tests - _native.appStartEnd ??= options.clock(); - appStartEndDateTime = _native.appStartEnd; + appStartEnd ??= options.clock(); - final duration = appStartEndDateTime?.difference(appStartDateTime); + final duration = appStartEnd?.difference(appStartDateTime); // We filter out app start more than 60s. // This could be due to many different reasons. @@ -143,7 +163,7 @@ class NativeAppStartIntegration extends Integration { final appStartInfo = AppStartInfo( nativeAppStart.isColdStart ? AppStartType.cold : AppStartType.warm, start: appStartDateTime, - end: appStartEndDateTime, + end: appStartEnd, pluginRegistration: pluginRegistrationDateTime, sentrySetupStart: sentrySetupStartDateTime, nativeSpanTimes: nativeSpanTimes); @@ -174,7 +194,7 @@ class NativeAppStartIntegration extends Integration { } }); - options.addEventProcessor(NativeAppStartEventProcessor(_native, hub: hub)); + options.addEventProcessor(NativeAppStartEventProcessor(hub: hub)); options.sdk.addIntegration('nativeAppStartIntegration'); } diff --git a/flutter/lib/src/integrations/native_sdk_integration.dart b/flutter/lib/src/integrations/native_sdk_integration.dart index 35181afc1e..7178883d73 100644 --- a/flutter/lib/src/integrations/native_sdk_integration.dart +++ b/flutter/lib/src/integrations/native_sdk_integration.dart @@ -1,7 +1,7 @@ import 'dart:async'; import 'package:sentry/sentry.dart'; -import '../native/sentry_native.dart'; +import '../native/sentry_native_binding.dart'; import '../sentry_flutter_options.dart'; /// Enables Sentry's native SDKs (Android and iOS) with options. @@ -9,7 +9,7 @@ class NativeSdkIntegration implements Integration { NativeSdkIntegration(this._native); SentryFlutterOptions? _options; - final SentryNative _native; + final SentryNativeBinding _native; @override Future call(Hub hub, SentryFlutterOptions options) async { diff --git a/flutter/lib/src/native/cocoa/sentry_native_cocoa.dart b/flutter/lib/src/native/cocoa/sentry_native_cocoa.dart index d6912c107c..9bb5af98b6 100644 --- a/flutter/lib/src/native/cocoa/sentry_native_cocoa.dart +++ b/flutter/lib/src/native/cocoa/sentry_native_cocoa.dart @@ -10,14 +10,14 @@ import 'binding.dart' as cocoa; class SentryNativeCocoa extends SentryNativeChannel { late final _lib = cocoa.SentryCocoa(DynamicLibrary.process()); - SentryNativeCocoa(super.channel); + SentryNativeCocoa(super.options, super.channel); @override - int? startProfiler(SentryId traceId) { - final cSentryId = cocoa.SentryId1.alloc(_lib) - ..initWithUUIDString_(cocoa.NSString(_lib, traceId.toString())); - final startTime = - cocoa.PrivateSentrySDKOnly.startProfilerForTrace_(_lib, cSentryId); - return startTime; - } + int? startProfiler(SentryId traceId) => tryCatchSync('startProfiler', () { + final cSentryId = cocoa.SentryId1.alloc(_lib) + ..initWithUUIDString_(cocoa.NSString(_lib, traceId.toString())); + final startTime = + cocoa.PrivateSentrySDKOnly.startProfilerForTrace_(_lib, cSentryId); + return startTime; + }); } diff --git a/flutter/lib/src/native/factory_real.dart b/flutter/lib/src/native/factory_real.dart index d5ee4f5cca..554279a8bc 100644 --- a/flutter/lib/src/native/factory_real.dart +++ b/flutter/lib/src/native/factory_real.dart @@ -6,12 +6,14 @@ import 'java/sentry_native_java.dart'; import 'sentry_native_binding.dart'; import 'sentry_native_channel.dart'; -SentryNativeBinding createBinding(PlatformChecker pc, MethodChannel channel) { - if (pc.platform.isIOS || pc.platform.isMacOS) { - return SentryNativeCocoa(channel); - } else if (pc.platform.isAndroid) { - return SentryNativeJava(channel); +SentryNativeBinding createBinding(SentryFlutterOptions options, + {MethodChannel channel = const MethodChannel('sentry_flutter')}) { + final platform = options.platformChecker.platform; + if (platform.isIOS || platform.isMacOS) { + return SentryNativeCocoa(options, channel); + } else if (platform.isAndroid) { + return SentryNativeJava(options, channel); } else { - return SentryNativeChannel(channel); + return SentryNativeChannel(options, channel); } } diff --git a/flutter/lib/src/native/factory_web.dart b/flutter/lib/src/native/factory_web.dart index c2cd57ada7..a928271d16 100644 --- a/flutter/lib/src/native/factory_web.dart +++ b/flutter/lib/src/native/factory_web.dart @@ -4,6 +4,7 @@ import '../../sentry_flutter.dart'; import 'sentry_native_binding.dart'; // This isn't actually called, see SentryFlutter.init() -SentryNativeBinding createBinding(PlatformChecker _, MethodChannel __) { +SentryNativeBinding createBinding(SentryFlutterOptions options, + {MethodChannel channel = const MethodChannel('sentry_flutter')}) { throw UnsupportedError("Native binding is not supported on this platform."); } diff --git a/flutter/lib/src/native/java/sentry_native_java.dart b/flutter/lib/src/native/java/sentry_native_java.dart index 20774e11fa..1b0ef13cc5 100644 --- a/flutter/lib/src/native/java/sentry_native_java.dart +++ b/flutter/lib/src/native/java/sentry_native_java.dart @@ -6,5 +6,5 @@ import '../sentry_native_channel.dart'; // generated JNI bindings. See https://github.com/getsentry/sentry-dart/issues/1444 @internal class SentryNativeJava extends SentryNativeChannel { - SentryNativeJava(super.channel); + SentryNativeJava(super.options, super.channel); } diff --git a/flutter/lib/src/native/native_app_start.dart b/flutter/lib/src/native/native_app_start.dart new file mode 100644 index 0000000000..7b6d53422f --- /dev/null +++ b/flutter/lib/src/native/native_app_start.dart @@ -0,0 +1,24 @@ +import 'package:meta/meta.dart'; + +@internal +class NativeAppStart { + NativeAppStart( + {required this.appStartTime, + required this.pluginRegistrationTime, + required this.isColdStart, + required this.nativeSpanTimes}); + + double appStartTime; + int pluginRegistrationTime; + bool isColdStart; + Map nativeSpanTimes; + + factory NativeAppStart.fromJson(Map json) { + return NativeAppStart( + appStartTime: json['appStartTime'] as double, + pluginRegistrationTime: json['pluginRegistrationTime'] as int, + isColdStart: json['isColdStart'] as bool, + nativeSpanTimes: json['nativeSpanTimes'] as Map, + ); + } +} diff --git a/flutter/lib/src/native/native_frames.dart b/flutter/lib/src/native/native_frames.dart new file mode 100644 index 0000000000..309abccbb7 --- /dev/null +++ b/flutter/lib/src/native/native_frames.dart @@ -0,0 +1,18 @@ +import 'package:meta/meta.dart'; + +@internal +class NativeFrames { + NativeFrames(this.totalFrames, this.slowFrames, this.frozenFrames); + + int totalFrames; + int slowFrames; + int frozenFrames; + + factory NativeFrames.fromJson(Map json) { + return NativeFrames( + json['totalFrames'] as int, + json['slowFrames'] as int, + json['frozenFrames'] as int, + ); + } +} diff --git a/flutter/lib/src/native/native_scope_observer.dart b/flutter/lib/src/native/native_scope_observer.dart index fe26a2b094..84dc31f646 100644 --- a/flutter/lib/src/native/native_scope_observer.dart +++ b/flutter/lib/src/native/native_scope_observer.dart @@ -2,55 +2,55 @@ import 'dart:async'; import 'package:sentry/sentry.dart'; -import 'sentry_native.dart'; +import 'sentry_native_binding.dart'; class NativeScopeObserver implements ScopeObserver { - NativeScopeObserver(this._sentryNative); + NativeScopeObserver(this._native); - final SentryNative _sentryNative; + final SentryNativeBinding _native; @override Future setContexts(String key, value) async { - await _sentryNative.setContexts(key, value); + await _native.setContexts(key, value); } @override Future removeContexts(String key) async { - await _sentryNative.removeContexts(key); + await _native.removeContexts(key); } @override Future setUser(SentryUser? user) async { - await _sentryNative.setUser(user); + await _native.setUser(user); } @override Future addBreadcrumb(Breadcrumb breadcrumb) async { - await _sentryNative.addBreadcrumb(breadcrumb); + await _native.addBreadcrumb(breadcrumb); } @override Future clearBreadcrumbs() async { - await _sentryNative.clearBreadcrumbs(); + await _native.clearBreadcrumbs(); } @override Future setExtra(String key, dynamic value) async { - await _sentryNative.setExtra(key, value); + await _native.setExtra(key, value); } @override Future removeExtra(String key) async { - await _sentryNative.removeExtra(key); + await _native.removeExtra(key); } @override Future setTag(String key, String value) async { - await _sentryNative.setTag(key, value); + await _native.setTag(key, value); } @override Future removeTag(String key) async { - await _sentryNative.removeTag(key); + await _native.removeTag(key); } } diff --git a/flutter/lib/src/native/sentry_native.dart b/flutter/lib/src/native/sentry_native.dart deleted file mode 100644 index d8d9c5a964..0000000000 --- a/flutter/lib/src/native/sentry_native.dart +++ /dev/null @@ -1,172 +0,0 @@ -import 'dart:async'; - -import 'package:meta/meta.dart'; - -import '../../sentry_flutter.dart'; -import 'sentry_native_binding.dart'; - -/// [SentryNative] holds state that it fetches from to the native SDKs. -/// It forwards to platform-specific implementations of [SentryNativeBinding]. -/// Any errors are logged and ignored. -@internal -class SentryNative { - final SentryOptions _options; - final SentryNativeBinding _binding; - - SentryNative(this._options, this._binding); - - // AppStart - - /// This timestamp marks the end of app startup. Either set automatically when - /// [SentryFlutterOptions.autoAppStart] is true, or by calling - /// [SentryFlutter.setAppStartEnd] - DateTime? appStartEnd; - - bool _didFetchAppStart = false; - - /// Flag indicating if app start was already fetched. - bool get didFetchAppStart => _didFetchAppStart; - - /// Flag indicating if app start measurement was added to the first transaction. - bool didAddAppStartMeasurement = false; - - Future init(SentryFlutterOptions options) async => - _invoke("init", () => _binding.init(options)); - - Future close() async => _invoke("close", _binding.close); - - /// Fetch [NativeAppStart] from native channels. Can only be called once. - Future fetchNativeAppStart() async { - _didFetchAppStart = true; - return _invoke("fetchNativeAppStart", _binding.fetchNativeAppStart); - } - - // NativeFrames - - Future beginNativeFramesCollection() => - _invoke("beginNativeFrames", _binding.beginNativeFrames); - - Future endNativeFramesCollection(SentryId traceId) => - _invoke("endNativeFrames", () => _binding.endNativeFrames(traceId)); - - // Scope - - Future setContexts(String key, dynamic value) => - _invoke("setContexts", () => _binding.setContexts(key, value)); - - Future removeContexts(String key) => - _invoke("removeContexts", () => _binding.removeContexts(key)); - - Future setUser(SentryUser? sentryUser) => - _invoke("setUser", () => _binding.setUser(sentryUser)); - - Future addBreadcrumb(Breadcrumb breadcrumb) => - _invoke("addBreadcrumb", () => _binding.addBreadcrumb(breadcrumb)); - - Future clearBreadcrumbs() => - _invoke("clearBreadcrumbs", _binding.clearBreadcrumbs); - - Future setExtra(String key, dynamic value) => - _invoke("setExtra", () => _binding.setExtra(key, value)); - - Future removeExtra(String key) => - _invoke("removeExtra", () => _binding.removeExtra(key)); - - Future setTag(String key, String value) => - _invoke("setTag", () => _binding.setTag(key, value)); - - Future removeTag(String key) => - _invoke("removeTag", () => _binding.removeTag(key)); - - int? startProfiler(SentryId traceId) => - _invokeSync("startProfiler", () => _binding.startProfiler(traceId)); - - Future discardProfiler(SentryId traceId) => - _invoke("discardProfiler", () => _binding.discardProfiler(traceId)); - - Future?> collectProfile( - SentryId traceId, int startTimeNs, int endTimeNs) => - _invoke("collectProfile", - () => _binding.collectProfile(traceId, startTimeNs, endTimeNs)); - - /// Reset state - void reset() { - appStartEnd = null; - _didFetchAppStart = false; - } - - // Helpers - Future _invoke( - String nativeMethodName, Future Function() fn) async { - try { - return await fn(); - } catch (error, stackTrace) { - _logError(nativeMethodName, error, stackTrace); - // ignore: invalid_use_of_internal_member - if (_options.automatedTestMode) { - rethrow; - } - return null; - } - } - - T? _invokeSync(String nativeMethodName, T? Function() fn) { - try { - return fn(); - } catch (error, stackTrace) { - _logError(nativeMethodName, error, stackTrace); - // ignore: invalid_use_of_internal_member - if (_options.automatedTestMode) { - rethrow; - } - return null; - } - } - - void _logError(String nativeMethodName, Object error, StackTrace stackTrace) { - _options.logger( - SentryLevel.error, - 'Native call `$nativeMethodName` failed', - exception: error, - stackTrace: stackTrace, - ); - } -} - -class NativeAppStart { - NativeAppStart( - {required this.appStartTime, - required this.pluginRegistrationTime, - required this.isColdStart, - required this.nativeSpanTimes}); - - double appStartTime; - int pluginRegistrationTime; - bool isColdStart; - Map nativeSpanTimes; - - factory NativeAppStart.fromJson(Map json) { - return NativeAppStart( - appStartTime: json['appStartTime'] as double, - pluginRegistrationTime: json['pluginRegistrationTime'] as int, - isColdStart: json['isColdStart'] as bool, - nativeSpanTimes: json['nativeSpanTimes'] as Map, - ); - } -} - -class NativeFrames { - NativeFrames(this.totalFrames, this.slowFrames, this.frozenFrames); - - int totalFrames; - int slowFrames; - int frozenFrames; - - factory NativeFrames.fromJson(Map json) { - return NativeFrames( - json['totalFrames'] as int, - json['slowFrames'] as int, - json['frozenFrames'] as int, - ); - } -} diff --git a/flutter/lib/src/native/sentry_native_binding.dart b/flutter/lib/src/native/sentry_native_binding.dart index 950e7f9994..96962a0575 100644 --- a/flutter/lib/src/native/sentry_native_binding.dart +++ b/flutter/lib/src/native/sentry_native_binding.dart @@ -1,20 +1,23 @@ import 'dart:async'; +import 'dart:typed_data'; import 'package:meta/meta.dart'; import '../../sentry_flutter.dart'; -import 'sentry_native.dart'; +import 'native_app_start.dart'; +import 'native_frames.dart'; /// Provide typed methods to access native layer. @internal abstract class SentryNativeBinding { - // TODO Move other native calls here. Future init(SentryFlutterOptions options); Future close(); Future fetchNativeAppStart(); + Future captureEnvelope(Uint8List envelopeData); + Future beginNativeFrames(); Future endNativeFrames(SentryId id); @@ -25,6 +28,8 @@ abstract class SentryNativeBinding { Future clearBreadcrumbs(); + Future?> loadContexts(); + Future setContexts(String key, dynamic value); Future removeContexts(String key); @@ -43,4 +48,6 @@ abstract class SentryNativeBinding { Future?> collectProfile( SentryId traceId, int startTimeNs, int endTimeNs); + + Future?> loadDebugImages(); } diff --git a/flutter/lib/src/native/sentry_native_channel.dart b/flutter/lib/src/native/sentry_native_channel.dart index 61b361de30..2b3e703065 100644 --- a/flutter/lib/src/native/sentry_native_channel.dart +++ b/flutter/lib/src/native/sentry_native_channel.dart @@ -1,61 +1,73 @@ import 'dart:async'; +// backcompatibility for Flutter < 3.3 +// ignore: unnecessary_import +import 'dart:typed_data'; import 'package:flutter/services.dart'; import 'package:meta/meta.dart'; import '../../sentry_flutter.dart'; -import 'sentry_native.dart'; +import 'native_app_start.dart'; +import 'native_frames.dart'; import 'method_channel_helper.dart'; import 'sentry_native_binding.dart'; +import 'sentry_native_invoker.dart'; +import 'sentry_safe_method_channel.dart'; /// Provide typed methods to access native layer via MethodChannel. @internal -class SentryNativeChannel implements SentryNativeBinding { - SentryNativeChannel(this._channel); - - final MethodChannel _channel; - - // TODO Move other native calls here. - - @override - Future init(SentryFlutterOptions options) async => - _channel.invokeMethod('initNativeSdk', { - 'dsn': options.dsn, - 'debug': options.debug, - 'environment': options.environment, - 'release': options.release, - 'enableAutoSessionTracking': options.enableAutoSessionTracking, - 'enableNativeCrashHandling': options.enableNativeCrashHandling, - 'attachStacktrace': options.attachStacktrace, - 'attachThreads': options.attachThreads, - 'autoSessionTrackingIntervalMillis': - options.autoSessionTrackingInterval.inMilliseconds, - 'dist': options.dist, - 'integrations': options.sdk.integrations, - 'packages': - options.sdk.packages.map((e) => e.toJson()).toList(growable: false), - 'diagnosticLevel': options.diagnosticLevel.name, - 'maxBreadcrumbs': options.maxBreadcrumbs, - 'anrEnabled': options.anrEnabled, - 'anrTimeoutIntervalMillis': options.anrTimeoutInterval.inMilliseconds, - 'enableAutoNativeBreadcrumbs': options.enableAutoNativeBreadcrumbs, - 'maxCacheItems': options.maxCacheItems, - 'sendDefaultPii': options.sendDefaultPii, - 'enableWatchdogTerminationTracking': - options.enableWatchdogTerminationTracking, - 'enableNdkScopeSync': options.enableNdkScopeSync, - 'enableAutoPerformanceTracing': options.enableAutoPerformanceTracing, - 'sendClientReports': options.sendClientReports, - 'proguardUuid': options.proguardUuid, - 'maxAttachmentSize': options.maxAttachmentSize, - 'recordHttpBreadcrumbs': options.recordHttpBreadcrumbs, - 'captureFailedRequests': options.captureFailedRequests, - 'enableAppHangTracking': options.enableAppHangTracking, - 'connectionTimeoutMillis': options.connectionTimeout.inMilliseconds, - 'readTimeoutMillis': options.readTimeout.inMilliseconds, - 'appHangTimeoutIntervalMillis': - options.appHangTimeoutInterval.inMilliseconds, - }); +class SentryNativeChannel + with SentryNativeSafeInvoker + implements SentryNativeBinding { + @override + final SentryFlutterOptions options; + + final SentrySafeMethodChannel _channel; + + SentryNativeChannel(this.options, MethodChannel channel) + : _channel = SentrySafeMethodChannel(channel, options); + + @override + Future init(SentryFlutterOptions options) async { + assert(this.options == options); + return _channel.invokeMethod('initNativeSdk', { + 'dsn': options.dsn, + 'debug': options.debug, + 'environment': options.environment, + 'release': options.release, + 'enableAutoSessionTracking': options.enableAutoSessionTracking, + 'enableNativeCrashHandling': options.enableNativeCrashHandling, + 'attachStacktrace': options.attachStacktrace, + 'attachThreads': options.attachThreads, + 'autoSessionTrackingIntervalMillis': + options.autoSessionTrackingInterval.inMilliseconds, + 'dist': options.dist, + 'integrations': options.sdk.integrations, + 'packages': + options.sdk.packages.map((e) => e.toJson()).toList(growable: false), + 'diagnosticLevel': options.diagnosticLevel.name, + 'maxBreadcrumbs': options.maxBreadcrumbs, + 'anrEnabled': options.anrEnabled, + 'anrTimeoutIntervalMillis': options.anrTimeoutInterval.inMilliseconds, + 'enableAutoNativeBreadcrumbs': options.enableAutoNativeBreadcrumbs, + 'maxCacheItems': options.maxCacheItems, + 'sendDefaultPii': options.sendDefaultPii, + 'enableWatchdogTerminationTracking': + options.enableWatchdogTerminationTracking, + 'enableNdkScopeSync': options.enableNdkScopeSync, + 'enableAutoPerformanceTracing': options.enableAutoPerformanceTracing, + 'sendClientReports': options.sendClientReports, + 'proguardUuid': options.proguardUuid, + 'maxAttachmentSize': options.maxAttachmentSize, + 'recordHttpBreadcrumbs': options.recordHttpBreadcrumbs, + 'captureFailedRequests': options.captureFailedRequests, + 'enableAppHangTracking': options.enableAppHangTracking, + 'connectionTimeoutMillis': options.connectionTimeout.inMilliseconds, + 'readTimeoutMillis': options.readTimeout.inMilliseconds, + 'appHangTimeoutIntervalMillis': + options.appHangTimeoutInterval.inMilliseconds, + }); + } @override Future close() async => _channel.invokeMethod('closeNativeSdk'); @@ -67,6 +79,14 @@ class SentryNativeChannel implements SentryNativeBinding { return (json != null) ? NativeAppStart.fromJson(json) : null; } + @override + Future captureEnvelope(Uint8List envelopeData) => + _channel.invokeMethod('captureEnvelope', [envelopeData]); + + @override + Future?> loadContexts() => + _channel.invokeMapMethod('loadContexts'); + @override Future beginNativeFrames() => _channel.invokeMethod('beginNativeFrames'); @@ -147,4 +167,15 @@ class SentryNativeChannel implements SentryNativeBinding { 'startTime': startTimeNs, 'endTime': endTimeNs, }); + + @override + Future?> loadDebugImages() => + tryCatchAsync('loadDebugImages', () async { + final images = await _channel + .invokeListMethod>('loadImageList'); + return images + ?.map((e) => e.cast()) + .map(DebugImage.fromJson) + .toList(); + }); } diff --git a/flutter/lib/src/native/sentry_native_invoker.dart b/flutter/lib/src/native/sentry_native_invoker.dart new file mode 100644 index 0000000000..dbda8c4513 --- /dev/null +++ b/flutter/lib/src/native/sentry_native_invoker.dart @@ -0,0 +1,47 @@ +import 'dart:async'; + +import 'package:meta/meta.dart'; + +import '../../sentry_flutter.dart'; + +/// Helper to safely invoke native methods. Any errors are logged and ignored. +@internal +mixin SentryNativeSafeInvoker { + SentryFlutterOptions get options; + + Future tryCatchAsync( + String nativeMethodName, Future Function() fn) async { + try { + return await fn(); + } catch (error, stackTrace) { + _logError(nativeMethodName, error, stackTrace); + // ignore: invalid_use_of_internal_member + if (options.automatedTestMode) { + rethrow; + } + return null; + } + } + + T? tryCatchSync(String nativeMethodName, T? Function() fn) { + try { + return fn(); + } catch (error, stackTrace) { + _logError(nativeMethodName, error, stackTrace); + // ignore: invalid_use_of_internal_member + if (options.automatedTestMode) { + rethrow; + } + return null; + } + } + + void _logError(String nativeMethodName, Object error, StackTrace stackTrace) { + options.logger( + SentryLevel.error, + 'Native call `$nativeMethodName` failed', + exception: error, + stackTrace: stackTrace, + ); + } +} diff --git a/flutter/lib/src/native/sentry_safe_method_channel.dart b/flutter/lib/src/native/sentry_safe_method_channel.dart new file mode 100644 index 0000000000..aa44c08f44 --- /dev/null +++ b/flutter/lib/src/native/sentry_safe_method_channel.dart @@ -0,0 +1,35 @@ +import 'dart:async'; + +import 'package:flutter/services.dart'; +import 'package:meta/meta.dart'; + +import '../../sentry_flutter.dart'; +import 'sentry_native_invoker.dart'; + +class SentrySafeMethodChannel with SentryNativeSafeInvoker { + @override + final SentryFlutterOptions options; + + final MethodChannel _channel; + + SentrySafeMethodChannel(this._channel, this.options); + + @optionalTypeArgs + Future invokeMethod(String method, [dynamic args]) => + tryCatchAsync(method, () => _channel.invokeMethod(method, args)); + + Future?> invokeListMethod(String method, [dynamic args]) => + tryCatchAsync(method, () async { + // Note, we're not using channel.invokeListMethod because it would fail in tests due to the generated mock not doing a cast. + final result = await _channel.invokeMethod>(method, args); + return result?.cast(); + }); + + Future?> invokeMapMethod(String method, [dynamic args]) => + tryCatchAsync(method, () async { + // Note, we're not using channel.invokeMapMethod because it would fail in tests due to the generated mock not doing a cast. + final result = + await _channel.invokeMethod>(method, args); + return result?.cast(); + }); +} diff --git a/flutter/lib/src/navigation/sentry_navigator_observer.dart b/flutter/lib/src/navigation/sentry_navigator_observer.dart index fbfc12b6ee..1a6b156377 100644 --- a/flutter/lib/src/navigation/sentry_navigator_observer.dart +++ b/flutter/lib/src/navigation/sentry_navigator_observer.dart @@ -6,11 +6,12 @@ import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; import 'package:meta/meta.dart'; import '../integrations/integrations.dart'; +import '../native/native_frames.dart'; +import '../native/sentry_native_binding.dart'; import 'time_to_display_tracker.dart'; import '../../sentry_flutter.dart'; import '../event_processor/flutter_enricher_event_processor.dart'; -import '../native/sentry_native.dart'; // ignore: implementation_imports import 'package:sentry/src/sentry_tracer.dart'; @@ -111,7 +112,7 @@ class SentryNavigatorObserver extends RouteObserver> { final bool _setRouteNameAsTransaction; final RouteNameExtractor? _routeNameExtractor; final AdditionalInfoExtractor? _additionalInfoProvider; - final SentryNative? _native; + final SentryNativeBinding? _native; static TimeToDisplayTracker? _timeToDisplayTracker; @internal @@ -247,8 +248,8 @@ class SentryNavigatorObserver extends RouteObserver> { trimEnd: true, onFinish: (transaction) async { _transaction = null; - final nativeFrames = await _native - ?.endNativeFramesCollection(transaction.context.traceId); + final nativeFrames = + await _native?.endNativeFrames(transaction.context.traceId); if (nativeFrames != null) { final measurements = nativeFrames.toMeasurements(); for (final item in measurements.entries) { @@ -277,7 +278,7 @@ class SentryNavigatorObserver extends RouteObserver> { scope.span ??= _transaction; }); - await _native?.beginNativeFramesCollection(); + await _native?.beginNativeFrames(); } Future _finishTimeToDisplayTracking({bool clearAfter = false}) async { diff --git a/flutter/lib/src/profiling.dart b/flutter/lib/src/profiling.dart index a4332d77e7..3fb22a9b75 100644 --- a/flutter/lib/src/profiling.dart +++ b/flutter/lib/src/profiling.dart @@ -8,16 +8,16 @@ import 'package:sentry/src/sentry_envelope_item_header.dart'; import 'package:sentry/src/sentry_item_type.dart'; import '../sentry_flutter.dart'; -import 'native/sentry_native.dart'; +import 'native/sentry_native_binding.dart'; // ignore: invalid_use_of_internal_member class SentryNativeProfilerFactory implements SentryProfilerFactory { - final SentryNative _native; + final SentryNativeBinding _native; final ClockProvider _clock; SentryNativeProfilerFactory(this._native, this._clock); - static void attachTo(Hub hub, SentryNative native) { + static void attachTo(Hub hub, SentryNativeBinding native) { // ignore: invalid_use_of_internal_member final options = hub.options; @@ -53,7 +53,7 @@ class SentryNativeProfilerFactory implements SentryProfilerFactory { // ignore: invalid_use_of_internal_member class SentryNativeProfiler implements SentryProfiler { - final SentryNative _native; + final SentryNativeBinding _native; final int _starTimeNs; final SentryId _traceId; bool _finished = false; diff --git a/flutter/lib/src/sentry_flutter.dart b/flutter/lib/src/sentry_flutter.dart index e0d4415de5..3a9ac1cb9b 100644 --- a/flutter/lib/src/sentry_flutter.dart +++ b/flutter/lib/src/sentry_flutter.dart @@ -1,7 +1,6 @@ import 'dart:async'; import 'dart:ui'; -import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; import 'package:meta/meta.dart'; import '../sentry_flutter.dart'; @@ -14,9 +13,9 @@ import 'integrations/connectivity/connectivity_integration.dart'; import 'integrations/screenshot_integration.dart'; import 'native/factory.dart'; import 'native/native_scope_observer.dart'; +import 'native/sentry_native_binding.dart'; import 'profiling.dart'; import 'renderer/renderer.dart'; -import 'native/sentry_native.dart'; import 'integrations/integrations.dart'; import 'event_processor/flutter_enricher_event_processor.dart'; @@ -32,8 +31,6 @@ typedef FlutterOptionsConfiguration = FutureOr Function( /// Sentry Flutter SDK main entry point mixin SentryFlutter { - static const _channel = MethodChannel('sentry_flutter'); - /// Represents the time when the Sentry init set up has started. @internal // ignore: invalid_use_of_internal_member @@ -42,7 +39,6 @@ mixin SentryFlutter { static Future init( FlutterOptionsConfiguration optionsConfiguration, { AppRunner? appRunner, - @internal MethodChannel channel = _channel, @internal PlatformChecker? platformChecker, @internal RendererWrapper? rendererWrapper, }) async { @@ -59,8 +55,7 @@ mixin SentryFlutter { } if (flutterOptions.platformChecker.hasNativeIntegration) { - final binding = createBinding(flutterOptions.platformChecker, channel); - _native = SentryNative(flutterOptions, binding); + _native = createBinding(flutterOptions); } final platformDispatcher = PlatformDispatcher.instance; @@ -80,7 +75,6 @@ mixin SentryFlutter { // first step is to install the native integration and set default values, // so we are able to capture future errors. final defaultIntegrations = _createDefaultIntegrations( - channel, flutterOptions, isOnErrorSupported, ); @@ -88,10 +82,13 @@ mixin SentryFlutter { flutterOptions.addIntegration(defaultIntegration); } - await _initDefaultValues(flutterOptions, channel); + await _initDefaultValues(flutterOptions); await Sentry.init( - (options) => optionsConfiguration(options as SentryFlutterOptions), + (options) { + assert(options == flutterOptions); + return optionsConfiguration(options as SentryFlutterOptions); + }, appRunner: appRunner, // ignore: invalid_use_of_internal_member options: flutterOptions, @@ -107,15 +104,12 @@ mixin SentryFlutter { } } - static Future _initDefaultValues( - SentryFlutterOptions options, - MethodChannel channel, - ) async { + static Future _initDefaultValues(SentryFlutterOptions options) async { options.addEventProcessor(FlutterExceptionEventProcessor()); // Not all platforms have a native integration. if (_native != null) { - options.transport = FileSystemTransport(channel, options); + options.transport = FileSystemTransport(_native!, options); options.addScopeObserver(NativeScopeObserver(_native!)); } @@ -136,13 +130,11 @@ mixin SentryFlutter { /// Install default integrations /// https://medium.com/flutter-community/error-handling-in-flutter-98fce88a34f0 static List _createDefaultIntegrations( - MethodChannel channel, SentryFlutterOptions options, bool isOnErrorSupported, ) { final integrations = []; final platformChecker = options.platformChecker; - final platform = platformChecker.platform; // Will call WidgetsFlutterBinding.ensureInitialized() before all other integrations. integrations.add(WidgetsFlutterBindingIntegration()); @@ -161,22 +153,13 @@ mixin SentryFlutter { // The ordering here matters, as we'd like to first start the native integration. // That allow us to send events to the network and then the Flutter integrations. // Flutter Web doesn't need that, only Android and iOS. - if (_native != null) { - integrations.add(NativeSdkIntegration(_native!)); - } - - // Will enrich events with device context, native packages and integrations - if (platformChecker.hasNativeIntegration && - !platformChecker.isWeb && - (platform.isIOS || platform.isMacOS || platform.isAndroid)) { - integrations.add(LoadContextsIntegration(channel)); + final native = _native; + if (native != null) { + integrations.add(NativeSdkIntegration(native)); + integrations.add(LoadContextsIntegration(native)); + integrations.add(LoadImageListIntegration(native)); } - if (platformChecker.hasNativeIntegration && - !platformChecker.isWeb && - (platform.isAndroid || platform.isIOS || platform.isMacOS)) { - integrations.add(LoadImageListIntegration(channel)); - } final renderer = options.rendererWrapper.getRenderer(); if (!platformChecker.isWeb || renderer == FlutterRenderer.canvasKit) { integrations.add(ScreenshotIntegration()); @@ -196,9 +179,9 @@ mixin SentryFlutter { // in errors. integrations.add(LoadReleaseIntegration()); - if (_native != null) { + if (native != null) { integrations.add(NativeAppStartIntegration( - _native!, + native, DefaultFrameCallbackHandler(), )); } @@ -218,7 +201,7 @@ mixin SentryFlutter { /// Manually set when your app finished startup. Make sure to set /// [SentryFlutterOptions.autoAppStart] to false on init. static void setAppStartEnd(DateTime appStartEnd) { - _native?.appStartEnd = appStartEnd; + NativeAppStartIntegration.appStartEnd = appStartEnd; } static void _setSdk(SentryFlutterOptions options) { @@ -240,9 +223,10 @@ mixin SentryFlutter { } @internal - static SentryNative? get native => _native; + static SentryNativeBinding? get native => _native; @internal - static set native(SentryNative? value) => _native = value; - static SentryNative? _native; + static set native(SentryNativeBinding? value) => _native = value; + + static SentryNativeBinding? _native; } diff --git a/flutter/test/file_system_transport_test.dart b/flutter/test/file_system_transport_test.dart index aa948e56fb..a658ab9f17 100644 --- a/flutter/test/file_system_transport_test.dart +++ b/flutter/test/file_system_transport_test.dart @@ -8,32 +8,22 @@ import 'dart:typed_data'; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:mockito/mockito.dart'; import 'package:sentry/sentry.dart'; import 'package:sentry_flutter/src/file_system_transport.dart'; import 'mocks.dart'; +import 'mocks.mocks.dart'; void main() { - const _channel = MethodChannel('sentry_flutter'); - - TestWidgetsFlutterBinding.ensureInitialized(); - late Fixture fixture; setUp(() { fixture = Fixture(); }); - tearDown(() { - // ignore: deprecated_member_use - _channel.setMockMethodCallHandler(null); - }); - - test('FileSystemTransport wont throw', () async { - // ignore: deprecated_member_use - _channel.setMockMethodCallHandler((MethodCall methodCall) async {}); - - final transport = fixture.getSut(_channel); + test("$FileSystemTransport won't throw", () async { + final transport = fixture.getSut(); final event = SentryEvent(); final sdkVersion = SdkVersion(name: 'fixture-sdkName', version: 'fixture-sdkVersion'); @@ -48,13 +38,10 @@ void main() { expect(sentryId, sentryId); }); - test('FileSystemTransport returns emptyId if channel throws', () async { - // ignore: deprecated_member_use - _channel.setMockMethodCallHandler((MethodCall methodCall) async { - throw Exception(); - }); + test('$FileSystemTransport returns emptyId if channel throws', () async { + when(fixture.binding.captureEnvelope(any)).thenThrow(Exception()); - final transport = fixture.getSut(_channel); + final transport = fixture.getSut(); final event = SentryEvent(); final sdkVersion = SdkVersion(name: 'fixture-sdkName', version: 'fixture-sdkVersion'); @@ -69,14 +56,8 @@ void main() { expect(SentryId.empty(), sentryId); }); - test('FileSystemTransport asserts the event', () async { - dynamic arguments; - // ignore: deprecated_member_use - _channel.setMockMethodCallHandler((MethodCall methodCall) async { - arguments = methodCall.arguments; - }); - - final transport = fixture.getSut(_channel); + test('$FileSystemTransport asserts the event', () async { + final transport = fixture.getSut(); final event = SentryEvent(message: SentryMessage('hi I am a special char ◤')); @@ -89,8 +70,9 @@ void main() { ); await transport.send(envelope); - final envelopeList = arguments as List; - final envelopeData = envelopeList.first as Uint8List; + final envelopeData = verify(fixture.binding.captureEnvelope(captureAny)) + .captured + .single as Uint8List; final envelopeString = utf8.decode(envelopeData); final lines = envelopeString.split('\n'); final envelopeHeader = lines.first; @@ -120,8 +102,9 @@ void main() { class Fixture { final options = SentryOptions(dsn: fakeDsn); + final binding = MockSentryNativeBinding(); - FileSystemTransport getSut(MethodChannel channel) { - return FileSystemTransport(channel, options); + FileSystemTransport getSut() { + return FileSystemTransport(binding, options); } } diff --git a/flutter/test/integrations/fixture.dart b/flutter/test/integrations/fixture.dart new file mode 100644 index 0000000000..19a5ed7904 --- /dev/null +++ b/flutter/test/integrations/fixture.dart @@ -0,0 +1,26 @@ +import 'dart:async'; + +import 'package:sentry_flutter/sentry_flutter.dart'; +import 'package:sentry_flutter/src/native/sentry_native_binding.dart'; + +import '../mocks.dart'; +import '../mocks.mocks.dart'; + +class IntegrationTestFixture { + late T sut; + late Hub hub; + final options = SentryFlutterOptions(dsn: fakeDsn); + final binding = MockSentryNativeBinding(); + + IntegrationTestFixture(T Function(SentryNativeBinding) factory) { + // ignore: invalid_use_of_internal_member + options.automatedTestMode = true; + + hub = Hub(options); + sut = factory(binding); + } + + Future registerIntegration() async { + await sut.call(hub, options); + } +} diff --git a/flutter/test/integrations/init_native_sdk_test.dart b/flutter/test/integrations/init_native_sdk_test.dart index 6d3bd57e22..0dcf3af502 100644 --- a/flutter/test/integrations/init_native_sdk_test.dart +++ b/flutter/test/integrations/init_native_sdk_test.dart @@ -25,7 +25,7 @@ void main() { }); var sut = fixture.getSut(channel); - await sut.init(createOptions()); + await sut.init(fixture.options); channel.setMethodCallHandler(null); @@ -76,7 +76,7 @@ void main() { }); var sut = fixture.getSut(channel); - final options = createOptions() + fixture.options ..debug = false ..environment = 'foo' ..release = 'foo@bar+1' @@ -106,10 +106,10 @@ void main() { ..readTimeout = Duration(milliseconds: 9002) ..appHangTimeoutInterval = Duration(milliseconds: 9003); - options.sdk.addIntegration('foo'); - options.sdk.addPackage('bar', '1'); + fixture.options.sdk.addIntegration('foo'); + fixture.options.sdk.addPackage('bar', '1'); - await sut.init(options); + await sut.init(fixture.options); channel.setMethodCallHandler(null); @@ -177,7 +177,9 @@ SentryFlutterOptions createOptions() { } class Fixture { + late SentryFlutterOptions options; SentryNativeChannel getSut(MethodChannel native) { - return SentryNativeChannel(native); + options = createOptions(); + return SentryNativeChannel(options, native); } } diff --git a/flutter/test/integrations/load_contexts_integration_test.dart b/flutter/test/integrations/load_contexts_integration_test.dart index a3bbbcbab7..5acce8d264 100644 --- a/flutter/test/integrations/load_contexts_integration_test.dart +++ b/flutter/test/integrations/load_contexts_integration_test.dart @@ -1,40 +1,23 @@ @TestOn('vm') library flutter_test; -import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/mockito.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:sentry_flutter/src/integrations/load_contexts_integration.dart'; -import '../mocks.dart'; -import '../mocks.mocks.dart'; +import 'fixture.dart'; void main() { group(LoadContextsIntegration, () { - const _channel = MethodChannel('sentry_flutter'); + late IntegrationTestFixture fixture; - TestWidgetsFlutterBinding.ensureInitialized(); - - late Fixture fixture; - - setUp(() { - fixture = Fixture(); - }); - - tearDown(() { - // ignore: deprecated_member_use - _channel.setMockMethodCallHandler(null); + setUp(() async { + fixture = IntegrationTestFixture(LoadContextsIntegration.new); + await fixture.registerIntegration(); }); test('loadContextsIntegration adds integration', () { - // ignore: deprecated_member_use - _channel.setMockMethodCallHandler((MethodCall methodCall) async {}); - - final integration = LoadContextsIntegration(_channel); - - integration(fixture.hub, fixture.options); - expect( fixture.options.sdk.integrations.contains('loadContextsIntegration'), true); @@ -46,19 +29,10 @@ void main() { final eventBreadcrumb = Breadcrumb(message: 'event'); var event = SentryEvent(breadcrumbs: [eventBreadcrumb]); - final nativeBreadcrumb = Breadcrumb(message: 'native'); - Map loadContexts = { - 'breadcrumbs': [nativeBreadcrumb.toJson()] - }; - - final future = Future.value(loadContexts); - when(fixture.methodChannel.invokeMethod('loadContexts')) - .thenAnswer((_) => future); - // ignore: deprecated_member_use - _channel.setMockMethodCallHandler((MethodCall methodCall) async {}); + when(fixture.binding.loadContexts()).thenAnswer((_) async => { + 'breadcrumbs': [Breadcrumb(message: 'native').toJson()] + }); - final integration = LoadContextsIntegration(fixture.methodChannel); - integration.call(fixture.hub, fixture.options); event = (await fixture.options.eventProcessors.first.apply(event, Hint()))!; @@ -72,19 +46,10 @@ void main() { final eventBreadcrumb = Breadcrumb(message: 'event'); var event = SentryEvent(breadcrumbs: [eventBreadcrumb]); - final nativeBreadcrumb = Breadcrumb(message: 'native'); - Map loadContexts = { - 'breadcrumbs': [nativeBreadcrumb.toJson()] - }; - - final future = Future.value(loadContexts); - when(fixture.methodChannel.invokeMethod('loadContexts')) - .thenAnswer((_) => future); - // ignore: deprecated_member_use - _channel.setMockMethodCallHandler((MethodCall methodCall) async {}); + when(fixture.binding.loadContexts()).thenAnswer((_) async => { + 'breadcrumbs': [Breadcrumb(message: 'native').toJson()] + }); - final integration = LoadContextsIntegration(fixture.methodChannel); - integration.call(fixture.hub, fixture.options); event = (await fixture.options.eventProcessors.first.apply(event, Hint()))!; @@ -105,23 +70,13 @@ void main() { final eventBreadcrumb = Breadcrumb(message: 'event'); var event = SentryEvent(breadcrumbs: [eventBreadcrumb]); - final nativeMutatedBreadcrumb = Breadcrumb(message: 'native-mutated'); - final nativeDeletedBreadcrumb = Breadcrumb(message: 'native-deleted'); - Map loadContexts = { - 'breadcrumbs': [ - nativeMutatedBreadcrumb.toJson(), - nativeDeletedBreadcrumb.toJson(), - ] - }; - - final future = Future.value(loadContexts); - when(fixture.methodChannel.invokeMethod('loadContexts')) - .thenAnswer((_) => future); - // ignore: deprecated_member_use - _channel.setMockMethodCallHandler((MethodCall methodCall) async {}); + when(fixture.binding.loadContexts()).thenAnswer((_) async => { + 'breadcrumbs': [ + Breadcrumb(message: 'native-mutated').toJson(), + Breadcrumb(message: 'native-deleted').toJson(), + ] + }); - final integration = LoadContextsIntegration(fixture.methodChannel); - integration.call(fixture.hub, fixture.options); event = (await fixture.options.eventProcessors.first.apply(event, Hint()))!; @@ -148,16 +103,8 @@ void main() { final options = fixture.options; final user = SentryUser(id: expectedId); - Map loadContexts = {'user': user.toJson()}; - final future = Future.value(loadContexts); - when(fixture.methodChannel.invokeMethod('loadContexts')) - .thenAnswer((_) => future); - // ignore: deprecated_member_use - _channel.setMockMethodCallHandler((MethodCall methodCall) async {}); - - final integration = LoadContextsIntegration(fixture.methodChannel); - options.addIntegration(integration); - options.integrations.first.call(fixture.hub, options); + when(fixture.binding.loadContexts()) + .thenAnswer((_) async => {'user': user.toJson()}); final client = SentryClient(options); final event = SentryEvent(); @@ -169,10 +116,3 @@ void main() { }); }); } - -class Fixture { - final hub = MockHub(); - final options = SentryFlutterOptions(dsn: fakeDsn); - - final methodChannel = MockMethodChannel(); -} diff --git a/flutter/test/integrations/load_contexts_integrations_test.dart b/flutter/test/integrations/load_contexts_integrations_test.dart index 8c7ae456e0..a1490b8212 100644 --- a/flutter/test/integrations/load_contexts_integrations_test.dart +++ b/flutter/test/integrations/load_contexts_integrations_test.dart @@ -1,8 +1,8 @@ @TestOn('vm') library flutter_test; -import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:mockito/mockito.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:sentry_flutter/src/integrations/load_contexts_integration.dart'; @@ -84,7 +84,7 @@ void main() { final event = await fixture.options.eventProcessors.first.apply(e, Hint()); - expect(fixture.called, true); + verify(fixture.binding.loadContexts()).called(1); expect(event?.contexts.device?.name, 'Device1'); expect(event?.contexts.app?.name, 'test-app'); expect(event?.contexts.app?.inForeground, true); @@ -124,7 +124,7 @@ void main() { final event = await fixture.options.eventProcessors.first.apply(e, Hint()); - expect(fixture.called, true); + verify(fixture.binding.loadContexts()).called(1); expect(event?.contexts.device?.name, 'eDevice'); expect(event?.contexts.app?.name, 'eApp'); expect(event?.contexts.app?.inForeground, true); @@ -236,10 +236,7 @@ void main() { ); test('should not throw on loadContextsIntegration exception', () async { - // ignore: deprecated_member_use - fixture.channel.setMockMethodCallHandler((MethodCall methodCall) async { - throw Exception(); - }); + when(fixture.binding.loadContexts()).thenThrow(Exception()); final integration = fixture.getSut(); integration(fixture.hub, fixture.options); @@ -426,12 +423,9 @@ void main() { } class Fixture { - final channel = MethodChannel('sentry_flutter'); - final hub = MockHub(); final options = SentryFlutterOptions(); - - var called = false; + final binding = MockSentryNativeBinding(); LoadContextsIntegration getSut( {Map contexts = const { @@ -466,12 +460,7 @@ class Fixture { } ] }}) { - // ignore: deprecated_member_use - channel.setMockMethodCallHandler((MethodCall methodCall) async { - called = true; - return contexts; - }); - - return LoadContextsIntegration(channel); + when(binding.loadContexts()).thenAnswer((_) async => contexts); + return LoadContextsIntegration(binding); } } diff --git a/flutter/test/integrations/load_image_list_test.dart b/flutter/test/integrations/load_image_list_test.dart index f7c72fc95e..35e59b7599 100644 --- a/flutter/test/integrations/load_image_list_test.dart +++ b/flutter/test/integrations/load_image_list_test.dart @@ -1,121 +1,62 @@ @TestOn('vm') library flutter_test; -import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:mockito/mockito.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:sentry_flutter/src/integrations/load_image_list_integration.dart'; -import '../mocks.dart'; -import '../sentry_flutter_test.dart'; +import 'fixture.dart'; void main() { group(LoadImageListIntegration, () { - TestWidgetsFlutterBinding.ensureInitialized(); - late Fixture fixture; + final imageList = [ + DebugImage.fromJson({ + 'code_file': '/apex/com.android.art/javalib/arm64/boot.oat', + 'code_id': '13577ce71153c228ecf0eb73fc39f45010d487f8', + 'image_addr': '0x6f80b000', + 'image_size': 3092480, + 'type': 'elf', + 'debug_id': 'e77c5713-5311-28c2-ecf0-eb73fc39f450', + 'debug_file': 'test' + }) + ]; + + late IntegrationTestFixture fixture; + + setUp(() async { + fixture = IntegrationTestFixture(LoadImageListIntegration.new); + when(fixture.binding.loadDebugImages()) + .thenAnswer((_) async => imageList); + await fixture.registerIntegration(); + }); + + test('$LoadImageListIntegration adds itself to sdk.integrations', () async { + expect( + fixture.options.sdk.integrations.contains('loadImageListIntegration'), + true, + ); + }); + + test('Native layer is not called as the event is symbolicated', () async { + expect(fixture.options.eventProcessors.length, 1); + + await fixture.hub.captureException(StateError('error'), + stackTrace: StackTrace.current); + + verifyNever(fixture.binding.loadDebugImages()); + }); + + test('Native layer is not called if the event has no stack traces', + () async { + await fixture.hub.captureException(StateError('error')); - tearDown(() { - // ignore: deprecated_member_use - fixture.channel.setMockMethodCallHandler(null); + verifyNever(fixture.binding.loadDebugImages()); }); - for (var platform in [ - MockPlatform.android(), - MockPlatform.iOs(), - MockPlatform.macOs() - ]) { - group(platform.operatingSystem, () { - final imageList = [ - { - 'code_file': '/apex/com.android.art/javalib/arm64/boot.oat', - 'code_id': '13577ce71153c228ecf0eb73fc39f45010d487f8', - 'image_addr': '0x6f80b000', - 'image_size': 3092480, - 'type': 'elf', - 'debug_id': 'e77c5713-5311-28c2-ecf0-eb73fc39f450', - 'debug_file': 'test' - } - ]; - - setUp(() { - fixture = Fixture(platform); - fixture.channel - // ignore: deprecated_member_use - .setMockMethodCallHandler((MethodCall methodCall) async { - return imageList; - }); - }); - - test('$LoadImageListIntegration adds itself to sdk.integrations', - () async { - final sut = fixture.getSut(); - - sut.call(fixture.hub, fixture.options); - - expect( - fixture.options.sdk.integrations - .contains('loadImageListIntegration'), - true, - ); - }); - - test('Native layer is not called as the event is symbolicated', - () async { - var called = false; - - final sut = fixture.getSut(); - fixture.channel - // ignore: deprecated_member_use - .setMockMethodCallHandler((MethodCall methodCall) async { - called = true; - return imageList; - }); - - sut.call(fixture.hub, fixture.options); - - expect(fixture.options.eventProcessors.length, 1); - - await fixture.hub.captureException(StateError('error'), - stackTrace: StackTrace.current); - - expect(called, false); - }); - - test('Native layer is not called if the event has no stack traces', - () async { - var called = false; - - final sut = fixture.getSut(); - fixture.channel - // ignore: deprecated_member_use - .setMockMethodCallHandler((MethodCall methodCall) async { - called = true; - return imageList; - }); - - sut.call(fixture.hub, fixture.options); - - await fixture.hub.captureException(StateError('error')); - - expect(called, false); - }); - - test('Native layer is called because stack traces are not symbolicated', - () async { - var called = false; - - final sut = fixture.getSut(); - fixture.channel - // ignore: deprecated_member_use - .setMockMethodCallHandler((MethodCall methodCall) async { - called = true; - return imageList; - }); - - sut.call(fixture.hub, fixture.options); - - await fixture.hub - .captureException(StateError('error'), stackTrace: ''' + test('Native layer is called because stack traces are not symbolicated', + () async { + await fixture.hub.captureException(StateError('error'), stackTrace: ''' warning: This VM has been configured to produce stack traces that violate the Dart standard. *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** pid: 30930, tid: 30990, name 1.ui @@ -126,62 +67,41 @@ void main() { #01 abs 000000723d637527 virt 00000000001f0527 _kDartIsolateSnapshotInstructions+0x1e5527 '''); - expect(called, true); - }); - - test('Event processor adds image list to the event', () async { - final sut = fixture.getSut(); - - sut.call(fixture.hub, fixture.options); - - final ep = fixture.options.eventProcessors.first; - SentryEvent? event = _getEvent(); - event = await ep.apply(event, Hint()); - - expect(1, event!.debugMeta!.images.length); - }); - - test('Event processor asserts image list', () async { - final sut = fixture.getSut(); - - sut.call(fixture.hub, fixture.options); - final ep = fixture.options.eventProcessors.first; - SentryEvent? event = _getEvent(); - event = await ep.apply(event, Hint()); - - final image = event!.debugMeta!.images.first; + verify(fixture.binding.loadDebugImages()).called(1); + }); - expect( - '/apex/com.android.art/javalib/arm64/boot.oat', image.codeFile); - expect('13577ce71153c228ecf0eb73fc39f45010d487f8', image.codeId); - expect('0x6f80b000', image.imageAddr); - expect(3092480, image.imageSize); - expect('elf', image.type); - expect('e77c5713-5311-28c2-ecf0-eb73fc39f450', image.debugId); - expect('test', image.debugFile); - }); + test('Event processor adds image list to the event', () async { + final ep = fixture.options.eventProcessors.first; + expect( + ep.runtimeType.toString(), "_LoadImageListIntegrationEventProcessor"); + SentryEvent? event = _getEvent(); + event = await ep.apply(event, Hint()); - test('Native layer is not called as there is no exceptions', () async { - var called = false; + expect(1, event!.debugMeta!.images.length); + }); - final sut = fixture.getSut(); - fixture.channel - // ignore: deprecated_member_use - .setMockMethodCallHandler((MethodCall methodCall) async { - called = true; - return imageList; - }); + test('Event processor asserts image list', () async { + final ep = fixture.options.eventProcessors.first; + SentryEvent? event = _getEvent(); + event = await ep.apply(event, Hint()); - sut.call(fixture.hub, fixture.options); + final image = event!.debugMeta!.images.first; - expect(fixture.options.eventProcessors.length, 1); + expect('/apex/com.android.art/javalib/arm64/boot.oat', image.codeFile); + expect('13577ce71153c228ecf0eb73fc39f45010d487f8', image.codeId); + expect('0x6f80b000', image.imageAddr); + expect(3092480, image.imageSize); + expect('elf', image.type); + expect('e77c5713-5311-28c2-ecf0-eb73fc39f450', image.debugId); + expect('test', image.debugFile); + }); - await fixture.hub.captureMessage('error'); + test('Native layer is not called as there is no exceptions', () async { + expect(fixture.options.eventProcessors.length, 1); - expect(called, false); - }); - }); - } + await fixture.hub.captureMessage('error'); + verifyNever(fixture.binding.loadDebugImages()); + }); }); } @@ -190,19 +110,3 @@ SentryEvent _getEvent() { final st = SentryStackTrace(frames: [frame]); return SentryEvent(threads: [SentryThread(stacktrace: st)]); } - -class Fixture { - late final Hub hub; - late final SentryFlutterOptions options; - final channel = MethodChannel('sentry_flutter'); - - Fixture(MockPlatform platform) { - options = SentryFlutterOptions( - dsn: fakeDsn, checker: getPlatformChecker(platform: platform)); - hub = Hub(options); - } - - LoadImageListIntegration getSut() { - return LoadImageListIntegration(channel); - } -} diff --git a/flutter/test/integrations/native_app_start_integration_test.dart b/flutter/test/integrations/native_app_start_integration_test.dart index eb13b41a8d..c472b0fa60 100644 --- a/flutter/test/integrations/native_app_start_integration_test.dart +++ b/flutter/test/integrations/native_app_start_integration_test.dart @@ -5,13 +5,14 @@ import 'package:collection/collection.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/mockito.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; +import 'package:sentry_flutter/src/integrations/integrations.dart'; import 'package:sentry_flutter/src/integrations/native_app_start_integration.dart'; -import 'package:sentry_flutter/src/native/sentry_native.dart'; import 'package:sentry/src/sentry_tracer.dart'; +import 'package:sentry_flutter/src/native/native_app_start.dart'; import '../fake_frame_callback_handler.dart'; -import '../mocks.dart'; import '../mocks.mocks.dart'; +import 'fixture.dart'; void main() { void setupMocks(Fixture fixture) { @@ -28,23 +29,22 @@ void main() { late Fixture fixture; setUp(() { - TestWidgetsFlutterBinding.ensureInitialized(); - fixture = Fixture(); setupMocks(fixture); - + when(fixture.binding.fetchNativeAppStart()).thenAnswer((_) async => + NativeAppStart( + appStartTime: 0, + pluginRegistrationTime: 10, + isColdStart: true, + nativeSpanTimes: {})); NativeAppStartIntegration.clearAppStartInfo(); }); test('native app start measurement added to first transaction', () async { - fixture.native.appStartEnd = DateTime.fromMillisecondsSinceEpoch(10); - fixture.binding.nativeAppStart = NativeAppStart( - appStartTime: 0, - pluginRegistrationTime: 10, - isColdStart: true, - nativeSpanTimes: {}); + NativeAppStartIntegration.appStartEnd = + DateTime.fromMillisecondsSinceEpoch(10); - fixture.getNativeAppStartIntegration().call(fixture.hub, fixture.options); + await fixture.registerIntegration(); final tracer = fixture.createTracer(); final transaction = SentryTransaction(tracer); @@ -60,14 +60,10 @@ void main() { test('native app start measurement not added to following transactions', () async { - fixture.native.appStartEnd = DateTime.fromMillisecondsSinceEpoch(10); - fixture.binding.nativeAppStart = NativeAppStart( - appStartTime: 0, - pluginRegistrationTime: 10, - isColdStart: true, - nativeSpanTimes: {}); + NativeAppStartIntegration.appStartEnd = + DateTime.fromMillisecondsSinceEpoch(10); - fixture.getNativeAppStartIntegration().call(fixture.hub, fixture.options); + await fixture.registerIntegration(); final tracer = fixture.createTracer(); final transaction = SentryTransaction(tracer); @@ -83,15 +79,11 @@ void main() { }); test('measurements appended', () async { - fixture.native.appStartEnd = DateTime.fromMillisecondsSinceEpoch(10); - fixture.binding.nativeAppStart = NativeAppStart( - appStartTime: 0, - pluginRegistrationTime: 10, - isColdStart: true, - nativeSpanTimes: {}); + NativeAppStartIntegration.appStartEnd = + DateTime.fromMillisecondsSinceEpoch(10); final measurement = SentryMeasurement.warmAppStart(Duration(seconds: 1)); - fixture.getNativeAppStartIntegration().call(fixture.hub, fixture.options); + await fixture.registerIntegration(); final tracer = fixture.createTracer(); final transaction = SentryTransaction(tracer).copyWith(); @@ -109,14 +101,10 @@ void main() { }); test('native app start measurement not added if more than 60s', () async { - fixture.native.appStartEnd = DateTime.fromMillisecondsSinceEpoch(60001); - fixture.binding.nativeAppStart = NativeAppStart( - appStartTime: 0, - pluginRegistrationTime: 10, - isColdStart: true, - nativeSpanTimes: {}); + NativeAppStartIntegration.appStartEnd = + DateTime.fromMillisecondsSinceEpoch(60001); - fixture.getNativeAppStartIntegration().call(fixture.hub, fixture.options); + await fixture.registerIntegration(); final tracer = fixture.createTracer(); final transaction = SentryTransaction(tracer); @@ -130,14 +118,10 @@ void main() { test('native app start integration is called and sets app start info', () async { - fixture.native.appStartEnd = DateTime.fromMillisecondsSinceEpoch(10); - fixture.binding.nativeAppStart = NativeAppStart( - appStartTime: 0, - pluginRegistrationTime: 10, - isColdStart: true, - nativeSpanTimes: {}); + NativeAppStartIntegration.appStartEnd = + DateTime.fromMillisecondsSinceEpoch(10); - fixture.getNativeAppStartIntegration().call(fixture.hub, fixture.options); + await fixture.registerIntegration(); final appStartInfo = await NativeAppStartIntegration.getAppStartInfo(); expect(appStartInfo?.start, DateTime.fromMillisecondsSinceEpoch(0)); @@ -148,13 +132,8 @@ void main() { 'autoAppStart is false and appStartEnd is not set does not add app start measurement', () async { fixture.options.autoAppStart = false; - fixture.binding.nativeAppStart = NativeAppStart( - appStartTime: 0, - pluginRegistrationTime: 10, - isColdStart: true, - nativeSpanTimes: {}); - fixture.getNativeAppStartIntegration().call(fixture.hub, fixture.options); + await fixture.registerIntegration(); final tracer = fixture.createTracer(); final transaction = SentryTransaction(tracer); @@ -171,14 +150,8 @@ void main() { 'autoAppStart is false and appStartEnd is set adds app start measurement', () async { fixture.options.autoAppStart = false; - fixture.binding.nativeAppStart = NativeAppStart( - appStartTime: 0, - pluginRegistrationTime: 10, - isColdStart: true, - nativeSpanTimes: {}); - SentryFlutter.native = fixture.native; - fixture.getNativeAppStartIntegration().call(fixture.hub, fixture.options); + await fixture.registerIntegration(); SentryFlutter.setAppStartEnd(DateTime.fromMillisecondsSinceEpoch(10)); @@ -250,29 +223,32 @@ void main() { }, }; - final allNativeSpanTimes = { - ...validNativeSpanTimes, - ...invalidNativeSpanTimes, - }; + final appStartInfoSrc = NativeAppStart( + appStartTime: 0, + pluginRegistrationTime: 10, + isColdStart: true, + nativeSpanTimes: { + ...validNativeSpanTimes, + ...invalidNativeSpanTimes, + }); setUp(() async { - TestWidgetsFlutterBinding.ensureInitialized(); - fixture = Fixture(); NativeAppStartIntegration.clearAppStartInfo(); - fixture.native.appStartEnd = DateTime.fromMillisecondsSinceEpoch(50); - fixture.binding.nativeAppStart = NativeAppStart( - appStartTime: 0, - pluginRegistrationTime: 10, - isColdStart: true, - nativeSpanTimes: allNativeSpanTimes); + NativeAppStartIntegration.appStartEnd = + DateTime.fromMillisecondsSinceEpoch(50); + // dartLoadingEnd needs to be set after engine end (see MockNativeChannel) SentryFlutter.sentrySetupStartTime = DateTime.fromMillisecondsSinceEpoch(15); setupMocks(fixture); - fixture.getNativeAppStartIntegration().call(fixture.hub, fixture.options); + + when(fixture.binding.fetchNativeAppStart()) + .thenAnswer((_) async => appStartInfoSrc); + + await fixture.registerIntegration(); final processor = fixture.options.eventProcessors.first; tracer = fixture.createTracer(); @@ -380,7 +356,7 @@ void main() { test('have correct startTimestamp', () async { final appStartTime = DateTime.fromMillisecondsSinceEpoch( - fixture.binding.nativeAppStart!.appStartTime.toInt()) + appStartInfoSrc.appStartTime.toInt()) .toUtc(); expect(coldStartSpan?.startTimestamp, appStartTime); expect(pluginRegistrationSpan?.startTimestamp, appStartTime); @@ -392,9 +368,10 @@ void main() { test('have correct endTimestamp', () async { final engineReadyEndtime = DateTime.fromMillisecondsSinceEpoch( - fixture.binding.nativeAppStart!.pluginRegistrationTime.toInt()) + appStartInfoSrc.pluginRegistrationTime.toInt()) .toUtc(); - expect(coldStartSpan?.endTimestamp, fixture.native.appStartEnd?.toUtc()); + expect(coldStartSpan?.endTimestamp, + NativeAppStartIntegration.appStartEnd?.toUtc()); expect(pluginRegistrationSpan?.endTimestamp, engineReadyEndtime); expect(sentrySetupSpan?.endTimestamp, SentryFlutter.sentrySetupStartTime?.toUtc()); @@ -403,25 +380,20 @@ void main() { }); } -class Fixture { - final hub = MockHub(); - final options = SentryFlutterOptions(dsn: fakeDsn); - final binding = MockNativeChannel(); - late final native = SentryNative(options, binding); +class Fixture extends IntegrationTestFixture { + @override + MockHub get hub => super.hub as MockHub; - Fixture() { - native.reset(); + Fixture() + : super((binding) => + NativeAppStartIntegration(binding, FakeFrameCallbackHandler())) { + NativeAppStartIntegration.reset(); + hub = MockHub(); + // ignore: invalid_use_of_internal_member when(hub.options).thenReturn(options); SentryFlutter.sentrySetupStartTime = DateTime.now().toUtc(); } - NativeAppStartIntegration getNativeAppStartIntegration() { - return NativeAppStartIntegration( - native, - FakeFrameCallbackHandler(), - ); - } - // ignore: invalid_use_of_internal_member SentryTracer createTracer({ bool? sampled = true, diff --git a/flutter/test/integrations/native_sdk_integration_test.dart b/flutter/test/integrations/native_sdk_integration_test.dart index 1826bd38f2..f94f88698c 100644 --- a/flutter/test/integrations/native_sdk_integration_test.dart +++ b/flutter/test/integrations/native_sdk_integration_test.dart @@ -1,110 +1,66 @@ @TestOn('vm') library flutter_test; -import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:mockito/mockito.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:sentry_flutter/src/integrations/native_sdk_integration.dart'; -import '../mocks.dart'; import '../mocks.mocks.dart'; +import 'fixture.dart'; void main() { group(NativeSdkIntegration, () { - const _channel = MethodChannel('sentry_flutter'); - - TestWidgetsFlutterBinding.ensureInitialized(); - - late Fixture fixture; + late IntegrationTestFixture fixture; setUp(() { - fixture = Fixture(); - }); - - tearDown(() { - // ignore: deprecated_member_use - _channel.setMockMethodCallHandler(null); + fixture = IntegrationTestFixture(NativeSdkIntegration.new); }); test('adds integration', () async { - // ignore: deprecated_member_use - _channel.setMockMethodCallHandler((MethodCall methodCall) async {}); - final mock = TestMockSentryNative(); - final integration = NativeSdkIntegration(mock); - - await integration(fixture.hub, fixture.options); - + await fixture.registerIntegration(); expect( fixture.options.sdk.integrations, contains('nativeSdkIntegration')); - expect(mock.numberOfInitCalls, 1); + verify(fixture.binding.init(any)).called(1); }); test('do not throw', () async { - final integration = NativeSdkIntegration(_ThrowingMockSentryNative()); - - await integration(fixture.hub, fixture.options); - + fixture.sut = NativeSdkIntegration(_ThrowingMockSentryNative()); + await fixture.registerIntegration(); expect(fixture.options.sdk.integrations.contains('nativeSdkIntegration'), false); }); test('closes native SDK', () async { - final mock = TestMockSentryNative(); - final integration = NativeSdkIntegration(mock); - - await integration.call(fixture.hub, fixture.options); - await integration.close(); - - expect(mock.numberOfCloseCalls, 1); + await fixture.registerIntegration(); + await fixture.sut.close(); + verify(fixture.binding.close()).called(1); }); test('does not call native sdk when auto init disabled', () async { - final mock = TestMockSentryNative(); - final integration = NativeSdkIntegration(mock); fixture.options.autoInitializeNativeSdk = false; - - await integration.call(fixture.hub, fixture.options); - - expect(mock.numberOfInitCalls, 0); + await fixture.registerIntegration(); + verifyNever(fixture.binding.init(any)); }); test('does not close native when auto init disabled', () async { - final mock = TestMockSentryNative(); - final integration = NativeSdkIntegration(mock); fixture.options.autoInitializeNativeSdk = false; - - await integration(fixture.hub, fixture.options); - await integration.close(); - - expect(mock.numberOfCloseCalls, 0); - }); - - test('adds integration', () async { - final mock = TestMockSentryNative(); - final integration = NativeSdkIntegration(mock); - - await integration.call(fixture.hub, fixture.options); - - expect(fixture.options.sdk.integrations, ['nativeSdkIntegration']); + await fixture.registerIntegration(); + await fixture.sut.close(); + verifyNever(fixture.binding.close()); }); test(' is not added in case of an exception', () async { - final integration = NativeSdkIntegration(_ThrowingMockSentryNative()); - - await integration.call(fixture.hub, fixture.options); + fixture.sut = NativeSdkIntegration(_ThrowingMockSentryNative()); + await fixture.registerIntegration(); expect(fixture.options.sdk.integrations, []); }); }); } -class Fixture { - final hub = MockHub(); - final options = SentryFlutterOptions(dsn: fakeDsn); -} - -class _ThrowingMockSentryNative extends TestMockSentryNative { +class _ThrowingMockSentryNative extends MockSentryNativeBinding { @override - Future init(SentryFlutterOptions options) async { + Future init(SentryFlutterOptions? options) async { throw Exception(); } } diff --git a/flutter/test/load_image_list_test.dart b/flutter/test/load_image_list_test.dart deleted file mode 100644 index 472aac0947..0000000000 --- a/flutter/test/load_image_list_test.dart +++ /dev/null @@ -1,183 +0,0 @@ -@TestOn('vm') -library flutter_test; - -import 'package:flutter/services.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:sentry_flutter/sentry_flutter.dart'; -import 'package:sentry_flutter/src/integrations/load_image_list_integration.dart'; - -import 'mocks.dart'; -import 'sentry_flutter_test.dart'; - -void main() { - TestWidgetsFlutterBinding.ensureInitialized(); - late Fixture fixture; - - tearDown(() { - // ignore: deprecated_member_use - fixture.channel.setMockMethodCallHandler(null); - }); - - for (var platform in [ - MockPlatform.android(), - MockPlatform.iOs(), - MockPlatform.macOs() - ]) { - group(platform.operatingSystem, () { - final imageList = [ - { - 'code_file': '/apex/com.android.art/javalib/arm64/boot.oat', - 'code_id': '13577ce71153c228ecf0eb73fc39f45010d487f8', - 'image_addr': '0x6f80b000', - 'image_size': 3092480, - 'type': 'elf', - 'debug_id': 'e77c5713-5311-28c2-ecf0-eb73fc39f450', - 'debug_file': 'test' - } - ]; - - setUp(() { - fixture = Fixture(platform); - // ignore: deprecated_member_use - fixture.channel.setMockMethodCallHandler((MethodCall methodCall) async { - return imageList; - }); - }); - - test('$LoadImageListIntegration adds itself to sdk.integrations', - () async { - final sut = fixture.getSut(); - - sut.call(fixture.hub, fixture.options); - - expect( - fixture.options.sdk.integrations.contains('loadImageListIntegration'), - true, - ); - }); - - test('Native layer is not called as the event is symbolicated', () async { - var called = false; - - final sut = fixture.getSut(); - // ignore: deprecated_member_use - fixture.channel.setMockMethodCallHandler((MethodCall methodCall) async { - called = true; - return imageList; - }); - - sut.call(fixture.hub, fixture.options); - - expect(fixture.options.eventProcessors.length, 1); - - await fixture.hub.captureException(StateError('error'), - stackTrace: StackTrace.current); - - expect(called, false); - }); - - test('Native layer is not called if the event has no stack traces', - () async { - var called = false; - - final sut = fixture.getSut(); - // ignore: deprecated_member_use - fixture.channel.setMockMethodCallHandler((MethodCall methodCall) async { - called = true; - return imageList; - }); - - sut.call(fixture.hub, fixture.options); - - await fixture.hub.captureException(StateError('error')); - - expect(called, false); - }); - - test('Native layer is called because stack traces are not symbolicated', - () async { - var called = false; - - final sut = fixture.getSut(); - // ignore: deprecated_member_use - fixture.channel.setMockMethodCallHandler((MethodCall methodCall) async { - called = true; - return imageList; - }); - - sut.call(fixture.hub, fixture.options); - - await fixture.hub.captureException(StateError('error'), stackTrace: ''' - warning: This VM has been configured to produce stack traces that violate the Dart standard. - *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** - pid: 30930, tid: 30990, name 1.ui - build_id: '5346e01103ffeed44e97094ff7bfcc19' - isolate_dso_base: 723d447000, vm_dso_base: 723d447000 - isolate_instructions: 723d452000, vm_instructions: 723d449000 - #00 abs 000000723d6346d7 virt 00000000001ed6d7 _kDartIsolateSnapshotInstructions+0x1e26d7 - #01 abs 000000723d637527 virt 00000000001f0527 _kDartIsolateSnapshotInstructions+0x1e5527 - '''); - - expect(called, true); - }); - - test('Event processor adds image list to the event', () async { - final sut = fixture.getSut(); - - sut.call(fixture.hub, fixture.options); - - final ep = fixture.options.eventProcessors.first; - SentryEvent? event = _getEvent(); - event = await ep.apply(event, Hint()); - - expect(1, event!.debugMeta!.images.length); - }); - - test('Event processor asserts image list', () async { - final sut = fixture.getSut(); - - sut.call(fixture.hub, fixture.options); - final ep = fixture.options.eventProcessors.first; - SentryEvent? event = _getEvent(); - event = await ep.apply(event, Hint()); - - final image = event!.debugMeta!.images.first; - - expect('/apex/com.android.art/javalib/arm64/boot.oat', image.codeFile); - expect('13577ce71153c228ecf0eb73fc39f45010d487f8', image.codeId); - expect('0x6f80b000', image.imageAddr); - expect(3092480, image.imageSize); - expect('elf', image.type); - expect('e77c5713-5311-28c2-ecf0-eb73fc39f450', image.debugId); - expect('test', image.debugFile); - }); - }); - } -} - -SentryEvent _getEvent() { - final frame = SentryStackFrame(platform: 'native'); - final st = SentryStackTrace(frames: [frame]); - final ex = SentryException( - type: 'type', - value: 'value', - stackTrace: st, - ); - return SentryEvent(exceptions: [ex]); -} - -class Fixture { - late final Hub hub; - late final SentryFlutterOptions options; - final channel = MethodChannel('sentry_flutter'); - - Fixture(MockPlatform platform) { - options = SentryFlutterOptions( - dsn: fakeDsn, checker: getPlatformChecker(platform: platform)); - hub = Hub(options); - } - - LoadImageListIntegration getSut() { - return LoadImageListIntegration(channel); - } -} diff --git a/flutter/test/mocks.dart b/flutter/test/mocks.dart index a373ee7511..4b7ff1aed5 100644 --- a/flutter/test/mocks.dart +++ b/flutter/test/mocks.dart @@ -10,7 +10,6 @@ import 'package:sentry/src/sentry_tracer.dart'; import 'package:meta/meta.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:sentry_flutter/src/renderer/renderer.dart'; -import 'package:sentry_flutter/src/native/sentry_native.dart'; import 'package:sentry_flutter/src/native/sentry_native_binding.dart'; import 'mocks.mocks.dart'; @@ -48,6 +47,7 @@ ISentrySpan startTransactionShim( SentryTransaction, SentrySpan, MethodChannel, + SentryNativeBinding ], customMocks: [ MockSpec(fallbackGenerators: {#startTransaction: startTransactionShim}) ]) @@ -162,271 +162,6 @@ class NoOpHub with NoSuchMethodProvider implements Hub { bool get isEnabled => false; } -// TODO can this be replaced with https://pub.dev/packages/mockito#verifying-exact-number-of-invocations--at-least-x--never -class TestMockSentryNative implements SentryNative { - @override - DateTime? appStartEnd; - - bool _didFetchAppStart = false; - - @override - bool get didFetchAppStart => _didFetchAppStart; - - @override - bool didAddAppStartMeasurement = false; - - Breadcrumb? breadcrumb; - var numberOfAddBreadcrumbCalls = 0; - var numberOfBeginNativeFramesCollectionCalls = 0; - var numberOfClearBreadcrumbsCalls = 0; - var numberOfEndNativeFramesCollectionCalls = 0; - var numberOfFetchNativeAppStartCalls = 0; - var removeContextsKey = ''; - var numberOfRemoveContextsCalls = 0; - var removeExtraKey = ''; - var numberOfRemoveExtraCalls = 0; - var removeTagKey = ''; - var numberOfRemoveTagCalls = 0; - var numberOfResetCalls = 0; - Map setContextData = {}; - var numberOfSetContextsCalls = 0; - Map setExtraData = {}; - var numberOfSetExtraCalls = 0; - Map setTagsData = {}; - var numberOfSetTagCalls = 0; - SentryUser? sentryUser; - var numberOfSetUserCalls = 0; - var numberOfStartProfilerCalls = 0; - var numberOfDiscardProfilerCalls = 0; - var numberOfCollectProfileCalls = 0; - var numberOfInitCalls = 0; - SentryFlutterOptions? initOptions; - var numberOfCloseCalls = 0; - - @override - Future addBreadcrumb(Breadcrumb breadcrumb) async { - this.breadcrumb = breadcrumb; - numberOfAddBreadcrumbCalls++; - } - - @override - Future beginNativeFramesCollection() async { - numberOfBeginNativeFramesCollectionCalls++; - } - - @override - Future clearBreadcrumbs() async { - numberOfClearBreadcrumbsCalls++; - } - - @override - Future endNativeFramesCollection(SentryId traceId) async { - numberOfEndNativeFramesCollectionCalls++; - return null; - } - - @override - Future fetchNativeAppStart() async { - _didFetchAppStart = true; - numberOfFetchNativeAppStartCalls++; - return null; - } - - @override - Future removeContexts(String key) async { - removeContextsKey = key; - numberOfRemoveContextsCalls++; - } - - @override - Future removeExtra(String key) async { - removeExtraKey = key; - numberOfRemoveExtraCalls++; - } - - @override - Future removeTag(String key) async { - removeTagKey = key; - numberOfRemoveTagCalls++; - } - - @override - void reset() { - numberOfResetCalls++; - } - - @override - Future setContexts(String key, value) async { - setContextData[key] = value; - numberOfSetContextsCalls++; - } - - @override - Future setExtra(String key, value) async { - setExtraData[key] = value; - numberOfSetExtraCalls++; - } - - @override - Future setTag(String key, String value) async { - setTagsData[key] = value; - numberOfSetTagCalls++; - } - - @override - Future setUser(SentryUser? sentryUser) async { - this.sentryUser = sentryUser; - numberOfSetUserCalls++; - } - - @override - Future?> collectProfile( - SentryId traceId, int startTimeNs, int endTimeNs) { - numberOfCollectProfileCalls++; - return Future.value(null); - } - - @override - int? startProfiler(SentryId traceId) { - numberOfStartProfilerCalls++; - return 42; - } - - @override - Future discardProfiler(SentryId traceId) { - numberOfDiscardProfilerCalls++; - return Future.value(null); - } - - @override - Future init(SentryFlutterOptions options) { - numberOfInitCalls++; - initOptions = options; - return Future.value(null); - } - - @override - Future close() { - numberOfCloseCalls++; - return Future.value(null); - } -} - -// TODO can this be replaced with https://pub.dev/packages/mockito#verifying-exact-number-of-invocations--at-least-x--never -class MockNativeChannel implements SentryNativeBinding { - NativeAppStart? nativeAppStart; - NativeFrames? nativeFrames; - SentryId? id; - - int numberOfBeginNativeFramesCalls = 0; - int numberOfEndNativeFramesCalls = 0; - int numberOfSetUserCalls = 0; - int numberOfAddBreadcrumbCalls = 0; - int numberOfClearBreadcrumbCalls = 0; - int numberOfRemoveContextsCalls = 0; - int numberOfRemoveExtraCalls = 0; - int numberOfRemoveTagCalls = 0; - int numberOfSetContextsCalls = 0; - int numberOfSetExtraCalls = 0; - int numberOfSetTagCalls = 0; - int numberOfStartProfilerCalls = 0; - int numberOfDiscardProfilerCalls = 0; - int numberOfCollectProfileCalls = 0; - int numberOfInitCalls = 0; - int numberOfCloseCalls = 0; - - @override - Future fetchNativeAppStart() async => nativeAppStart; - - @override - Future beginNativeFrames() async { - numberOfBeginNativeFramesCalls += 1; - } - - @override - Future endNativeFrames(SentryId id) async { - this.id = id; - numberOfEndNativeFramesCalls += 1; - return nativeFrames; - } - - @override - Future setUser(SentryUser? user) async { - numberOfSetUserCalls += 1; - } - - @override - Future addBreadcrumb(Breadcrumb breadcrumb) async { - numberOfAddBreadcrumbCalls += 1; - } - - @override - Future clearBreadcrumbs() async { - numberOfClearBreadcrumbCalls += 1; - } - - @override - Future removeContexts(String key) async { - numberOfRemoveContextsCalls += 1; - } - - @override - Future removeExtra(String key) async { - numberOfRemoveExtraCalls += 1; - } - - @override - Future removeTag(String key) async { - numberOfRemoveTagCalls += 1; - } - - @override - Future setContexts(String key, value) async { - numberOfSetContextsCalls += 1; - } - - @override - Future setExtra(String key, value) async { - numberOfSetExtraCalls += 1; - } - - @override - Future setTag(String key, value) async { - numberOfSetTagCalls += 1; - } - - @override - Future?> collectProfile( - SentryId traceId, int startTimeNs, int endTimeNs) { - numberOfCollectProfileCalls++; - return Future.value(null); - } - - @override - int? startProfiler(SentryId traceId) { - numberOfStartProfilerCalls++; - return null; - } - - @override - Future discardProfiler(SentryId traceId) { - numberOfDiscardProfilerCalls++; - return Future.value(null); - } - - @override - Future init(SentryFlutterOptions options) { - numberOfInitCalls++; - return Future.value(null); - } - - @override - Future close() { - numberOfCloseCalls++; - return Future.value(null); - } -} - class MockRendererWrapper implements RendererWrapper { MockRendererWrapper(this._renderer); diff --git a/flutter/test/mocks.mocks.dart b/flutter/test/mocks.mocks.dart index ee81d44430..bf6114a638 100644 --- a/flutter/test/mocks.mocks.dart +++ b/flutter/test/mocks.mocks.dart @@ -3,20 +3,27 @@ // Do not manually edit this file. // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:async' as _i7; +import 'dart:async' as _i8; +import 'dart:typed_data' as _i16; import 'package:flutter/src/services/binary_messenger.dart' as _i6; import 'package:flutter/src/services/message_codec.dart' as _i5; -import 'package:flutter/src/services/platform_channel.dart' as _i11; +import 'package:flutter/src/services/platform_channel.dart' as _i12; import 'package:mockito/mockito.dart' as _i1; -import 'package:mockito/src/dummies.dart' as _i9; +import 'package:mockito/src/dummies.dart' as _i10; import 'package:sentry/sentry.dart' as _i2; -import 'package:sentry/src/profiling.dart' as _i10; +import 'package:sentry/src/metrics/metric.dart' as _i19; +import 'package:sentry/src/metrics/metrics_api.dart' as _i7; +import 'package:sentry/src/profiling.dart' as _i11; import 'package:sentry/src/protocol.dart' as _i3; -import 'package:sentry/src/sentry_envelope.dart' as _i8; +import 'package:sentry/src/sentry_envelope.dart' as _i9; import 'package:sentry/src/sentry_tracer.dart' as _i4; +import 'package:sentry_flutter/sentry_flutter.dart' as _i14; +import 'package:sentry_flutter/src/native/native_app_start.dart' as _i15; +import 'package:sentry_flutter/src/native/native_frames.dart' as _i17; +import 'package:sentry_flutter/src/native/sentry_native_binding.dart' as _i13; -import 'mocks.dart' as _i12; +import 'mocks.dart' as _i18; // ignore_for_file: type=lint // ignore_for_file: avoid_redundant_argument_values @@ -145,8 +152,8 @@ class _FakeSentryOptions_10 extends _i1.SmartFake implements _i2.SentryOptions { ); } -class _FakeScope_11 extends _i1.SmartFake implements _i2.Scope { - _FakeScope_11( +class _FakeMetricsApi_11 extends _i1.SmartFake implements _i7.MetricsApi { + _FakeMetricsApi_11( Object parent, Invocation parentInvocation, ) : super( @@ -155,8 +162,18 @@ class _FakeScope_11 extends _i1.SmartFake implements _i2.Scope { ); } -class _FakeHub_12 extends _i1.SmartFake implements _i2.Hub { - _FakeHub_12( +class _FakeScope_12 extends _i1.SmartFake implements _i2.Scope { + _FakeScope_12( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeHub_13 extends _i1.SmartFake implements _i2.Hub { + _FakeHub_13( Object parent, Invocation parentInvocation, ) : super( @@ -174,14 +191,14 @@ class MockTransport extends _i1.Mock implements _i2.Transport { } @override - _i7.Future<_i3.SentryId?> send(_i8.SentryEnvelope? envelope) => + _i8.Future<_i3.SentryId?> send(_i9.SentryEnvelope? envelope) => (super.noSuchMethod( Invocation.method( #send, [envelope], ), - returnValue: _i7.Future<_i3.SentryId?>.value(), - ) as _i7.Future<_i3.SentryId?>); + returnValue: _i8.Future<_i3.SentryId?>.value(), + ) as _i8.Future<_i3.SentryId?>); } /// A class which mocks [SentryTracer]. @@ -195,7 +212,7 @@ class MockSentryTracer extends _i1.Mock implements _i4.SentryTracer { @override String get name => (super.noSuchMethod( Invocation.getter(#name), - returnValue: _i9.dummyValue( + returnValue: _i10.dummyValue( this, Invocation.getter(#name), ), @@ -229,7 +246,7 @@ class MockSentryTracer extends _i1.Mock implements _i4.SentryTracer { ); @override - set profiler(_i10.SentryProfiler? _profiler) => super.noSuchMethod( + set profiler(_i11.SentryProfiler? _profiler) => super.noSuchMethod( Invocation.setter( #profiler, _profiler, @@ -238,7 +255,7 @@ class MockSentryTracer extends _i1.Mock implements _i4.SentryTracer { ); @override - set profileInfo(_i10.SentryProfileInfo? _profileInfo) => super.noSuchMethod( + set profileInfo(_i11.SentryProfileInfo? _profileInfo) => super.noSuchMethod( Invocation.setter( #profileInfo, _profileInfo, @@ -322,7 +339,7 @@ class MockSentryTracer extends _i1.Mock implements _i4.SentryTracer { ) as Map); @override - _i7.Future finish({ + _i8.Future finish({ _i3.SpanStatus? status, DateTime? endTimestamp, }) => @@ -335,9 +352,9 @@ class MockSentryTracer extends _i1.Mock implements _i4.SentryTracer { #endTimestamp: endTimestamp, }, ), - returnValue: _i7.Future.value(), - returnValueForMissingStub: _i7.Future.value(), - ) as _i7.Future); + returnValue: _i8.Future.value(), + returnValueForMissingStub: _i8.Future.value(), + ) as _i8.Future); @override void removeData(String? key) => super.noSuchMethod( @@ -562,6 +579,16 @@ class MockSentryTransaction extends _i1.Mock implements _i3.SentryTransaction { returnValueForMissingStub: null, ); + @override + set metricSummaries(Map>? _metricSummaries) => + super.noSuchMethod( + Invocation.setter( + #metricSummaries, + _metricSummaries, + ), + returnValueForMissingStub: null, + ); + @override set transactionInfo(_i3.SentryTransactionInfo? _transactionInfo) => super.noSuchMethod( @@ -712,6 +739,7 @@ class MockSentryTransaction extends _i1.Mock implements _i3.SentryTransaction { #threads: threads, #type: type, #measurements: measurements, + #metricSummaries: metricSummaries, #transactionInfo: transactionInfo, }, ), @@ -791,7 +819,7 @@ class MockSentrySpan extends _i1.Mock implements _i3.SentrySpan { ) as Map); @override - _i7.Future finish({ + _i8.Future finish({ _i3.SpanStatus? status, DateTime? endTimestamp, }) => @@ -804,9 +832,9 @@ class MockSentrySpan extends _i1.Mock implements _i3.SentrySpan { #endTimestamp: endTimestamp, }, ), - returnValue: _i7.Future.value(), - returnValueForMissingStub: _i7.Future.value(), - ) as _i7.Future); + returnValue: _i8.Future.value(), + returnValueForMissingStub: _i8.Future.value(), + ) as _i8.Future); @override void removeData(String? key) => super.noSuchMethod( @@ -941,7 +969,7 @@ class MockSentrySpan extends _i1.Mock implements _i3.SentrySpan { /// A class which mocks [MethodChannel]. /// /// See the documentation for Mockito's code generation for more information. -class MockMethodChannel extends _i1.Mock implements _i11.MethodChannel { +class MockMethodChannel extends _i1.Mock implements _i12.MethodChannel { MockMethodChannel() { _i1.throwOnMissingStub(this); } @@ -949,7 +977,7 @@ class MockMethodChannel extends _i1.Mock implements _i11.MethodChannel { @override String get name => (super.noSuchMethod( Invocation.getter(#name), - returnValue: _i9.dummyValue( + returnValue: _i10.dummyValue( this, Invocation.getter(#name), ), @@ -974,7 +1002,7 @@ class MockMethodChannel extends _i1.Mock implements _i11.MethodChannel { ) as _i6.BinaryMessenger); @override - _i7.Future invokeMethod( + _i8.Future invokeMethod( String? method, [ dynamic arguments, ]) => @@ -986,11 +1014,11 @@ class MockMethodChannel extends _i1.Mock implements _i11.MethodChannel { arguments, ], ), - returnValue: _i7.Future.value(), - ) as _i7.Future); + returnValue: _i8.Future.value(), + ) as _i8.Future); @override - _i7.Future?> invokeListMethod( + _i8.Future?> invokeListMethod( String? method, [ dynamic arguments, ]) => @@ -1002,11 +1030,11 @@ class MockMethodChannel extends _i1.Mock implements _i11.MethodChannel { arguments, ], ), - returnValue: _i7.Future?>.value(), - ) as _i7.Future?>); + returnValue: _i8.Future?>.value(), + ) as _i8.Future?>); @override - _i7.Future?> invokeMapMethod( + _i8.Future?> invokeMapMethod( String? method, [ dynamic arguments, ]) => @@ -1018,12 +1046,12 @@ class MockMethodChannel extends _i1.Mock implements _i11.MethodChannel { arguments, ], ), - returnValue: _i7.Future?>.value(), - ) as _i7.Future?>); + returnValue: _i8.Future?>.value(), + ) as _i8.Future?>); @override void setMethodCallHandler( - _i7.Future Function(_i5.MethodCall)? handler) => + _i8.Future Function(_i5.MethodCall)? handler) => super.noSuchMethod( Invocation.method( #setMethodCallHandler, @@ -1033,6 +1061,243 @@ class MockMethodChannel extends _i1.Mock implements _i11.MethodChannel { ); } +/// A class which mocks [SentryNativeBinding]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockSentryNativeBinding extends _i1.Mock + implements _i13.SentryNativeBinding { + MockSentryNativeBinding() { + _i1.throwOnMissingStub(this); + } + + @override + _i8.Future init(_i14.SentryFlutterOptions? options) => + (super.noSuchMethod( + Invocation.method( + #init, + [options], + ), + returnValue: _i8.Future.value(), + returnValueForMissingStub: _i8.Future.value(), + ) as _i8.Future); + + @override + _i8.Future close() => (super.noSuchMethod( + Invocation.method( + #close, + [], + ), + returnValue: _i8.Future.value(), + returnValueForMissingStub: _i8.Future.value(), + ) as _i8.Future); + + @override + _i8.Future<_i15.NativeAppStart?> fetchNativeAppStart() => (super.noSuchMethod( + Invocation.method( + #fetchNativeAppStart, + [], + ), + returnValue: _i8.Future<_i15.NativeAppStart?>.value(), + ) as _i8.Future<_i15.NativeAppStart?>); + + @override + _i8.Future captureEnvelope(_i16.Uint8List? envelopeData) => + (super.noSuchMethod( + Invocation.method( + #captureEnvelope, + [envelopeData], + ), + returnValue: _i8.Future.value(), + returnValueForMissingStub: _i8.Future.value(), + ) as _i8.Future); + + @override + _i8.Future beginNativeFrames() => (super.noSuchMethod( + Invocation.method( + #beginNativeFrames, + [], + ), + returnValue: _i8.Future.value(), + returnValueForMissingStub: _i8.Future.value(), + ) as _i8.Future); + + @override + _i8.Future<_i17.NativeFrames?> endNativeFrames(_i3.SentryId? id) => + (super.noSuchMethod( + Invocation.method( + #endNativeFrames, + [id], + ), + returnValue: _i8.Future<_i17.NativeFrames?>.value(), + ) as _i8.Future<_i17.NativeFrames?>); + + @override + _i8.Future setUser(_i3.SentryUser? user) => (super.noSuchMethod( + Invocation.method( + #setUser, + [user], + ), + returnValue: _i8.Future.value(), + returnValueForMissingStub: _i8.Future.value(), + ) as _i8.Future); + + @override + _i8.Future addBreadcrumb(_i3.Breadcrumb? breadcrumb) => + (super.noSuchMethod( + Invocation.method( + #addBreadcrumb, + [breadcrumb], + ), + returnValue: _i8.Future.value(), + returnValueForMissingStub: _i8.Future.value(), + ) as _i8.Future); + + @override + _i8.Future clearBreadcrumbs() => (super.noSuchMethod( + Invocation.method( + #clearBreadcrumbs, + [], + ), + returnValue: _i8.Future.value(), + returnValueForMissingStub: _i8.Future.value(), + ) as _i8.Future); + + @override + _i8.Future?> loadContexts() => (super.noSuchMethod( + Invocation.method( + #loadContexts, + [], + ), + returnValue: _i8.Future?>.value(), + ) as _i8.Future?>); + + @override + _i8.Future setContexts( + String? key, + dynamic value, + ) => + (super.noSuchMethod( + Invocation.method( + #setContexts, + [ + key, + value, + ], + ), + returnValue: _i8.Future.value(), + returnValueForMissingStub: _i8.Future.value(), + ) as _i8.Future); + + @override + _i8.Future removeContexts(String? key) => (super.noSuchMethod( + Invocation.method( + #removeContexts, + [key], + ), + returnValue: _i8.Future.value(), + returnValueForMissingStub: _i8.Future.value(), + ) as _i8.Future); + + @override + _i8.Future setExtra( + String? key, + dynamic value, + ) => + (super.noSuchMethod( + Invocation.method( + #setExtra, + [ + key, + value, + ], + ), + returnValue: _i8.Future.value(), + returnValueForMissingStub: _i8.Future.value(), + ) as _i8.Future); + + @override + _i8.Future removeExtra(String? key) => (super.noSuchMethod( + Invocation.method( + #removeExtra, + [key], + ), + returnValue: _i8.Future.value(), + returnValueForMissingStub: _i8.Future.value(), + ) as _i8.Future); + + @override + _i8.Future setTag( + String? key, + String? value, + ) => + (super.noSuchMethod( + Invocation.method( + #setTag, + [ + key, + value, + ], + ), + returnValue: _i8.Future.value(), + returnValueForMissingStub: _i8.Future.value(), + ) as _i8.Future); + + @override + _i8.Future removeTag(String? key) => (super.noSuchMethod( + Invocation.method( + #removeTag, + [key], + ), + returnValue: _i8.Future.value(), + returnValueForMissingStub: _i8.Future.value(), + ) as _i8.Future); + + @override + int? startProfiler(_i3.SentryId? traceId) => + (super.noSuchMethod(Invocation.method( + #startProfiler, + [traceId], + )) as int?); + + @override + _i8.Future discardProfiler(_i3.SentryId? traceId) => + (super.noSuchMethod( + Invocation.method( + #discardProfiler, + [traceId], + ), + returnValue: _i8.Future.value(), + returnValueForMissingStub: _i8.Future.value(), + ) as _i8.Future); + + @override + _i8.Future?> collectProfile( + _i3.SentryId? traceId, + int? startTimeNs, + int? endTimeNs, + ) => + (super.noSuchMethod( + Invocation.method( + #collectProfile, + [ + traceId, + startTimeNs, + endTimeNs, + ], + ), + returnValue: _i8.Future?>.value(), + ) as _i8.Future?>); + + @override + _i8.Future?> loadDebugImages() => (super.noSuchMethod( + Invocation.method( + #loadDebugImages, + [], + ), + returnValue: _i8.Future?>.value(), + ) as _i8.Future?>); +} + /// A class which mocks [Hub]. /// /// See the documentation for Mockito's code generation for more information. @@ -1050,6 +1315,15 @@ class MockHub extends _i1.Mock implements _i2.Hub { ), ) as _i2.SentryOptions); + @override + _i7.MetricsApi get metricsApi => (super.noSuchMethod( + Invocation.getter(#metricsApi), + returnValue: _FakeMetricsApi_11( + this, + Invocation.getter(#metricsApi), + ), + ) as _i7.MetricsApi); + @override bool get isEnabled => (super.noSuchMethod( Invocation.getter(#isEnabled), @@ -1068,14 +1342,14 @@ class MockHub extends _i1.Mock implements _i2.Hub { @override _i2.Scope get scope => (super.noSuchMethod( Invocation.getter(#scope), - returnValue: _FakeScope_11( + returnValue: _FakeScope_12( this, Invocation.getter(#scope), ), ) as _i2.Scope); @override - set profilerFactory(_i10.SentryProfilerFactory? value) => super.noSuchMethod( + set profilerFactory(_i11.SentryProfilerFactory? value) => super.noSuchMethod( Invocation.setter( #profilerFactory, value, @@ -1084,7 +1358,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { ); @override - _i7.Future<_i3.SentryId> captureEvent( + _i8.Future<_i3.SentryId> captureEvent( _i3.SentryEvent? event, { dynamic stackTrace, _i2.Hint? hint, @@ -1100,7 +1374,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { #withScope: withScope, }, ), - returnValue: _i7.Future<_i3.SentryId>.value(_FakeSentryId_5( + returnValue: _i8.Future<_i3.SentryId>.value(_FakeSentryId_5( this, Invocation.method( #captureEvent, @@ -1112,10 +1386,10 @@ class MockHub extends _i1.Mock implements _i2.Hub { }, ), )), - ) as _i7.Future<_i3.SentryId>); + ) as _i8.Future<_i3.SentryId>); @override - _i7.Future<_i3.SentryId> captureException( + _i8.Future<_i3.SentryId> captureException( dynamic throwable, { dynamic stackTrace, _i2.Hint? hint, @@ -1131,7 +1405,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { #withScope: withScope, }, ), - returnValue: _i7.Future<_i3.SentryId>.value(_FakeSentryId_5( + returnValue: _i8.Future<_i3.SentryId>.value(_FakeSentryId_5( this, Invocation.method( #captureException, @@ -1143,10 +1417,10 @@ class MockHub extends _i1.Mock implements _i2.Hub { }, ), )), - ) as _i7.Future<_i3.SentryId>); + ) as _i8.Future<_i3.SentryId>); @override - _i7.Future<_i3.SentryId> captureMessage( + _i8.Future<_i3.SentryId> captureMessage( String? message, { _i3.SentryLevel? level, String? template, @@ -1166,7 +1440,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { #withScope: withScope, }, ), - returnValue: _i7.Future<_i3.SentryId>.value(_FakeSentryId_5( + returnValue: _i8.Future<_i3.SentryId>.value(_FakeSentryId_5( this, Invocation.method( #captureMessage, @@ -1180,21 +1454,21 @@ class MockHub extends _i1.Mock implements _i2.Hub { }, ), )), - ) as _i7.Future<_i3.SentryId>); + ) as _i8.Future<_i3.SentryId>); @override - _i7.Future captureUserFeedback(_i2.SentryUserFeedback? userFeedback) => + _i8.Future captureUserFeedback(_i2.SentryUserFeedback? userFeedback) => (super.noSuchMethod( Invocation.method( #captureUserFeedback, [userFeedback], ), - returnValue: _i7.Future.value(), - returnValueForMissingStub: _i7.Future.value(), - ) as _i7.Future); + returnValue: _i8.Future.value(), + returnValueForMissingStub: _i8.Future.value(), + ) as _i8.Future); @override - _i7.Future addBreadcrumb( + _i8.Future addBreadcrumb( _i3.Breadcrumb? crumb, { _i2.Hint? hint, }) => @@ -1204,9 +1478,9 @@ class MockHub extends _i1.Mock implements _i2.Hub { [crumb], {#hint: hint}, ), - returnValue: _i7.Future.value(), - returnValueForMissingStub: _i7.Future.value(), - ) as _i7.Future); + returnValue: _i8.Future.value(), + returnValueForMissingStub: _i8.Future.value(), + ) as _i8.Future); @override void bindClient(_i2.SentryClient? client) => super.noSuchMethod( @@ -1223,7 +1497,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { #clone, [], ), - returnValue: _FakeHub_12( + returnValue: _FakeHub_13( this, Invocation.method( #clone, @@ -1233,21 +1507,21 @@ class MockHub extends _i1.Mock implements _i2.Hub { ) as _i2.Hub); @override - _i7.Future close() => (super.noSuchMethod( + _i8.Future close() => (super.noSuchMethod( Invocation.method( #close, [], ), - returnValue: _i7.Future.value(), - returnValueForMissingStub: _i7.Future.value(), - ) as _i7.Future); + returnValue: _i8.Future.value(), + returnValueForMissingStub: _i8.Future.value(), + ) as _i8.Future); @override - _i7.FutureOr configureScope(_i2.ScopeCallback? callback) => + _i8.FutureOr configureScope(_i2.ScopeCallback? callback) => (super.noSuchMethod(Invocation.method( #configureScope, [callback], - )) as _i7.FutureOr); + )) as _i8.FutureOr); @override _i2.ISentrySpan startTransaction( @@ -1280,7 +1554,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { #customSamplingContext: customSamplingContext, }, ), - returnValue: _i12.startTransactionShim( + returnValue: _i18.startTransactionShim( name, operation, description: description, @@ -1338,7 +1612,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { ) as _i2.ISentrySpan); @override - _i7.Future<_i3.SentryId> captureTransaction( + _i8.Future<_i3.SentryId> captureTransaction( _i3.SentryTransaction? transaction, { _i2.SentryTraceContextHeader? traceContext, }) => @@ -1348,7 +1622,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { [transaction], {#traceContext: traceContext}, ), - returnValue: _i7.Future<_i3.SentryId>.value(_FakeSentryId_5( + returnValue: _i8.Future<_i3.SentryId>.value(_FakeSentryId_5( this, Invocation.method( #captureTransaction, @@ -1356,7 +1630,24 @@ class MockHub extends _i1.Mock implements _i2.Hub { {#traceContext: traceContext}, ), )), - ) as _i7.Future<_i3.SentryId>); + ) as _i8.Future<_i3.SentryId>); + + @override + _i8.Future<_i3.SentryId> captureMetrics( + Map>? metricsBuckets) => + (super.noSuchMethod( + Invocation.method( + #captureMetrics, + [metricsBuckets], + ), + returnValue: _i8.Future<_i3.SentryId>.value(_FakeSentryId_5( + this, + Invocation.method( + #captureMetrics, + [metricsBuckets], + ), + )), + ) as _i8.Future<_i3.SentryId>); @override void setSpanContext( diff --git a/flutter/test/native_scope_observer_test.dart b/flutter/test/native_scope_observer_test.dart index 980449b11f..9d7a8fd2a9 100644 --- a/flutter/test/native_scope_observer_test.dart +++ b/flutter/test/native_scope_observer_test.dart @@ -2,98 +2,75 @@ library flutter_test; import 'package:flutter_test/flutter_test.dart'; +import 'package:mockito/mockito.dart'; import 'package:sentry/sentry.dart'; import 'package:sentry_flutter/src/native/native_scope_observer.dart'; -import 'mocks.dart'; +import 'mocks.mocks.dart'; void main() { - late Fixture fixture; + late MockSentryNativeBinding mock; + late NativeScopeObserver sut; setUp(() { - fixture = Fixture(); + mock = MockSentryNativeBinding(); + sut = NativeScopeObserver(mock); }); test('addBreadcrumbCalls', () async { - final sut = fixture.getSut(); final breadcrumb = Breadcrumb(); await sut.addBreadcrumb(breadcrumb); - expect(fixture.mock.breadcrumb, breadcrumb); - expect(fixture.mock.numberOfAddBreadcrumbCalls, 1); + expect(verify(mock.addBreadcrumb(captureAny)).captured.single, breadcrumb); }); test('clearBreadcrumbsCalls', () async { - final sut = fixture.getSut(); await sut.clearBreadcrumbs(); - expect(fixture.mock.numberOfClearBreadcrumbsCalls, 1); + verify(mock.clearBreadcrumbs()).called(1); }); test('removeContextsCalls', () async { - final sut = fixture.getSut(); await sut.removeContexts('fixture-key'); - expect(fixture.mock.removeContextsKey, 'fixture-key'); - expect(fixture.mock.numberOfRemoveContextsCalls, 1); + expect( + verify(mock.removeContexts(captureAny)).captured.single, 'fixture-key'); }); test('removeExtraCalls', () async { - final sut = fixture.getSut(); await sut.removeExtra('fixture-key'); - expect(fixture.mock.removeExtraKey, 'fixture-key'); - expect(fixture.mock.numberOfRemoveExtraCalls, 1); + expect(verify(mock.removeExtra(captureAny)).captured.single, 'fixture-key'); }); test('removeTagCalls', () async { - final sut = fixture.getSut(); await sut.removeTag('fixture-key'); - expect(fixture.mock.removeTagKey, 'fixture-key'); - expect(fixture.mock.numberOfRemoveTagCalls, 1); + expect(verify(mock.removeTag(captureAny)).captured.single, 'fixture-key'); }); test('setContextsCalls', () async { - final sut = fixture.getSut(); await sut.setContexts('fixture-key', 'fixture-value'); - expect(fixture.mock.setContextData['fixture-key'], 'fixture-value'); - expect(fixture.mock.numberOfSetContextsCalls, 1); + verify(mock.setContexts('fixture-key', 'fixture-value')).called(1); }); test('setExtraCalls', () async { - final sut = fixture.getSut(); await sut.setExtra('fixture-key', 'fixture-value'); - expect(fixture.mock.setExtraData['fixture-key'], 'fixture-value'); - expect(fixture.mock.numberOfSetExtraCalls, 1); + verify(mock.setExtra('fixture-key', 'fixture-value')).called(1); }); test('setTagCalls', () async { - final sut = fixture.getSut(); await sut.setTag('fixture-key', 'fixture-value'); - expect(fixture.mock.setTagsData['fixture-key'], 'fixture-value'); - expect(fixture.mock.numberOfSetTagCalls, 1); + verify(mock.setTag('fixture-key', 'fixture-value')).called(1); }); test('setUserCalls', () async { - final sut = fixture.getSut(); - final user = SentryUser(id: 'foo bar'); await sut.setUser(user); - expect(fixture.mock.sentryUser, user); - expect(fixture.mock.numberOfSetUserCalls, 1); + expect(verify(mock.setUser(captureAny)).captured.single, user); }); } - -class Fixture { - var mock = TestMockSentryNative(); - - NativeScopeObserver getSut() { - final sut = NativeScopeObserver(mock); - return sut; - } -} diff --git a/flutter/test/navigation/sentry_display_widget_test.dart b/flutter/test/navigation/sentry_display_widget_test.dart index 2cafb706d5..a0495bfe8d 100644 --- a/flutter/test/navigation/sentry_display_widget_test.dart +++ b/flutter/test/navigation/sentry_display_widget_test.dart @@ -108,7 +108,6 @@ class Fixture { final fakeFrameCallbackHandler = FakeFrameCallbackHandler(); Fixture() { - SentryFlutter.native = TestMockSentryNative(); navigatorObserver = SentryNavigatorObserver(hub: hub); } diff --git a/flutter/test/navigation/time_to_display_tracker_test.dart b/flutter/test/navigation/time_to_display_tracker_test.dart index ca9d0425a0..975adb37fd 100644 --- a/flutter/test/navigation/time_to_display_tracker_test.dart +++ b/flutter/test/navigation/time_to_display_tracker_test.dart @@ -52,7 +52,6 @@ void main() { }); test('finishes ttid span', () async { - SentryFlutter.native = TestMockSentryNative(); final sut = fixture.getSut(); final endTimestamp = fixture.startTimestamp.add(const Duration(milliseconds: 10)); @@ -228,7 +227,6 @@ void main() { test('does not create ttfd span when not enabled', () async { fixture.options.enableTimeToFullDisplayTracing = false; - SentryFlutter.native = TestMockSentryNative(); final sut = fixture.getSut(); final transaction = fixture.getTransaction() as SentryTracer; diff --git a/flutter/test/profiling_test.dart b/flutter/test/profiling_test.dart index adf88e0f2e..04ff70d065 100644 --- a/flutter/test/profiling_test.dart +++ b/flutter/test/profiling_test.dart @@ -10,6 +10,13 @@ import 'mocks.mocks.dart'; import 'sentry_flutter_test.dart'; void main() { + late MockSentryNativeBinding mock; + + setUp(() { + mock = MockSentryNativeBinding(); + when(mock.startProfiler(any)).thenReturn(1); + }); + group('$SentryNativeProfilerFactory', () { Hub hubWithSampleRate(double profilesSampleRate) { final o = SentryFlutterOptions(dsn: fakeDsn); @@ -23,42 +30,39 @@ void main() { test('attachTo() respects sampling rate', () async { var hub = hubWithSampleRate(0.0); - SentryNativeProfilerFactory.attachTo(hub, TestMockSentryNative()); + SentryNativeProfilerFactory.attachTo(hub, mock); // ignore: invalid_use_of_internal_member verifyNever(hub.profilerFactory = any); hub = hubWithSampleRate(0.1); - SentryNativeProfilerFactory.attachTo(hub, TestMockSentryNative()); + SentryNativeProfilerFactory.attachTo(hub, mock); // ignore: invalid_use_of_internal_member verify(hub.profilerFactory = any); }); test('creates a profiler', () async { - final nativeMock = TestMockSentryNative(); // ignore: invalid_use_of_internal_member - final sut = SentryNativeProfilerFactory(nativeMock, getUtcDateTime); + final sut = SentryNativeProfilerFactory(mock, getUtcDateTime); final profiler = sut.startProfiler(SentryTransactionContext( 'name', 'op', )); - expect(nativeMock.numberOfStartProfilerCalls, 1); + verify(mock.startProfiler(any)).called(1); expect(profiler, isNotNull); }); }); group('$SentryNativeProfiler', () { - late TestMockSentryNative nativeMock; late SentryNativeProfiler sut; setUp(() { - nativeMock = TestMockSentryNative(); // ignore: invalid_use_of_internal_member - final factory = SentryNativeProfilerFactory(nativeMock, getUtcDateTime); + final factory = SentryNativeProfilerFactory(mock, getUtcDateTime); final profiler = factory.startProfiler(SentryTransactionContext( 'name', 'op', )); - expect(nativeMock.numberOfStartProfilerCalls, 1); + verify(mock.startProfiler(any)).called(1); expect(profiler, isNotNull); sut = profiler!; }); @@ -71,14 +75,15 @@ void main() { await null; await null; - expect(nativeMock.numberOfDiscardProfilerCalls, 1); + verify(mock.discardProfiler(any)).called(1); // finishFor() mustn't work after disposing expect(await sut.finishFor(MockSentryTransaction()), isNull); - expect(nativeMock.numberOfCollectProfileCalls, 0); + verifyNever(mock.collectProfile(any, any, any)); }); test('dispose() does not call discard() after finishing', () async { + when(mock.collectProfile(any, any, any)).thenAnswer((_) async => null); final mockTransaction = MockSentryTransaction(); when(mockTransaction.startTimestamp).thenReturn(DateTime.now()); when(mockTransaction.timestamp).thenReturn(DateTime.now()); @@ -89,8 +94,8 @@ void main() { // Yield to let the .then() in .dispose() execute. await null; - expect(nativeMock.numberOfDiscardProfilerCalls, 0); - expect(nativeMock.numberOfCollectProfileCalls, 1); + verifyNever(mock.discardProfiler(any)); + verify(mock.collectProfile(any, any, any)).called(1); }); }); } diff --git a/flutter/test/sentry_flutter_test.dart b/flutter/test/sentry_flutter_test.dart index e06938da90..0c9590dc92 100644 --- a/flutter/test/sentry_flutter_test.dart +++ b/flutter/test/sentry_flutter_test.dart @@ -2,6 +2,7 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:package_info_plus/package_info_plus.dart'; +import 'package:sentry/src/platform/platform.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:sentry_flutter/src/integrations/connectivity/connectivity_integration.dart'; import 'package:sentry_flutter/src/integrations/integrations.dart'; @@ -639,7 +640,7 @@ void loadTestPackage() { } PlatformChecker getPlatformChecker({ - required MockPlatform platform, + required Platform platform, bool isWeb = false, }) { final platformChecker = PlatformChecker( diff --git a/flutter/test/sentry_native_channel_test.dart b/flutter/test/sentry_native_channel_test.dart index 050693cc8a..6a10400d3c 100644 --- a/flutter/test/sentry_native_channel_test.dart +++ b/flutter/test/sentry_native_channel_test.dart @@ -3,242 +3,287 @@ @TestOn('vm') library flutter_test; +import 'dart:typed_data'; + import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/mockito.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; +import 'package:sentry_flutter/src/native/factory.dart'; import 'package:sentry_flutter/src/native/method_channel_helper.dart'; -import 'package:sentry_flutter/src/native/sentry_native.dart'; -import 'package:sentry_flutter/src/native/sentry_native_channel.dart'; +import 'package:sentry_flutter/src/native/sentry_native_binding.dart'; +import 'package:sentry/src/platform/platform.dart' as platform; +import 'mocks.dart'; import 'mocks.mocks.dart'; +import 'sentry_flutter_test.dart'; void main() { - group('$SentryNative', () { - late Fixture fixture; - - setUp(() { - fixture = Fixture(); - }); - - test('fetchNativeAppStart', () async { - final map = { - 'pluginRegistrationTime': 1, - 'appStartTime': 0.1, - 'isColdStart': true, - // ignore: inference_failure_on_collection_literal - 'nativeSpanTimes': {}, - }; - final future = Future.value(map); - - when(fixture.methodChannel - .invokeMapMethod('fetchNativeAppStart')) - .thenAnswer((_) => future); - - final sut = fixture.getSut(); - final actual = await sut.fetchNativeAppStart(); - - expect(actual?.appStartTime, 0.1); - expect(actual?.isColdStart, true); - }); - - test('beginNativeFrames', () async { - final sut = fixture.getSut(); - when(fixture.methodChannel.invokeMethod('beginNativeFrames')) - .thenAnswer((realInvocation) async {}); - await sut.beginNativeFrames(); - - verify(fixture.methodChannel.invokeMethod('beginNativeFrames')); - }); - - test('endNativeFrames', () async { - final sentryId = SentryId.empty(); - final map = { - 'totalFrames': 3, - 'slowFrames': 2, - 'frozenFrames': 1 - }; - final future = Future.value(map); - - when(fixture.methodChannel.invokeMapMethod( - 'endNativeFrames', {'id': sentryId.toString()})) - .thenAnswer((_) => future); - - final sut = fixture.getSut(); - final actual = await sut.endNativeFrames(sentryId); - - expect(actual?.totalFrames, 3); - expect(actual?.slowFrames, 2); - expect(actual?.frozenFrames, 1); - }); - - test('setUser', () async { - final user = SentryUser( - id: "fixture-id", - data: {'object': Object()}, - ); - final normalizedUser = user.copyWith( - data: MethodChannelHelper.normalizeMap(user.data), - ); - when(fixture.methodChannel - .invokeMethod('setUser', {'user': normalizedUser.toJson()})) - .thenAnswer((_) => Future.value()); - - final sut = fixture.getSut(); - await sut.setUser(user); - - verify(fixture.methodChannel - .invokeMethod('setUser', {'user': normalizedUser.toJson()})); - }); - - test('addBreadcrumb', () async { - final breadcrumb = Breadcrumb( - data: {'object': Object()}, - ); - final normalizedBreadcrumb = breadcrumb.copyWith( - data: MethodChannelHelper.normalizeMap(breadcrumb.data)); - - when(fixture.methodChannel.invokeMethod( - 'addBreadcrumb', {'breadcrumb': normalizedBreadcrumb.toJson()})) - .thenAnswer((_) => Future.value()); - - final sut = fixture.getSut(); - await sut.addBreadcrumb(breadcrumb); - - verify(fixture.methodChannel.invokeMethod( - 'addBreadcrumb', {'breadcrumb': normalizedBreadcrumb.toJson()})); - }); - - test('clearBreadcrumbs', () async { - when(fixture.methodChannel.invokeMethod('clearBreadcrumbs')) - .thenAnswer((_) => Future.value()); - - final sut = fixture.getSut(); - await sut.clearBreadcrumbs(); - - verify(fixture.methodChannel.invokeMethod('clearBreadcrumbs')); - }); - - test('setContexts', () async { - final value = {'object': Object()}; - final normalizedValue = MethodChannelHelper.normalize(value); - when(fixture.methodChannel.invokeMethod( - 'setContexts', {'key': 'fixture-key', 'value': normalizedValue})) - .thenAnswer((_) => Future.value()); - - final sut = fixture.getSut(); - await sut.setContexts('fixture-key', value); - - verify(fixture.methodChannel.invokeMethod( - 'setContexts', {'key': 'fixture-key', 'value': normalizedValue})); - }); - - test('removeContexts', () async { - when(fixture.methodChannel - .invokeMethod('removeContexts', {'key': 'fixture-key'})) - .thenAnswer((_) => Future.value()); - - final sut = fixture.getSut(); - await sut.removeContexts('fixture-key'); - - verify(fixture.methodChannel - .invokeMethod('removeContexts', {'key': 'fixture-key'})); + for (var mockPlatform in [ + MockPlatform.android(), + MockPlatform.iOs(), + MockPlatform.macOs() + ]) { + group('$SentryNativeBinding', () { + late SentryNativeBinding sut; + late MockMethodChannel channel; + + setUp(() { + final options = SentryFlutterOptions( + dsn: fakeDsn, checker: getPlatformChecker(platform: mockPlatform)) + // ignore: invalid_use_of_internal_member + ..automatedTestMode = true; + channel = MockMethodChannel(); + sut = createBinding(options, channel: channel); + }); + + // TODO move other methods here, e.g. init_native_sdk_test.dart + + test('fetchNativeAppStart', () async { + when(channel.invokeMethod('fetchNativeAppStart')) + .thenAnswer((_) async => { + 'pluginRegistrationTime': 1, + 'appStartTime': 0.1, + 'isColdStart': true, + // ignore: inference_failure_on_collection_literal + 'nativeSpanTimes': {}, + }); + + final actual = await sut.fetchNativeAppStart(); + + expect(actual?.appStartTime, 0.1); + expect(actual?.isColdStart, true); + }); + + test('beginNativeFrames', () async { + when(channel.invokeMethod('beginNativeFrames')) + .thenAnswer((realInvocation) async {}); + await sut.beginNativeFrames(); + + verify(channel.invokeMethod('beginNativeFrames')); + }); + + test('endNativeFrames', () async { + final sentryId = SentryId.empty(); + + when(channel + .invokeMethod('endNativeFrames', {'id': sentryId.toString()})) + .thenAnswer((_) async => { + 'totalFrames': 3, + 'slowFrames': 2, + 'frozenFrames': 1, + }); + + final actual = await sut.endNativeFrames(sentryId); + + expect(actual?.totalFrames, 3); + expect(actual?.slowFrames, 2); + expect(actual?.frozenFrames, 1); + }); + + test('setUser', () async { + final user = SentryUser( + id: "fixture-id", + data: {'object': Object()}, + ); + final normalizedUser = user.copyWith( + data: MethodChannelHelper.normalizeMap(user.data), + ); + when(channel.invokeMethod('setUser', {'user': normalizedUser.toJson()})) + .thenAnswer((_) => Future.value()); + + await sut.setUser(user); + + verify( + channel.invokeMethod('setUser', {'user': normalizedUser.toJson()})); + }); + + test('addBreadcrumb', () async { + final breadcrumb = Breadcrumb( + data: {'object': Object()}, + ); + final normalizedBreadcrumb = breadcrumb.copyWith( + data: MethodChannelHelper.normalizeMap(breadcrumb.data)); + + when(channel.invokeMethod( + 'addBreadcrumb', {'breadcrumb': normalizedBreadcrumb.toJson()})) + .thenAnswer((_) => Future.value()); + + await sut.addBreadcrumb(breadcrumb); + + verify(channel.invokeMethod( + 'addBreadcrumb', {'breadcrumb': normalizedBreadcrumb.toJson()})); + }); + + test('clearBreadcrumbs', () async { + when(channel.invokeMethod('clearBreadcrumbs')) + .thenAnswer((_) => Future.value()); + + await sut.clearBreadcrumbs(); + + verify(channel.invokeMethod('clearBreadcrumbs')); + }); + + test('setContexts', () async { + final value = {'object': Object()}; + final normalizedValue = MethodChannelHelper.normalize(value); + when(channel.invokeMethod('setContexts', { + 'key': 'fixture-key', + 'value': normalizedValue + })).thenAnswer((_) => Future.value()); + + await sut.setContexts('fixture-key', value); + + verify(channel.invokeMethod( + 'setContexts', {'key': 'fixture-key', 'value': normalizedValue})); + }); + + test('removeContexts', () async { + when(channel.invokeMethod('removeContexts', {'key': 'fixture-key'})) + .thenAnswer((_) => Future.value()); + + await sut.removeContexts('fixture-key'); + + verify(channel.invokeMethod('removeContexts', {'key': 'fixture-key'})); + }); + + test('setExtra', () async { + final value = {'object': Object()}; + final normalizedValue = MethodChannelHelper.normalize(value); + when(channel.invokeMethod( + 'setExtra', {'key': 'fixture-key', 'value': normalizedValue})) + .thenAnswer((_) => Future.value()); + + await sut.setExtra('fixture-key', value); + + verify(channel.invokeMethod( + 'setExtra', {'key': 'fixture-key', 'value': normalizedValue})); + }); + + test('removeExtra', () async { + when(channel.invokeMethod('removeExtra', {'key': 'fixture-key'})) + .thenAnswer((_) => Future.value()); + + await sut.removeExtra('fixture-key'); + + verify(channel.invokeMethod('removeExtra', {'key': 'fixture-key'})); + }); + + test('setTag', () async { + when(channel.invokeMethod( + 'setTag', {'key': 'fixture-key', 'value': 'fixture-value'})) + .thenAnswer((_) => Future.value()); + + await sut.setTag('fixture-key', 'fixture-value'); + + verify(channel.invokeMethod( + 'setTag', {'key': 'fixture-key', 'value': 'fixture-value'})); + }); + + test('removeTag', () async { + when(channel.invokeMethod('removeTag', {'key': 'fixture-key'})) + .thenAnswer((_) => Future.value()); + + await sut.removeTag('fixture-key'); + + verify(channel.invokeMethod('removeTag', {'key': 'fixture-key'})); + }); + + test('startProfiler', () { + late Matcher matcher; + if (mockPlatform.isAndroid) { + matcher = throwsUnsupportedError; + } else if (mockPlatform.isIOS || mockPlatform.isMacOS) { + if (platform.instance.isMacOS) { + matcher = throwsA(predicate((e) => + e is Exception && + e.toString().contains('Failed to load Objective-C class'))); + } else { + matcher = throwsA(predicate((e) => + e is ArgumentError && + e.toString().contains('Failed to lookup symbol'))); + } + } + expect(() => sut.startProfiler(SentryId.newId()), matcher); + + verifyZeroInteractions(channel); + }); + + test('discardProfiler', () async { + final traceId = SentryId.newId(); + when(channel.invokeMethod('discardProfiler', traceId.toString())) + .thenAnswer((_) async {}); + + await sut.discardProfiler(traceId); + + verify(channel.invokeMethod('discardProfiler', traceId.toString())); + }); + + test('collectProfile', () async { + final traceId = SentryId.newId(); + const startTime = 42; + const endTime = 50; + when(channel.invokeMethod('collectProfile', { + 'traceId': traceId.toString(), + 'startTime': startTime, + 'endTime': endTime, + })).thenAnswer((_) async => {}); + + await sut.collectProfile(traceId, startTime, endTime); + + verify(channel.invokeMethod('collectProfile', { + 'traceId': traceId.toString(), + 'startTime': startTime, + 'endTime': endTime, + })); + }); + + test('captureEnvelope', () async { + final data = Uint8List.fromList([1, 2, 3]); + + late Uint8List captured; + when(channel.invokeMethod('captureEnvelope', any)).thenAnswer( + (invocation) async => + {captured = invocation.positionalArguments[1][0] as Uint8List}); + + await sut.captureEnvelope(data); + + expect(captured, data); + }); + + test('loadContexts', () async { + when(channel.invokeMethod('loadContexts')) + .thenAnswer((invocation) async => { + 'foo': [1, 2, 3], + 'bar': {'a': 'b'}, + }); + + final data = await sut.loadContexts(); + + expect(data, { + 'foo': [1, 2, 3], + 'bar': {'a': 'b'}, + }); + }); + + test('loadDebugImages', () async { + final json = [ + { + 'code_file': '/apex/com.android.art/javalib/arm64/boot.oat', + 'code_id': '13577ce71153c228ecf0eb73fc39f45010d487f8', + 'image_addr': '0x6f80b000', + 'image_size': 3092480, + 'type': 'elf', + 'debug_id': 'e77c5713-5311-28c2-ecf0-eb73fc39f450', + 'debug_file': 'test' + } + ]; + + when(channel.invokeMethod('loadImageList')) + .thenAnswer((invocation) async => json); + + final data = await sut.loadDebugImages(); + + expect(data?.map((v) => v.toJson()), json); + }); }); - - test('setExtra', () async { - final value = {'object': Object()}; - final normalizedValue = MethodChannelHelper.normalize(value); - when(fixture.methodChannel.invokeMethod( - 'setExtra', {'key': 'fixture-key', 'value': normalizedValue})) - .thenAnswer((_) => Future.value()); - - final sut = fixture.getSut(); - await sut.setExtra('fixture-key', value); - - verify(fixture.methodChannel.invokeMethod( - 'setExtra', {'key': 'fixture-key', 'value': normalizedValue})); - }); - - test('removeExtra', () async { - when(fixture.methodChannel - .invokeMethod('removeExtra', {'key': 'fixture-key'})) - .thenAnswer((_) => Future.value()); - - final sut = fixture.getSut(); - await sut.removeExtra('fixture-key'); - - verify(fixture.methodChannel - .invokeMethod('removeExtra', {'key': 'fixture-key'})); - }); - - test('setTag', () async { - when(fixture.methodChannel.invokeMethod( - 'setTag', {'key': 'fixture-key', 'value': 'fixture-value'})) - .thenAnswer((_) => Future.value()); - - final sut = fixture.getSut(); - await sut.setTag('fixture-key', 'fixture-value'); - - verify(fixture.methodChannel.invokeMethod( - 'setTag', {'key': 'fixture-key', 'value': 'fixture-value'})); - }); - - test('removeTag', () async { - when(fixture.methodChannel - .invokeMethod('removeTag', {'key': 'fixture-key'})) - .thenAnswer((_) => Future.value()); - - final sut = fixture.getSut(); - await sut.removeTag('fixture-key'); - - verify(fixture.methodChannel - .invokeMethod('removeTag', {'key': 'fixture-key'})); - }); - - test('startProfiler', () { - final sut = fixture.getSut(); - expect(() => sut.startProfiler(SentryId.newId()), throwsUnsupportedError); - verifyZeroInteractions(fixture.methodChannel); - }); - - test('discardProfiler', () async { - final traceId = SentryId.newId(); - when(fixture.methodChannel - .invokeMethod('discardProfiler', traceId.toString())) - .thenAnswer((_) async {}); - - final sut = fixture.getSut(); - await sut.discardProfiler(traceId); - - verify(fixture.methodChannel - .invokeMethod('discardProfiler', traceId.toString())); - }); - - test('collectProfile', () async { - final traceId = SentryId.newId(); - const startTime = 42; - const endTime = 50; - when(fixture.methodChannel - .invokeMapMethod('collectProfile', { - 'traceId': traceId.toString(), - 'startTime': startTime, - 'endTime': endTime, - })).thenAnswer((_) => Future.value()); - - final sut = fixture.getSut(); - await sut.collectProfile(traceId, startTime, endTime); - - verify(fixture.methodChannel.invokeMapMethod('collectProfile', { - 'traceId': traceId.toString(), - 'startTime': startTime, - 'endTime': endTime, - })); - }); - }); -} - -class Fixture { - final methodChannel = MockMethodChannel(); - - SentryNativeChannel getSut() { - return SentryNativeChannel(methodChannel); } } diff --git a/flutter/test/sentry_native_test.dart b/flutter/test/sentry_native_test.dart deleted file mode 100644 index 8d30312f6f..0000000000 --- a/flutter/test/sentry_native_test.dart +++ /dev/null @@ -1,120 +0,0 @@ -@TestOn('vm') -library flutter_test; - -import 'package:flutter_test/flutter_test.dart'; -import 'package:sentry_flutter/sentry_flutter.dart'; -import 'package:sentry_flutter/src/native/sentry_native.dart'; -import 'mocks.dart'; - -void main() { - group('$SentryNative', () { - final channel = MockNativeChannel(); - final options = SentryFlutterOptions(dsn: fakeDsn); - late final sut = SentryNative(options, channel); - - tearDown(() { - sut.reset(); - }); - - test('fetchNativeAppStart sets didFetchAppStart', () async { - final nativeAppStart = NativeAppStart( - appStartTime: 0.0, - pluginRegistrationTime: 10, - isColdStart: true, - nativeSpanTimes: {}); - channel.nativeAppStart = nativeAppStart; - - expect(sut.didFetchAppStart, false); - - final firstCall = await sut.fetchNativeAppStart(); - expect(firstCall, nativeAppStart); - - expect(sut.didFetchAppStart, true); - }); - - test('beginNativeFramesCollection', () async { - await sut.beginNativeFramesCollection(); - expect(channel.numberOfBeginNativeFramesCalls, 1); - }); - - test('endNativeFramesCollection', () async { - final nativeFrames = NativeFrames(3, 2, 1); - final traceId = SentryId.empty(); - channel.nativeFrames = nativeFrames; - - final actual = await sut.endNativeFramesCollection(traceId); - - expect(actual, nativeFrames); - expect(channel.id, traceId); - expect(channel.numberOfEndNativeFramesCalls, 1); - }); - - test('setUser', () async { - await sut.setUser(null); - expect(channel.numberOfSetUserCalls, 1); - }); - - test('addBreadcrumb', () async { - await sut.addBreadcrumb(Breadcrumb()); - expect(channel.numberOfAddBreadcrumbCalls, 1); - }); - - test('clearBreadcrumbs', () async { - await sut.clearBreadcrumbs(); - expect(channel.numberOfClearBreadcrumbCalls, 1); - }); - - test('setContexts', () async { - await sut.setContexts('fixture-key', 'fixture-value'); - expect(channel.numberOfSetContextsCalls, 1); - }); - - test('removeContexts', () async { - await sut.removeContexts('fixture-key'); - expect(channel.numberOfRemoveContextsCalls, 1); - }); - - test('setExtra', () async { - await sut.setExtra('fixture-key', 'fixture-value'); - expect(channel.numberOfSetExtraCalls, 1); - }); - - test('removeExtra', () async { - await sut.removeExtra('fixture-key'); - expect(channel.numberOfRemoveExtraCalls, 1); - }); - - test('setTag', () async { - await sut.setTag('fixture-key', 'fixture-value'); - expect(channel.numberOfSetTagCalls, 1); - }); - - test('removeTag', () async { - await sut.removeTag('fixture-key'); - expect(channel.numberOfRemoveTagCalls, 1); - }); - - test('startProfiler', () async { - sut.startProfiler(SentryId.newId()); - expect(channel.numberOfStartProfilerCalls, 1); - }); - - test('discardProfiler', () async { - await sut.discardProfiler(SentryId.newId()); - expect(channel.numberOfDiscardProfilerCalls, 1); - }); - - test('collectProfile', () async { - await sut.collectProfile(SentryId.newId(), 1, 2); - expect(channel.numberOfCollectProfileCalls, 1); - }); - - test('reset', () async { - sut.appStartEnd = DateTime.now(); - await sut.fetchNativeAppStart(); - sut.reset(); - expect(sut.appStartEnd, null); - expect(sut.didFetchAppStart, false); - }); - }); -} diff --git a/flutter/test/sentry_navigator_observer_test.dart b/flutter/test/sentry_navigator_observer_test.dart index e2b1488cca..bc9971cb9c 100644 --- a/flutter/test/sentry_navigator_observer_test.dart +++ b/flutter/test/sentry_navigator_observer_test.dart @@ -8,8 +8,8 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/mockito.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:sentry_flutter/src/integrations/integrations.dart'; -import 'package:sentry_flutter/src/native/sentry_native.dart'; import 'package:sentry/src/sentry_tracer.dart'; +import 'package:sentry_flutter/src/native/native_frames.dart'; import 'package:sentry_flutter/src/navigation/time_to_display_tracker.dart'; import 'package:sentry_flutter/src/navigation/time_to_initial_display_tracker.dart'; @@ -41,16 +41,14 @@ void main() { setUp(() { fixture = Fixture(); - WidgetsFlutterBinding.ensureInitialized(); }); group('NativeFrames', () { - late MockNativeChannel mockNativeChannel; + late MockSentryNativeBinding mockBinding; setUp(() { - mockNativeChannel = MockNativeChannel(); - SentryFlutter.native = - SentryNative(SentryFlutterOptions(dsn: fakeDsn), mockNativeChannel); + mockBinding = MockSentryNativeBinding(); + SentryFlutter.native = mockBinding; }); tearDown(() { @@ -76,9 +74,8 @@ void main() { await sut.completedDisplayTracking?.future; // Handle internal async method calls. - await Future.delayed(const Duration(milliseconds: 10), () { - expect(mockNativeChannel.numberOfBeginNativeFramesCalls, 1); - }); + await Future.delayed(const Duration(milliseconds: 10), () {}); + verify(mockBinding.beginNativeFrames()).called(1); }); test('transaction finish adds native frames to tracer', () async { @@ -88,12 +85,8 @@ void main() { options.tracesSampleRate = 1; final hub = Hub(options); - mockNativeChannel = MockNativeChannel(); - SentryFlutter.native = - SentryNative(SentryFlutterOptions(dsn: fakeDsn), mockNativeChannel); - - final nativeFrames = NativeFrames(3, 2, 1); - mockNativeChannel.nativeFrames = nativeFrames; + when(mockBinding.endNativeFrames(any)) + .thenAnswer((_) async => NativeFrames(3, 2, 1)); final sut = fixture.getSut(hub: hub); @@ -109,7 +102,7 @@ void main() { // Wait for the transaction to finish the async native frame fetching await Future.delayed(Duration(milliseconds: 1500)); - expect(mockNativeChannel.numberOfEndNativeFramesCalls, 1); + verify(mockBinding.beginNativeFrames()).called(1); final measurements = actualTransaction?.measurements ?? {}; @@ -986,8 +979,6 @@ void main() { } class Fixture { - final mockNativeChannel = MockNativeChannel(); - SentryNavigatorObserver getSut({ required Hub hub, bool enableAutoTransactions = true, From 5c83e42a041a0613baf303ea2ce712cbbc3beedd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 19 Jun 2024 15:20:08 +0200 Subject: [PATCH 213/237] build(deps): bump ruby/setup-ruby from 1.179.0 to 1.179.1 (#2094) Bumps [ruby/setup-ruby](https://github.com/ruby/setup-ruby) from 1.179.0 to 1.179.1. - [Release notes](https://github.com/ruby/setup-ruby/releases) - [Commits](https://github.com/ruby/setup-ruby/compare/d5fb7a202fc07872cb44f00ba8e6197b70cb0c55...78c01b705fd9d5ad960d432d3a0cfa341d50e410) --- updated-dependencies: - dependency-name: ruby/setup-ruby dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor --- .github/workflows/testflight.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/testflight.yml b/.github/workflows/testflight.yml index 5ba54d043c..87e55cf30d 100644 --- a/.github/workflows/testflight.yml +++ b/.github/workflows/testflight.yml @@ -16,7 +16,7 @@ jobs: - uses: actions/checkout@v4 - uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 # pin@v2.16.0 - run: xcodes select 15.0.1 - - uses: ruby/setup-ruby@d5fb7a202fc07872cb44f00ba8e6197b70cb0c55 # pin@v1.179.0 + - uses: ruby/setup-ruby@78c01b705fd9d5ad960d432d3a0cfa341d50e410 # pin@v1.179.1 with: ruby-version: '2.7.5' bundler-cache: true From 82369c96f10fd436e477e1769f3ac4921df844ac Mon Sep 17 00:00:00 2001 From: Alejandro Santiago Date: Wed, 19 Jun 2024 14:20:48 +0100 Subject: [PATCH 214/237] docs: include SentryFlutter.init documentation (#2093) Co-authored-by: Giancarlo Buenaflor --- flutter/lib/src/sentry_flutter.dart | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/flutter/lib/src/sentry_flutter.dart b/flutter/lib/src/sentry_flutter.dart index 3a9ac1cb9b..f9914d7eaa 100644 --- a/flutter/lib/src/sentry_flutter.dart +++ b/flutter/lib/src/sentry_flutter.dart @@ -36,6 +36,17 @@ mixin SentryFlutter { // ignore: invalid_use_of_internal_member static DateTime? sentrySetupStartTime; + /// Initializes the Sentry Flutter SDK. + /// + /// Unlike [Sentry.init], this method creates the Flutter default integrations. + /// + /// [optionsConfiguration] is a callback that allows you to configure the Sentry + /// options. The [SentryFlutterOptions] should not be adjusted anywhere else than + /// during [init], so that's why they're not directly exposed outside of this method. + /// + /// You can use the static members of [Sentry] from within other packages without the + /// need of initializing it in the package; as long as they have been already properly + /// initialized in the application package. static Future init( FlutterOptionsConfiguration optionsConfiguration, { AppRunner? appRunner, From 5b88f8ff8465140f755098e693b0a210d8c9f1e0 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 19 Jun 2024 16:38:40 +0200 Subject: [PATCH 215/237] chore(deps): update Cocoa SDK to v8.29.1 (#2109) * chore: update flutter/scripts/update-cocoa.sh to 8.29.1 * formatting --------- Co-authored-by: GitHub Co-authored-by: GIancarlo Buenaflor --- CHANGELOG.md | 8 ++++++++ flutter/ios/sentry_flutter.podspec | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 75b24a6314..5ae8139d38 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## Unreleased + +### Dependencies + +- Bump Cocoa SDK from v8.29.0 to v8.29.1 ([#2109](https://github.com/getsentry/sentry-dart/pull/2109)) + - [changelog](https://github.com/getsentry/sentry-cocoa/blob/main/CHANGELOG.md#8291) + - [diff](https://github.com/getsentry/sentry-cocoa/compare/8.29.0...8.29.1) + ## 8.3.0 ### Fixes diff --git a/flutter/ios/sentry_flutter.podspec b/flutter/ios/sentry_flutter.podspec index bd76cc2f2f..8881fdefec 100644 --- a/flutter/ios/sentry_flutter.podspec +++ b/flutter/ios/sentry_flutter.podspec @@ -16,7 +16,7 @@ Sentry SDK for Flutter with support to native through sentry-cocoa. :tag => s.version.to_s } s.source_files = 'Classes/**/*' s.public_header_files = 'Classes/**/*.h' - s.dependency 'Sentry/HybridSDK', '8.29.0' + s.dependency 'Sentry/HybridSDK', '8.29.1' s.ios.dependency 'Flutter' s.osx.dependency 'FlutterMacOS' s.ios.deployment_target = '12.0' From f3c5f6bd7705084a405c2185d49b232da69c28be Mon Sep 17 00:00:00 2001 From: Ivan Dlugos <6349682+vaind@users.noreply.github.com> Date: Thu, 20 Jun 2024 13:23:12 +0200 Subject: [PATCH 216/237] ci: deduplicate dart tests in actions (#2114) * ci: deduplicate dart tests in actions * fix checkout * disable web tests on file and hive --- .github/actions/coverage/action.yml | 37 ++++++++++++++++++++++ .github/actions/dart-test/action.yml | 34 ++++++++++++++++++++ .github/workflows/dart.yml | 47 ++++++++++------------------ .github/workflows/dio.yml | 37 +++++++--------------- .github/workflows/file.yml | 39 ++++++++--------------- .github/workflows/hive.yml | 37 +++++++--------------- .github/workflows/logging.yml | 38 +++++++--------------- 7 files changed, 135 insertions(+), 134 deletions(-) create mode 100644 .github/actions/coverage/action.yml create mode 100644 .github/actions/dart-test/action.yml diff --git a/.github/actions/coverage/action.yml b/.github/actions/coverage/action.yml new file mode 100644 index 0000000000..9eaf7f0393 --- /dev/null +++ b/.github/actions/coverage/action.yml @@ -0,0 +1,37 @@ +name: Dart tests +description: Run Dart Tests and collect coverage +inputs: + directory: + description: The directory to run tests in + required: false + default: '' + coverage: + description: Codecov name + required: false + default: '' + min-coverage: + description: Minimum coverage percentage + required: false + default: '0' + +runs: + using: composite + + steps: + - name: Format coverage info + if: ${{ inputs.coverage != '' }} + run: dart pub run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.dart_tool/package_config.json --report-on=lib + shell: bash + working-directory: ${{ inputs.directory }} + + - uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # pin@v3 + if: ${{ inputs.coverage != '' }} + with: + name: ${{ inputs.coverage != '' }} + files: ./${{ inputs.directory }}/coverage/lcov.info + + - uses: VeryGoodOpenSource/very_good_coverage@c953fca3e24a915e111cc6f55f03f756dcb3964c # pin@v3.0.0 + if: ${{ inputs.coverage != '' }} + with: + path: './${{ inputs.directory }}/coverage/lcov.info' + min_coverage: ${{ inputs.min-coverage }} diff --git a/.github/actions/dart-test/action.yml b/.github/actions/dart-test/action.yml new file mode 100644 index 0000000000..606f145c64 --- /dev/null +++ b/.github/actions/dart-test/action.yml @@ -0,0 +1,34 @@ +name: Dart tests +description: Run Dart tests +inputs: + directory: + description: The directory to run tests in + required: false + default: '' + web: + description: Whether to run tests for web + required: false + default: 'true' + +runs: + using: composite + + steps: + - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 # pin@v1 + with: + sdk: ${{ matrix.sdk }} + + - run: dart pub get + shell: bash + working-directory: ${{ inputs.directory }} + + - name: Test VM + run: dart test -p vm --coverage=coverage --test-randomize-ordering-seed=random --chain-stack-traces + shell: bash + working-directory: ${{ inputs.directory }} + + - name: Test dart2js + if: ${{ inputs.web == 'true' }} + run: dart test -p chrome --test-randomize-ordering-seed=random --chain-stack-traces + shell: bash + working-directory: ${{ inputs.directory }} diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml index 625dcf9c86..650adefa46 100644 --- a/.github/workflows/dart.yml +++ b/.github/workflows/dart.yml @@ -6,10 +6,10 @@ on: - release/** pull_request: paths: - - "!**/*.md" - - "!**/class-diagram.svg" - - ".github/workflows/dart.yml" - - "dart/**" + - '!**/*.md' + - '!**/class-diagram.svg' + - '.github/workflows/dart.yml' + - 'dart/**' jobs: cancel-previous-workflow: @@ -24,10 +24,6 @@ jobs: name: Build ${{matrix.sdk}} on ${{matrix.os}} runs-on: ${{ matrix.os }} timeout-minutes: 30 - defaults: - run: - shell: bash - working-directory: ./dart strategy: fail-fast: false matrix: @@ -39,47 +35,36 @@ jobs: - os: macos-latest sdk: beta steps: - - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 # pin@v1 - with: - sdk: ${{ matrix.sdk }} - uses: actions/checkout@v4 - - name: Test (VM and browser) - run: | - dart pub get - dart test -p chrome --test-randomize-ordering-seed=random --chain-stack-traces - dart test -p vm --coverage=coverage --test-randomize-ordering-seed=random --chain-stack-traces - dart pub run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.dart_tool/package_config.json --report-on=lib + - uses: ./.github/actions/dart-test + with: + directory: dart + + - uses: ./.github/actions/coverage + if: runner.os == 'Linux' && matrix.sdk == 'stable' + with: + directory: dart + coverage: sentry + min-coverage: 85 - name: Install webdev if: runner.os != 'Windows' run: dart pub global activate webdev - name: Build example + working-directory: dart/example run: | - cd example dart pub get dart compile aot-snapshot bin/example.dart - name: Build Web example if: runner.os != 'Windows' + working-directory: dart/example_web run: | - cd example_web dart pub get webdev build - - uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # pin@v3 - if: runner.os == 'Linux' && matrix.sdk == 'stable' - with: - name: sentry - files: ./dart/coverage/lcov.info - - - uses: VeryGoodOpenSource/very_good_coverage@c953fca3e24a915e111cc6f55f03f756dcb3964c # pin@v3.0.0 - if: runner.os == 'Linux' && matrix.sdk == 'stable' - with: - path: "./dart/coverage/lcov.info" - min_coverage: 85 - analyze: uses: ./.github/workflows/analyze.yml with: diff --git a/.github/workflows/dio.yml b/.github/workflows/dio.yml index e096e3a10e..902012b688 100644 --- a/.github/workflows/dio.yml +++ b/.github/workflows/dio.yml @@ -6,11 +6,11 @@ on: - release/** pull_request: paths: - - "!**/*.md" - - "!**/class-diagram.svg" - - ".github/workflows/dio.yml" - - "dart/**" - - "dio/**" + - '!**/*.md' + - '!**/class-diagram.svg' + - '.github/workflows/dio.yml' + - 'dart/**' + - 'dio/**' jobs: cancel-previous-workflow: @@ -25,10 +25,6 @@ jobs: name: Build ${{matrix.sdk}} on ${{matrix.os}} runs-on: ${{ matrix.os }} timeout-minutes: 30 - defaults: - run: - shell: bash - working-directory: ./dio strategy: fail-fast: false matrix: @@ -40,29 +36,18 @@ jobs: - os: macos-latest sdk: beta steps: - - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 # pin@v1 - with: - sdk: ${{ matrix.sdk }} - uses: actions/checkout@v4 - - name: Test (VM and browser) - run: | - dart pub get - dart test -p chrome --test-randomize-ordering-seed=random --chain-stack-traces - dart test -p vm --coverage=coverage --test-randomize-ordering-seed=random --chain-stack-traces - dart pub run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.dart_tool/package_config.json --report-on=lib - - - uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # pin@v3 - if: runner.os == 'Linux' && matrix.sdk == 'stable' + - uses: ./.github/actions/dart-test with: - name: sentry_dio - files: ./dio/coverage/lcov.info + directory: dio - - uses: VeryGoodOpenSource/very_good_coverage@c953fca3e24a915e111cc6f55f03f756dcb3964c # pin@v3.0.0 + - uses: ./.github/actions/coverage if: runner.os == 'Linux' && matrix.sdk == 'stable' with: - path: "./dio/coverage/lcov.info" - min_coverage: 81 + directory: dio + coverage: sentry_dio + min-coverage: 81 analyze: uses: ./.github/workflows/analyze.yml diff --git a/.github/workflows/file.yml b/.github/workflows/file.yml index 34e2e42ba4..30416c4f0a 100644 --- a/.github/workflows/file.yml +++ b/.github/workflows/file.yml @@ -6,12 +6,12 @@ on: - release/** pull_request: paths: - - "!**/*.md" - - "!**/class-diagram.svg" - - ".github/workflows/file.yml" - - "dart/**" - - "flutter/**" - - "file/**" + - '!**/*.md' + - '!**/class-diagram.svg' + - '.github/workflows/file.yml' + - 'dart/**' + - 'flutter/**' + - 'file/**' jobs: cancel-previous-workflow: @@ -26,10 +26,6 @@ jobs: name: Build ${{matrix.sdk}} on ${{matrix.os}} runs-on: ${{ matrix.os }} timeout-minutes: 30 - defaults: - run: - shell: bash - working-directory: ./file strategy: fail-fast: false matrix: @@ -41,28 +37,19 @@ jobs: - os: macos-latest sdk: beta steps: - - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 # pin@v1 - with: - sdk: ${{ matrix.sdk }} - uses: actions/checkout@v4 - - name: Test VM - run: | - dart pub get - dart test -p vm --coverage=coverage --test-randomize-ordering-seed=random --chain-stack-traces - dart pub run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.dart_tool/package_config.json --report-on=lib - - - uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # pin@v3 - if: runner.os == 'Linux' && matrix.sdk == 'stable' + - uses: ./.github/actions/dart-test with: - name: sentry_file - files: ./file/coverage/lcov.info + directory: file + web: false - - uses: VeryGoodOpenSource/very_good_coverage@c953fca3e24a915e111cc6f55f03f756dcb3964c # pin@v3.0.0 + - uses: ./.github/actions/coverage if: runner.os == 'Linux' && matrix.sdk == 'stable' with: - path: "./file/coverage/lcov.info" - min_coverage: 55 + directory: file + coverage: sentry_file + min-coverage: 55 analyze: uses: ./.github/workflows/analyze.yml diff --git a/.github/workflows/hive.yml b/.github/workflows/hive.yml index 2855960115..2f32603646 100644 --- a/.github/workflows/hive.yml +++ b/.github/workflows/hive.yml @@ -6,11 +6,11 @@ on: - release/** pull_request: paths: - - "!**/*.md" - - "!**/class-diagram.svg" - - ".github/workflows/hive.yml" - - "dart/**" - - "hive/**" + - '!**/*.md' + - '!**/class-diagram.svg' + - '.github/workflows/hive.yml' + - 'dart/**' + - 'hive/**' jobs: cancel-previous-workflow: @@ -25,10 +25,6 @@ jobs: name: Build ${{matrix.sdk}} on ${{matrix.os}} runs-on: ${{ matrix.os }} timeout-minutes: 30 - defaults: - run: - shell: bash - working-directory: ./hive strategy: fail-fast: false matrix: @@ -40,28 +36,19 @@ jobs: - os: macos-latest sdk: beta steps: - - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 # pin@v1 - with: - sdk: ${{ matrix.sdk }} - uses: actions/checkout@v4 - - name: Test VM - run: | - dart pub get - dart test -p vm --coverage=coverage --test-randomize-ordering-seed=random --chain-stack-traces - dart pub run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.dart_tool/package_config.json --report-on=lib - - - uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # pin@v3 - if: runner.os == 'Linux' && matrix.sdk == 'stable' + - uses: ./.github/actions/dart-test with: - name: sentry_hive - files: ./hive/coverage/lcov.info + directory: hive + web: false - - uses: VeryGoodOpenSource/very_good_coverage@c953fca3e24a915e111cc6f55f03f756dcb3964c # pin@v3.0.0 + - uses: ./.github/actions/coverage if: runner.os == 'Linux' && matrix.sdk == 'stable' with: - path: "./hive/coverage/lcov.info" - min_coverage: 55 + directory: hive + coverage: sentry_hive + min-coverage: 55 analyze: uses: ./.github/workflows/analyze.yml diff --git a/.github/workflows/logging.yml b/.github/workflows/logging.yml index a8e08fd172..6b6c1bf6be 100644 --- a/.github/workflows/logging.yml +++ b/.github/workflows/logging.yml @@ -6,11 +6,11 @@ on: - release/** pull_request: paths: - - "!**/*.md" - - "!**/class-diagram.svg" - - ".github/workflows/logging.yml" - - "dart/**" - - "logging/**" + - '!**/*.md' + - '!**/class-diagram.svg' + - '.github/workflows/logging.yml' + - 'dart/**' + - 'logging/**' jobs: cancel-previous-workflow: @@ -25,10 +25,6 @@ jobs: name: Build ${{matrix.sdk}} on ${{matrix.os}} runs-on: ${{ matrix.os }} timeout-minutes: 30 - defaults: - run: - shell: bash - working-directory: ./logging strategy: fail-fast: false matrix: @@ -40,28 +36,18 @@ jobs: - os: macos-latest sdk: beta steps: - - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 # pin@v1 - with: - sdk: ${{ matrix.sdk }} - uses: actions/checkout@v4 - - name: Test (VM and browser) - run: | - dart pub get - dart test -p chrome --test-randomize-ordering-seed=random --chain-stack-traces - dart test -p vm --coverage=coverage --test-randomize-ordering-seed=random --chain-stack-traces - dart pub run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.dart_tool/package_config.json --report-on=lib - - - uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # pin@v3 - if: runner.os == 'Linux' && matrix.sdk == 'stable' + - uses: ./.github/actions/dart-test with: - name: sentry_logging - files: ./logging/coverage/lcov.info + directory: logging - - uses: VeryGoodOpenSource/very_good_coverage@c953fca3e24a915e111cc6f55f03f756dcb3964c # pin@v2.1.0 if: runner.os == 'Linux' && matrix.sdk == 'stable' + - uses: ./.github/actions/coverage + if: runner.os == 'Linux' && matrix.sdk == 'stable' with: - path: "./logging/coverage/lcov.info" - min_coverage: 90 + directory: logging + coverage: sentry_logging + min-coverage: 90 analyze: uses: ./.github/workflows/analyze.yml From 3c912682c10e5f7525bbda1344c7b20616deb220 Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Thu, 20 Jun 2024 14:28:41 +0200 Subject: [PATCH 217/237] Add codecov token reference (#2118) --- .github/actions/coverage/action.yml | 1 + .github/workflows/drift.yml | 1 + .github/workflows/isar.yml | 1 + .github/workflows/sqflite.yml | 1 + 4 files changed, 4 insertions(+) diff --git a/.github/actions/coverage/action.yml b/.github/actions/coverage/action.yml index 9eaf7f0393..427e1818af 100644 --- a/.github/actions/coverage/action.yml +++ b/.github/actions/coverage/action.yml @@ -29,6 +29,7 @@ runs: with: name: ${{ inputs.coverage != '' }} files: ./${{ inputs.directory }}/coverage/lcov.info + token: ${{ secrets.CODECOV_TOKEN }} - uses: VeryGoodOpenSource/very_good_coverage@c953fca3e24a915e111cc6f55f03f756dcb3964c # pin@v3.0.0 if: ${{ inputs.coverage != '' }} diff --git a/.github/workflows/drift.yml b/.github/workflows/drift.yml index 075cdacddf..a1aa8ac4bd 100644 --- a/.github/workflows/drift.yml +++ b/.github/workflows/drift.yml @@ -102,6 +102,7 @@ jobs: name: sentry_drift file: ./drift/coverage/lcov.info functionalities: "search" # remove after https://github.com/codecov/codecov-action/issues/600 + token: ${{ secrets.CODECOV_TOKEN }} - uses: VeryGoodOpenSource/very_good_coverage@c953fca3e24a915e111cc6f55f03f756dcb3964c # pin@v3.0.0 if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' diff --git a/.github/workflows/isar.yml b/.github/workflows/isar.yml index b1237202c8..06d5b18c8e 100644 --- a/.github/workflows/isar.yml +++ b/.github/workflows/isar.yml @@ -102,6 +102,7 @@ jobs: name: sentry_isar file: ./isar/coverage/lcov.info functionalities: "search" # remove after https://github.com/codecov/codecov-action/issues/600 + token: ${{ secrets.CODECOV_TOKEN }} - uses: VeryGoodOpenSource/very_good_coverage@c953fca3e24a915e111cc6f55f03f756dcb3964c # pin@v3.0.0 if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' diff --git a/.github/workflows/sqflite.yml b/.github/workflows/sqflite.yml index 7515d9d4b1..feac37bd80 100644 --- a/.github/workflows/sqflite.yml +++ b/.github/workflows/sqflite.yml @@ -102,6 +102,7 @@ jobs: name: sentry_sqflite file: ./sqflite/coverage/lcov.info functionalities: "search" # remove after https://github.com/codecov/codecov-action/issues/600 + token: ${{ secrets.CODECOV_TOKEN }} - uses: VeryGoodOpenSource/very_good_coverage@c953fca3e24a915e111cc6f55f03f756dcb3964c # pin@v3.0.0 if: runner.os == 'Linux' && matrix.sdk == 'stable' && matrix.target == 'linux' From b87d0b3c2bba57bddb26736911e83b8e6aa28bcb Mon Sep 17 00:00:00 2001 From: Ivan Dlugos <6349682+vaind@users.noreply.github.com> Date: Thu, 20 Jun 2024 15:32:01 +0200 Subject: [PATCH 218/237] ci: fix codecov token passing (#2121) --- .github/actions/coverage/action.yml | 5 ++++- .github/workflows/dart.yml | 1 + .github/workflows/dio.yml | 1 + .github/workflows/file.yml | 1 + .github/workflows/hive.yml | 1 + .github/workflows/logging.yml | 1 + 6 files changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/actions/coverage/action.yml b/.github/actions/coverage/action.yml index 427e1818af..5989db8aac 100644 --- a/.github/actions/coverage/action.yml +++ b/.github/actions/coverage/action.yml @@ -13,6 +13,9 @@ inputs: description: Minimum coverage percentage required: false default: '0' + token: + description: Codecov token + required: true runs: using: composite @@ -29,7 +32,7 @@ runs: with: name: ${{ inputs.coverage != '' }} files: ./${{ inputs.directory }}/coverage/lcov.info - token: ${{ secrets.CODECOV_TOKEN }} + token: ${{ inputs.token }} - uses: VeryGoodOpenSource/very_good_coverage@c953fca3e24a915e111cc6f55f03f756dcb3964c # pin@v3.0.0 if: ${{ inputs.coverage != '' }} diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml index 650adefa46..ef6a7de8e5 100644 --- a/.github/workflows/dart.yml +++ b/.github/workflows/dart.yml @@ -44,6 +44,7 @@ jobs: - uses: ./.github/actions/coverage if: runner.os == 'Linux' && matrix.sdk == 'stable' with: + token: ${{ secrets.CODECOV_TOKEN }} directory: dart coverage: sentry min-coverage: 85 diff --git a/.github/workflows/dio.yml b/.github/workflows/dio.yml index 902012b688..8aa8e578cd 100644 --- a/.github/workflows/dio.yml +++ b/.github/workflows/dio.yml @@ -45,6 +45,7 @@ jobs: - uses: ./.github/actions/coverage if: runner.os == 'Linux' && matrix.sdk == 'stable' with: + token: ${{ secrets.CODECOV_TOKEN }} directory: dio coverage: sentry_dio min-coverage: 81 diff --git a/.github/workflows/file.yml b/.github/workflows/file.yml index 30416c4f0a..6d5cd8f8c9 100644 --- a/.github/workflows/file.yml +++ b/.github/workflows/file.yml @@ -47,6 +47,7 @@ jobs: - uses: ./.github/actions/coverage if: runner.os == 'Linux' && matrix.sdk == 'stable' with: + token: ${{ secrets.CODECOV_TOKEN }} directory: file coverage: sentry_file min-coverage: 55 diff --git a/.github/workflows/hive.yml b/.github/workflows/hive.yml index 2f32603646..9200a4ab0a 100644 --- a/.github/workflows/hive.yml +++ b/.github/workflows/hive.yml @@ -46,6 +46,7 @@ jobs: - uses: ./.github/actions/coverage if: runner.os == 'Linux' && matrix.sdk == 'stable' with: + token: ${{ secrets.CODECOV_TOKEN }} directory: hive coverage: sentry_hive min-coverage: 55 diff --git a/.github/workflows/logging.yml b/.github/workflows/logging.yml index 6b6c1bf6be..803b205dd4 100644 --- a/.github/workflows/logging.yml +++ b/.github/workflows/logging.yml @@ -45,6 +45,7 @@ jobs: - uses: ./.github/actions/coverage if: runner.os == 'Linux' && matrix.sdk == 'stable' with: + token: ${{ secrets.CODECOV_TOKEN }} directory: logging coverage: sentry_logging min-coverage: 90 From 04bd9e665bd9e8a5f2d1b16c55e4e3fdd18f9b6d Mon Sep 17 00:00:00 2001 From: Ivan Dlugos <6349682+vaind@users.noreply.github.com> Date: Mon, 24 Jun 2024 11:37:21 +0200 Subject: [PATCH 219/237] ci: update metrics-ios.yml (#2124) --- metrics/metrics-ios.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/metrics/metrics-ios.yml b/metrics/metrics-ios.yml index 57177c0899..6c7e175b04 100644 --- a/metrics/metrics-ios.yml +++ b/metrics/metrics-ios.yml @@ -10,5 +10,5 @@ startupTimeTest: diffMax: 150 binarySizeTest: - diffMin: 900 KiB - diffMax: 1300 KiB + diffMin: 1200 KiB + diffMax: 1500 KiB From 99b37a63685b3aff7826925353d08423bf5ebe92 Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Mon, 24 Jun 2024 12:26:13 +0200 Subject: [PATCH 220/237] Ignore .fvm (#2125) --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 1f40d0ebb1..2965c68572 100644 --- a/.gitignore +++ b/.gitignore @@ -13,7 +13,7 @@ pubspec.lock build/ .cxx/ .vscode/ - +.fvm/ .test_coverage.dart dart/coverage/* From ed9c5882af6da771d858dfd6c912e8dd1c92daaf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Jun 2024 23:06:29 +0200 Subject: [PATCH 221/237] build(deps): bump gradle/gradle-build-action from 3.4.1 to 3.4.2 (#2127) Bumps [gradle/gradle-build-action](https://github.com/gradle/gradle-build-action) from 3.4.1 to 3.4.2. - [Release notes](https://github.com/gradle/gradle-build-action/releases) - [Commits](https://github.com/gradle/gradle-build-action/compare/04b20c065cf1ab708c96e64a8811018d0a1fbc88...66535aaf56f831b35e3a8481c9c99b665b84dd45) --- updated-dependencies: - dependency-name: gradle/gradle-build-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/flutter_integration_test.yml | 2 +- .github/workflows/flutter_test.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/flutter_integration_test.yml b/.github/workflows/flutter_integration_test.yml index 25a88a9291..f51af5d341 100644 --- a/.github/workflows/flutter_integration_test.yml +++ b/.github/workflows/flutter_integration_test.yml @@ -49,7 +49,7 @@ jobs: run: flutter pub get - name: Gradle cache - uses: gradle/gradle-build-action@04b20c065cf1ab708c96e64a8811018d0a1fbc88 # pin@v3.4.1 + uses: gradle/gradle-build-action@66535aaf56f831b35e3a8481c9c99b665b84dd45 # pin@v3.4.2 - name: AVD cache uses: actions/cache@v4 diff --git a/.github/workflows/flutter_test.yml b/.github/workflows/flutter_test.yml index 4d355a7310..d5b894ab36 100644 --- a/.github/workflows/flutter_test.yml +++ b/.github/workflows/flutter_test.yml @@ -54,7 +54,7 @@ jobs: run: flutter pub get - name: Gradle cache - uses: gradle/gradle-build-action@04b20c065cf1ab708c96e64a8811018d0a1fbc88 # pin@v3.0.0 + uses: gradle/gradle-build-action@66535aaf56f831b35e3a8481c9c99b665b84dd45 # pin@v3.0.0 - name: AVD cache uses: actions/cache@v4 From 389a4e154da857d171b845033816f354d7e954c3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Jun 2024 23:06:44 +0200 Subject: [PATCH 222/237] build(deps): bump ruby/setup-ruby from 1.179.1 to 1.180.1 (#2128) Bumps [ruby/setup-ruby](https://github.com/ruby/setup-ruby) from 1.179.1 to 1.180.1. - [Release notes](https://github.com/ruby/setup-ruby/releases) - [Commits](https://github.com/ruby/setup-ruby/compare/78c01b705fd9d5ad960d432d3a0cfa341d50e410...3783f195e29b74ae398d7caca108814bbafde90e) --- updated-dependencies: - dependency-name: ruby/setup-ruby dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/testflight.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/testflight.yml b/.github/workflows/testflight.yml index 87e55cf30d..4f69c558f8 100644 --- a/.github/workflows/testflight.yml +++ b/.github/workflows/testflight.yml @@ -16,7 +16,7 @@ jobs: - uses: actions/checkout@v4 - uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 # pin@v2.16.0 - run: xcodes select 15.0.1 - - uses: ruby/setup-ruby@78c01b705fd9d5ad960d432d3a0cfa341d50e410 # pin@v1.179.1 + - uses: ruby/setup-ruby@3783f195e29b74ae398d7caca108814bbafde90e # pin@v1.180.1 with: ruby-version: '2.7.5' bundler-cache: true From 7e7f0b1ba00d87ca0c564c0aee2b80b9e66a8253 Mon Sep 17 00:00:00 2001 From: Ivan Dlugos <6349682+vaind@users.noreply.github.com> Date: Tue, 25 Jun 2024 10:19:08 +0200 Subject: [PATCH 223/237] feat: enable wasm compilation (#2113) * feat: migrates to package:web and js_interop * fix: enhances comment * chore: Adds changelog * chore: formatting * fix: changes min flutter version to 3.13.0 and dart sdk 3.1.0 to be compatible with package:web 0.5.1 * compat with dart:html & dart:web * fixups * more fixups * analyzer * chore: changelog entry * run dart test for all supported dart version * update web example tests * update ci * update deps so that we can run test with old dart versions * fix ci * fix web enricher test * fix ci * ci fixes * ignore pana error * fix CI * fix ci * remove dart 2.17 build * fixes * fix CI * test dart2wasm * cleanup * disable dart2wasm on windows * fix tests for wasm --------- Co-authored-by: Josh Burton --- .github/actions/dart-test/action.yml | 8 +- .github/workflows/analyze.yml | 4 +- .github/workflows/dart.yml | 39 +++-- .github/workflows/flutter.yml | 1 + CHANGELOG.md | 12 +- dart/example_web/pubspec.yaml | 1 + dart/example_web/web/main.dart | 33 +++-- dart/example_web_legacy/.gitignore | 9 ++ dart/example_web_legacy/README.md | 8 ++ dart/example_web_legacy/analysis_options.yaml | 5 + dart/example_web_legacy/pubspec.yaml | 17 +++ dart/example_web_legacy/web/event.dart | 76 ++++++++++ dart/example_web_legacy/web/favicon.ico | Bin 0 -> 3559 bytes dart/example_web_legacy/web/index.html | 69 +++++++++ dart/example_web_legacy/web/main.dart | 135 ++++++++++++++++++ dart/example_web_legacy/web/styles.css | 14 ++ .../environment/environment_variables.dart | 3 +- .../enricher/enricher_event_processor.dart | 3 +- .../html_enricher_event_processor.dart | 103 +++++++++++++ .../web_enricher_event_processor.dart | 33 +++-- .../exception/exception_event_processor.dart | 3 +- dart/lib/src/origin.dart | 7 +- dart/lib/src/origin_html.dart | 4 + .../src/{noop_origin.dart => origin_io.dart} | 0 dart/lib/src/origin_web.dart | 6 + dart/lib/src/platform/_html_platform.dart | 51 +++++++ dart/lib/src/platform/_web_platform.dart | 14 +- dart/lib/src/platform/platform.dart | 5 +- dart/lib/src/sentry_client_stub.dart | 11 -- dart/lib/src/sentry_stack_trace_factory.dart | 2 +- dart/lib/src/utils/isolate_utils.dart | 3 +- dart/pubspec.yaml | 5 +- .../enricher/web_enricher_test.dart | 18 +-- dart/test/example_web_compile_test.dart | 27 ++-- dart/test/sentry_client_test.dart | 5 +- dart/test/stack_trace_test.dart | 3 +- dart/test/test_utils.dart | 5 + file/lib/src/sentry_file_extension.dart | 4 +- .../connectivity/connectivity_provider.dart | 3 +- .../html_connectivity_provider.dart | 32 +++++ .../web_connectivity_provider.dart | 17 ++- flutter/lib/src/native/factory.dart | 4 +- flutter/lib/src/renderer/renderer.dart | 1 + flutter/lib/src/renderer/web_renderer.dart | 18 +++ hive/lib/src/sentry_box_collection.dart | 1 + hive/test/mocks/mocks.dart | 1 + hive/test/mocks/mocks.mocks.dart | 1 + min_version_test/lib/main.dart | 7 +- .../lib/transaction/file_transaction.dart | 4 +- ...ion_locator.dart => transaction_stub.dart} | 2 +- .../lib/transaction/web_transaction.dart | 5 +- min_version_test/pubspec.yaml | 1 - 52 files changed, 716 insertions(+), 127 deletions(-) create mode 100644 dart/example_web_legacy/.gitignore create mode 100644 dart/example_web_legacy/README.md create mode 100644 dart/example_web_legacy/analysis_options.yaml create mode 100644 dart/example_web_legacy/pubspec.yaml create mode 100644 dart/example_web_legacy/web/event.dart create mode 100644 dart/example_web_legacy/web/favicon.ico create mode 100644 dart/example_web_legacy/web/index.html create mode 100644 dart/example_web_legacy/web/main.dart create mode 100644 dart/example_web_legacy/web/styles.css create mode 100644 dart/lib/src/event_processor/enricher/html_enricher_event_processor.dart create mode 100644 dart/lib/src/origin_html.dart rename dart/lib/src/{noop_origin.dart => origin_io.dart} (100%) create mode 100644 dart/lib/src/origin_web.dart create mode 100644 dart/lib/src/platform/_html_platform.dart delete mode 100644 dart/lib/src/sentry_client_stub.dart create mode 100644 flutter/lib/src/integrations/connectivity/html_connectivity_provider.dart create mode 100644 flutter/lib/src/renderer/web_renderer.dart rename min_version_test/lib/transaction/{transaction_locator.dart => transaction_stub.dart} (60%) diff --git a/.github/actions/dart-test/action.yml b/.github/actions/dart-test/action.yml index 606f145c64..bb13fa0300 100644 --- a/.github/actions/dart-test/action.yml +++ b/.github/actions/dart-test/action.yml @@ -23,7 +23,7 @@ runs: working-directory: ${{ inputs.directory }} - name: Test VM - run: dart test -p vm --coverage=coverage --test-randomize-ordering-seed=random --chain-stack-traces + run: dart test -p vm ${{ (runner.os == 'Linux' && matrix.sdk == 'stable' && '--coverage=coverage') || '' }} --test-randomize-ordering-seed=random --chain-stack-traces shell: bash working-directory: ${{ inputs.directory }} @@ -32,3 +32,9 @@ runs: run: dart test -p chrome --test-randomize-ordering-seed=random --chain-stack-traces shell: bash working-directory: ${{ inputs.directory }} + + - name: Test dart2wasm + if: ${{ inputs.web == 'true' && (matrix.sdk == 'stable' || matrix.sdk == 'beta') && runner.os != 'Windows' }} + run: dart test -p chrome --compiler dart2wasm --test-randomize-ordering-seed=random --chain-stack-traces + shell: bash + working-directory: ${{ inputs.directory }} diff --git a/.github/workflows/analyze.yml b/.github/workflows/analyze.yml index bf31098e20..fa3ef62068 100644 --- a/.github/workflows/analyze.yml +++ b/.github/workflows/analyze.yml @@ -39,7 +39,7 @@ jobs: - run: ${{ inputs.sdk }} pub get - run: dart format --set-exit-if-changed ./ - + - name: dart analyze uses: invertase/github-action-dart-analyzer@e981b01a458d0bab71ee5da182e5b26687b7101b # pin@v3.0.0 with: @@ -78,6 +78,6 @@ jobs: PERCENTAGE=$(( $TOTAL * 100 / $TOTAL_MAX )) if (( $PERCENTAGE < ${{ inputs.panaThreshold }} )) then - echo Score too low! + echo "Score too low ($PERCENTAGE % is less than the expected ${{ inputs.panaThreshold }} %)!" exit 1 fi diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml index ef6a7de8e5..8f2c2f2b10 100644 --- a/.github/workflows/dart.yml +++ b/.github/workflows/dart.yml @@ -21,19 +21,28 @@ jobs: access_token: ${{ github.token }} build: - name: Build ${{matrix.sdk}} on ${{matrix.os}} - runs-on: ${{ matrix.os }} + name: Dart ${{matrix.sdk}} on ${{matrix.os}} + runs-on: ${{ matrix.os }}-latest timeout-minutes: 30 strategy: fail-fast: false matrix: - os: [ubuntu-latest, windows-latest, macos-latest] - sdk: [stable, beta] - exclude: - - os: windows-latest - sdk: beta - - os: macos-latest - sdk: beta + os: [ubuntu] + sdk: + - '2.18' + - '2.19' + - '3.0' + - '3.1' + - '3.2' + - '3.3' + - '3.4' + - stable + - beta + include: + - os: windows + sdk: stable + - os: macos + sdk: stable steps: - uses: actions/checkout@v4 @@ -49,24 +58,14 @@ jobs: coverage: sentry min-coverage: 85 - - name: Install webdev - if: runner.os != 'Windows' - run: dart pub global activate webdev - - name: Build example working-directory: dart/example run: | dart pub get dart compile aot-snapshot bin/example.dart - - name: Build Web example - if: runner.os != 'Windows' - working-directory: dart/example_web - run: | - dart pub get - webdev build - analyze: uses: ./.github/workflows/analyze.yml with: package: dart + panaThreshold: 87 diff --git a/.github/workflows/flutter.yml b/.github/workflows/flutter.yml index cec1edecab..32130d4765 100644 --- a/.github/workflows/flutter.yml +++ b/.github/workflows/flutter.yml @@ -144,6 +144,7 @@ jobs: with: package: flutter sdk: flutter + panaThreshold: 87 pod-lint: runs-on: macos-latest diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ae8139d38..0bc2f45ab2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Features + +- Support WebAssembly compilation (dart2wasm) ([#2113](https://github.com/getsentry/sentry-dart/pull/2113)) + ### Dependencies - Bump Cocoa SDK from v8.29.0 to v8.29.1 ([#2109](https://github.com/getsentry/sentry-dart/pull/2109)) @@ -122,7 +126,7 @@ This release contains breaking changes, please read the changelog carefully. ### Features -- Experimental: Add support for Sentry Developer Metrics ([#1940](https://github.com/getsentry/sentry-dart/pull/1940), [#1949](https://github.com/getsentry/sentry-dart/pull/1949), [#1954](https://github.com/getsentry/sentry-dart/pull/1954), [#1958](https://github.com/getsentry/sentry-dart/pull/1958)) +- Experimental: Add support for Sentry Developer Metrics ([#1940](https://github.com/getsentry/sentry-dart/pull/1940), [#1949](https://github.com/getsentry/sentry-dart/pull/1949), [#1954](https://github.com/getsentry/sentry-dart/pull/1954), [#1958](https://github.com/getsentry/sentry-dart/pull/1958)) Use the Metrics API to track processing time, download sizes, user signups, and conversion rates and correlate them back to tracing data in order to get deeper insights and solve issues faster. Our API supports counters, distributions, sets, gauges and timers, and it's easy to get started: ```dart Sentry.metrics() @@ -235,14 +239,14 @@ This release contains breaking changes, please read the changelog carefully. - Now the device context from Android is available in `BeforeSendCallback` - Set ip_address to {{auto}} by default, even if sendDefaultPII is disabled ([#1665](https://github.com/getsentry/sentry-dart/pull/1665)) - Instead use the "Prevent Storing of IP Addresses" option in the "Security & Privacy" project settings on sentry.io - -### Fixes + +### Fixes - Remove Flutter dependency from Drift integration ([#1867](https://github.com/getsentry/sentry-dart/pull/1867)) - Remove dead code, cold start bool is now always present ([#1861](https://github.com/getsentry/sentry-dart/pull/1861)) - Fix iOS "Arithmetic Overflow" ([#1874](https://github.com/getsentry/sentry-dart/pull/1874)) -### Dependencies +### Dependencies - Bump Cocoa SDK from v8.19.0 to v8.20.0 ([#1856](https://github.com/getsentry/sentry-dart/pull/1856)) - [changelog](https://github.com/getsentry/sentry-cocoa/blob/main/CHANGELOG.md#8200) diff --git a/dart/example_web/pubspec.yaml b/dart/example_web/pubspec.yaml index 7bcb64d06e..141e5120ac 100644 --- a/dart/example_web/pubspec.yaml +++ b/dart/example_web/pubspec.yaml @@ -9,6 +9,7 @@ environment: dependencies: sentry: path: ../../dart/ + web: ^0.5.1 dev_dependencies: build_runner: ^2.4.2 diff --git a/dart/example_web/web/main.dart b/dart/example_web/web/main.dart index 3034effe9b..b39a05e0dc 100644 --- a/dart/example_web/web/main.dart +++ b/dart/example_web/web/main.dart @@ -1,5 +1,5 @@ import 'dart:async'; -import 'dart:html'; +import 'package:web/web.dart'; import 'package:sentry/sentry.dart'; import 'package:sentry/src/version.dart'; @@ -24,7 +24,7 @@ Future main() async { Future runApp() async { print('runApp'); - querySelector('#output')?.text = 'Your Dart app is running.'; + document.querySelector('#output')?.text = 'Your Dart app is running.'; await Sentry.addBreadcrumb( Breadcrumb( @@ -57,12 +57,20 @@ Future runApp() async { ); }); - querySelector('#btEvent') + document + .querySelector('#btEvent') ?.onClick .listen((event) => captureCompleteExampleEvent()); - querySelector('#btMessage')?.onClick.listen((event) => captureMessage()); - querySelector('#btException')?.onClick.listen((event) => captureException()); - querySelector('#btUnhandledException') + document + .querySelector('#btMessage') + ?.onClick + .listen((event) => captureMessage()); + document + .querySelector('#btException') + ?.onClick + .listen((event) => captureException()); + document + .querySelector('#btUnhandledException') ?.onClick .listen((event) => captureUnhandledException()); } @@ -76,7 +84,8 @@ Future captureMessage() async { ); print('capture message result : $sentryId'); if (sentryId != SentryId.empty()) { - querySelector('#messageResult')?.style.display = 'block'; + (document.querySelector('#messageResult') as HTMLElement?)?.style.display = + 'block'; } } @@ -93,13 +102,16 @@ Future captureException() async { print('Capture exception : SentryId: $sentryId'); if (sentryId != SentryId.empty()) { - querySelector('#exceptionResult')?.style.display = 'block'; + (document.querySelector('#exceptionResult') as HTMLElement?) + ?.style + .display = 'block'; } } } Future captureUnhandledException() async { - querySelector('#unhandledResult')?.style.display = 'block'; + (document.querySelector('#unhandledResult') as HTMLElement?)?.style.display = + 'block'; await buildCard(); } @@ -111,7 +123,8 @@ Future captureCompleteExampleEvent() async { print('Response SentryId: $sentryId'); if (sentryId != SentryId.empty()) { - querySelector('#eventResult')?.style.display = 'block'; + (document.querySelector('#eventResult') as HTMLElement?)?.style.display = + 'block'; } } diff --git a/dart/example_web_legacy/.gitignore b/dart/example_web_legacy/.gitignore new file mode 100644 index 0000000000..3d64647b50 --- /dev/null +++ b/dart/example_web_legacy/.gitignore @@ -0,0 +1,9 @@ +# Files and directories created by pub +.dart_tool/ +.packages + +# Conventional directory for build outputs +build/ + +# Directory created by dartdoc +doc/api/ diff --git a/dart/example_web_legacy/README.md b/dart/example_web_legacy/README.md new file mode 100644 index 0000000000..98202566f6 --- /dev/null +++ b/dart/example_web_legacy/README.md @@ -0,0 +1,8 @@ +# Sentry Dart : web example + +```sh +dart pub get + +# run the project ( see https://dart.dev/tools/webdev#serve ) +dart run webdev serve --release +``` diff --git a/dart/example_web_legacy/analysis_options.yaml b/dart/example_web_legacy/analysis_options.yaml new file mode 100644 index 0000000000..be16ace7d1 --- /dev/null +++ b/dart/example_web_legacy/analysis_options.yaml @@ -0,0 +1,5 @@ +include: package:lints/recommended.yaml + +analyzer: + errors: + path_does_not_exist: ignore diff --git a/dart/example_web_legacy/pubspec.yaml b/dart/example_web_legacy/pubspec.yaml new file mode 100644 index 0000000000..49b7807084 --- /dev/null +++ b/dart/example_web_legacy/pubspec.yaml @@ -0,0 +1,17 @@ +name: sentry_dart_web_example +description: An absolute bare-bones web app. + +publish_to: 'none' + +environment: + sdk: '>=2.17.0 <4.0.0' + +dependencies: + sentry: + path: ../../dart/ + +dev_dependencies: + build_runner: ^2.3.0 + build_web_compilers: ^3.2.3 + lints: ^2.0.0 + webdev: ^2.7.0 diff --git a/dart/example_web_legacy/web/event.dart b/dart/example_web_legacy/web/event.dart new file mode 100644 index 0000000000..6e3e8b3e0b --- /dev/null +++ b/dart/example_web_legacy/web/event.dart @@ -0,0 +1,76 @@ +import 'package:sentry/src/protocol.dart'; + +final event = SentryEvent( + logger: 'main', + serverName: 'server.dart', + release: '1.4.0-preview.1', + environment: 'Test', + message: SentryMessage('This is an example Dart event.'), + tags: const {'project-id': '7371'}, + // ignore: deprecated_member_use, deprecated_member_use_from_same_package + extra: const {'section': '1'}, + // fingerprint: const ['example-dart'], + user: SentryUser( + id: '800', + username: 'first-user', + email: 'first@user.lan', + // ipAddress: '127.0.0.1', + data: {'first-sign-in': '2020-01-01'}, + ), + breadcrumbs: [ + Breadcrumb( + message: 'UI Lifecycle', + timestamp: DateTime.now().toUtc(), + category: 'ui.lifecycle', + type: 'navigation', + data: {'screen': 'MainActivity', 'state': 'created'}, + level: SentryLevel.info, + ) + ], + contexts: Contexts( + operatingSystem: const SentryOperatingSystem( + name: 'Android', + version: '5.0.2', + build: 'LRX22G.P900XXS0BPL2', + kernelVersion: + 'Linux version 3.4.39-5726670 (dpi@SWHC3807) (gcc version 4.8 (GCC) ) #1 SMP PREEMPT Thu Dec 1 19:42:39 KST 2016', + rooted: false, + ), + runtimes: [const SentryRuntime(name: 'ART', version: '5')], + app: SentryApp( + name: 'Example Dart App', + version: '1.42.0', + identifier: 'HGT-App-13', + build: '93785', + buildType: 'release', + deviceAppHash: '5afd3a6', + startTime: DateTime.now().toUtc(), + ), + browser: const SentryBrowser(name: 'Firefox', version: '42.0.1'), + device: SentryDevice( + name: 'SM-P900', + family: 'SM-P900', + model: 'SM-P900 (LRX22G)', + modelId: 'LRX22G', + arch: 'armeabi-v7a', + batteryLevel: 99, + orientation: SentryOrientation.landscape, + manufacturer: 'samsung', + brand: 'samsung', + screenDensity: 2.1, + screenDpi: 320, + online: true, + charging: true, + lowMemory: true, + simulator: false, + memorySize: 1500, + freeMemory: 200, + usableMemory: 4294967296, + storageSize: 4294967296, + freeStorage: 2147483648, + externalStorageSize: 8589934592, + externalFreeStorage: 2863311530, + bootTime: DateTime.now().toUtc(), + ), + ), +); diff --git a/dart/example_web_legacy/web/favicon.ico b/dart/example_web_legacy/web/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..7ba349b3e628d2423d4a2ed217422a4722f73739 GIT binary patch literal 3559 zcmV|z)fLATAcZDKyK$JdGY~s=NSr`PnS}BvP$+3A z8CpoogqBhg+p;Cg51fS9@izOF7~1r6zw|?g zDQ!X_8B4l7_wKH=QY>4NwW55uUP;#D-rxP7bI-kdjtU{9Dpi9&%XV3<*GkWK^P@NG zgWRw6Vb?`n$T_Evx_k{$?y0Rh-E#bYD?-UGV3Tc>$SdfYhb2dG)#K`(KPKx z4IwA0_p^z5A4{(AI%=BqUe-mpgFoo&TY*3Gu!0a29lR)aGV2dpEZ4z|Kc)+FUc-bN zHIDPB&TC8HnJ0tyG0*^nmzmQ?TnN+!QqapY^N|7@`F5AqbYw-`02pC0LNbv4yz60?w^9K&j_>533B&I%i9tFNIn5p2kb+@G0y43>@$)ns6>BLG63+2Wpepx zJ&v#ILasL(C%pe{n)2h>g2u-1wVpgKUaNE4V$J76NI&82+j&+}!O~12Z$~FRKK$`9 zx^J3f|L@(w z@^0VL;CU-=w^+ZF9FR4?4ODJ#62DZXnxe`qk)!2S9)0Z%YeH3TkE!aMNY!YE_0LhF z2ESF$qU+kcNYfp>Oq;_Knx0_qs&4=0WPdHW`-Qyher0=jx5gB?QhDMW+Qc1=t$k|< zt=eZtRI`&@>AfXtZFZz?wIfZ37txkUL?4_$0OBvSIr99C2j2UN)Ni@j77k#SApKPq z|7OZGK1&}QM-|70VjJzpQ8hDwD&8DI6m)83lM`v+s(Btdr*I>`(aIvtK1ZDD;A51L zClILKDAJgMZ)-X|x8@2VC+X9BJv40&^lN&j5M^{HDvl4q-~qts09^Y4!n4Ma6_Lw34kz1b@>qe;tZn9VPT9z@k+{b=Lo2to6L3;F~QIz4!D1T|P-qRdf7Z303(CYKm}t10))3j2!;|tzyS7gc;G1rFhS73B&NU|LN;}mYr{eivPfUF zdm~5DreHsX?W>bdsM|qmnE=2HBnZ`V2&GU0HiPHE4BB~d@G=O*FMxyW35}^c+*y^d zu=LHL8rmGaLUn`myIgTKc-?scBq8(@2<4?z0#?C(P6j}(1UFeFC{V&pSs-Nh`dIqC zkq_zKagZ2z+AcRzw=V!dgs?$W0)eov1WLdv*y|LWVW)c@2!awQQ^c0$7^MT+`37Is z%4jsE07!ol4_@%H1b}B@02vS}j=YN~fUrVwC4dzE;VS8yeRqJ(To9x$c>TNqWIDzpRz&Sr zPzjP57~P9Na0}*O4%=_+^52#;fi&rNW3NA+l7688GL>)?AiTgTsszmeR~7(L6O~|@ zzz|qG+3C{n4%C4}E>qpUB(Ws{kV9bm(b{8HL<58sjR2ud0W;XQkP4(=2|ILf=2+pq z(O1(09&`AwG{n*Q)qw$JVxnF zMFb%C2^hk0fN(%m0*265LNmZ)!wN7*KLbbq8UaA{1auJa2wp!^`o#huDPc4NLNR?p zE@mJB=mh`=BfnEomf&3wBwPRh_zkhFA1nrdt00_4bi2$P+KLn!cjN=0CupO3Leg$3 zp*Vm{2>k+tq!Nk%A+NXX^~lmZ}E0)ru(A`q6O1aeT4#SAh5kY%uwe*{*64`?9{h|TK{lms9t zVMO!^gQrlLafwQR&uH5D+yIa;xWn}w$_&dP-ZmCH63kNx)pmez0+e9HK7lI?Lbe@Z zCIIH03!8~Gbn zf+p*Bct|+_8A_;n`y?vsWCSI&<*x)yyDR;;ESm|WDWSu=9V-Fv4K$Kt?D8OWhX~-< z8M4JKx(QsRgh2tq34qYWSpHUUkm|e@h>8u?io3kMt+jNkPo$fU+`TO^E$=_ zAV@2L(Nh=zdBX|I7zlv)vLWhvxn(AR^nQB+a(@#wUK`rQ52NkQchOw{V?Bles;Gnx zuO~1Di)SVo=CHckmenU{((WCK0PvY$@A#*1=j-)CbAeSgo{@WXVb|Yr24@501Of;Q zgQUdn@s6RV_;ctHhZSwHy^XM+5McC+FpA(acq zkST#cFbNRUG6bnF(C#1)tpLs{oldkvBx7pL^j%9 z^aQ|o(0&Tt4lvfjK-P*ds`G^*Gl%u3PGSg&Ms9I z*zZ)`R3{W-EGbbsnIz4z4?~&D2QBA=kRHntC1hrXOE4OI7(xn09lZ7ozLsW{b=7 zbnCtL2cfv(eDh3zWQflPAv+AgOlsk^pSVZR4(AZM7hvEebZwgR987~DJRT$~4t`JN z@IV4P-6z6hXeZ}5TxI0SRjTv?3$ouKS*60hr&tvtLe{uv^Z_W4m}z-GL@GnHGIPk* zw6ctFod^P(OD!y`KXwnJ@4>QqH;FL@i7G0^fC~dyCpy$y;qkr9N%VyCOuRPafGQLB zzxU5Nx5-m}$bfT6kttLODx@M`to1wZ2XmNi7JNd^g%aAUV6e$$mBbisA;#D$#u!)` zw}J0?$bOnExiyeYuJhSrI5vUQ{Xnh5v4#|I^i3@pb{W7_{P2k5GK==kbAYr zd@D&R#;~Cu!m^6Z1Sv9BK^_RF-@KuRkuuEQ=LX6u&}L20<6F-P1JfjkL^$kk*d@$ZG_p zlDS-4dId>x;8Ix))Ft8KEW?C11O-;*xfWL`Qzk1{Ldf+^h!aB1=lxg-30(gpl+6{; zlAp7sn($go>tSNJPRTIkIh2%t4%H;e)d~Xy$^IHbwmS{eULGp}7eC>K>x%RdXHl9i z=pa>P`f>La2+w!sQ%|I9!8C>-&H_}9-U;=8E{GN8praR|_~}w{8h=S2<}S6&1}__C z{K0ykqcUgtgVR>NYFus(0ow+ctv$LRyQjfxf3DtV-(8H>5U@W7MVi`%u=AlE% + + + + + + + + + + + dart_web + + + + + + + + + + +
+ +
+ +
Captured
+
+ +
+ +
Captured
+
+ +
+ +
Captured
+
+ +
+ +
Captured
+
+ + + diff --git a/dart/example_web_legacy/web/main.dart b/dart/example_web_legacy/web/main.dart new file mode 100644 index 0000000000..3034effe9b --- /dev/null +++ b/dart/example_web_legacy/web/main.dart @@ -0,0 +1,135 @@ +import 'dart:async'; +import 'dart:html'; + +import 'package:sentry/sentry.dart'; +import 'package:sentry/src/version.dart'; + +import 'event.dart'; + +// ATTENTION: Change the DSN below with your own to see the events in Sentry. Get one at sentry.io +const dsn = + 'https://e85b375ffb9f43cf8bdf9787768149e0@o447951.ingest.sentry.io/5428562'; + +Future main() async { + await Sentry.init( + (options) => options + ..dsn = dsn + ..debug = true + ..sendDefaultPii = true + ..addEventProcessor(TagEventProcessor()), + appRunner: runApp, + ); +} + +Future runApp() async { + print('runApp'); + + querySelector('#output')?.text = 'Your Dart app is running.'; + + await Sentry.addBreadcrumb( + Breadcrumb( + message: 'Authenticated user', + category: 'auth', + type: 'debug', + data: { + 'admin': true, + 'permissions': [1, 2, 3] + }, + ), + ); + + await Sentry.configureScope((scope) async { + scope + // ..fingerprint = ['example-dart'] + ..transaction = '/example/app' + ..level = SentryLevel.warning; + await scope.setTag('build', '579'); + await scope.setExtra('company-name', 'Dart Inc'); + + await scope.setUser( + SentryUser( + id: '800', + username: 'first-user', + email: 'first@user.lan', + // ipAddress: '127.0.0.1', + data: {'first-sign-in': '2020-01-01'}, + ), + ); + }); + + querySelector('#btEvent') + ?.onClick + .listen((event) => captureCompleteExampleEvent()); + querySelector('#btMessage')?.onClick.listen((event) => captureMessage()); + querySelector('#btException')?.onClick.listen((event) => captureException()); + querySelector('#btUnhandledException') + ?.onClick + .listen((event) => captureUnhandledException()); +} + +Future captureMessage() async { + print('Capturing Message : '); + final sentryId = await Sentry.captureMessage( + 'Message 2', + template: 'Message %s', + params: ['2'], + ); + print('capture message result : $sentryId'); + if (sentryId != SentryId.empty()) { + querySelector('#messageResult')?.style.display = 'block'; + } +} + +Future captureException() async { + try { + await buildCard(); + } catch (error, stackTrace) { + print('\nReporting the following stack trace: '); + final sentryId = await Sentry.captureException( + error, + stackTrace: stackTrace, + ); + + print('Capture exception : SentryId: $sentryId'); + + if (sentryId != SentryId.empty()) { + querySelector('#exceptionResult')?.style.display = 'block'; + } + } +} + +Future captureUnhandledException() async { + querySelector('#unhandledResult')?.style.display = 'block'; + + await buildCard(); +} + +Future captureCompleteExampleEvent() async { + print('\nReporting a complete event example: $sdkName'); + final sentryId = await Sentry.captureEvent(event); + + print('Response SentryId: $sentryId'); + + if (sentryId != SentryId.empty()) { + querySelector('#eventResult')?.style.display = 'block'; + } +} + +Future buildCard() async { + await loadData(); +} + +Future loadData() async { + await parseData(); +} + +Future parseData() async { + throw StateError('This is a test error'); +} + +class TagEventProcessor implements EventProcessor { + @override + SentryEvent? apply(SentryEvent event, Hint hint) { + return event..tags?.addAll({'page-locale': 'en-us'}); + } +} diff --git a/dart/example_web_legacy/web/styles.css b/dart/example_web_legacy/web/styles.css new file mode 100644 index 0000000000..cc035c95c9 --- /dev/null +++ b/dart/example_web_legacy/web/styles.css @@ -0,0 +1,14 @@ +@import url(https://fonts.googleapis.com/css?family=Roboto); + +html, body { + width: 100%; + height: 100%; + margin: 0; + padding: 0; + font-family: 'Roboto', sans-serif; +} + +#output { + padding: 20px; + text-align: center; +} diff --git a/dart/lib/src/environment/environment_variables.dart b/dart/lib/src/environment/environment_variables.dart index 916cdea47d..3dcb1674b3 100644 --- a/dart/lib/src/environment/environment_variables.dart +++ b/dart/lib/src/environment/environment_variables.dart @@ -1,6 +1,7 @@ import '../platform_checker.dart'; import '_io_environment_variables.dart' - if (dart.library.html) '_web_environment_variables.dart' as env; + if (dart.library.html) '_web_environment_variables.dart' + if (dart.library.js_interop) '_web_environment_variables.dart' as env; /// Reads environment variables from the system. /// In an Flutter environment these can be set via diff --git a/dart/lib/src/event_processor/enricher/enricher_event_processor.dart b/dart/lib/src/event_processor/enricher/enricher_event_processor.dart index 78d19738bd..779d64b700 100644 --- a/dart/lib/src/event_processor/enricher/enricher_event_processor.dart +++ b/dart/lib/src/event_processor/enricher/enricher_event_processor.dart @@ -1,7 +1,8 @@ import '../../event_processor.dart'; import '../../sentry_options.dart'; import 'io_enricher_event_processor.dart' - if (dart.library.html) 'web_enricher_event_processor.dart'; + if (dart.library.html) 'html_enricher_event_processor.dart' + if (dart.library.js_interop) 'web_enricher_event_processor.dart'; abstract class EnricherEventProcessor implements EventProcessor { factory EnricherEventProcessor(SentryOptions options) => diff --git a/dart/lib/src/event_processor/enricher/html_enricher_event_processor.dart b/dart/lib/src/event_processor/enricher/html_enricher_event_processor.dart new file mode 100644 index 0000000000..e51cff4b71 --- /dev/null +++ b/dart/lib/src/event_processor/enricher/html_enricher_event_processor.dart @@ -0,0 +1,103 @@ +import 'dart:html' as html show window, Window; + +import '../../../sentry.dart'; +import 'enricher_event_processor.dart'; + +EnricherEventProcessor enricherEventProcessor(SentryOptions options) { + return WebEnricherEventProcessor( + html.window, + options, + ); +} + +class WebEnricherEventProcessor implements EnricherEventProcessor { + WebEnricherEventProcessor( + this._window, + this._options, + ); + + final html.Window _window; + + final SentryOptions _options; + + @override + SentryEvent? apply(SentryEvent event, Hint hint) { + // Web has no native integration, so no need to check for it + + final contexts = event.contexts.copyWith( + device: _getDevice(event.contexts.device), + culture: _getSentryCulture(event.contexts.culture), + ); + + contexts['dart_context'] = _getDartContext(); + + return event.copyWith( + contexts: contexts, + request: _getRequest(event.request), + transaction: event.transaction ?? _window.location.pathname, + ); + } + + // As seen in + // https://github.com/getsentry/sentry-javascript/blob/a6f8dc26a4c7ae2146ae64995a2018c8578896a6/packages/browser/src/integrations/useragent.ts + SentryRequest _getRequest(SentryRequest? request) { + final requestHeader = request?.headers; + final header = requestHeader == null + ? {} + : Map.from(requestHeader); + + header.putIfAbsent('User-Agent', () => _window.navigator.userAgent); + + final url = request?.url ?? _window.location.toString(); + return (request ?? SentryRequest(url: url)) + .copyWith(headers: header) + .sanitized(); + } + + SentryDevice _getDevice(SentryDevice? device) { + return (device ?? SentryDevice()).copyWith( + online: device?.online ?? _window.navigator.onLine, + memorySize: device?.memorySize ?? _getMemorySize(), + orientation: device?.orientation ?? _getScreenOrientation(), + screenHeightPixels: device?.screenHeightPixels ?? + _window.screen?.available.height.toInt(), + screenWidthPixels: + device?.screenWidthPixels ?? _window.screen?.available.width.toInt(), + screenDensity: + device?.screenDensity ?? _window.devicePixelRatio.toDouble(), + ); + } + + int? _getMemorySize() { + // https://developer.mozilla.org/en-US/docs/Web/API/Navigator/deviceMemory + final size = _window.navigator.deviceMemory?.toDouble(); + final memoryByteSize = size != null ? size * 1024 * 1024 * 1024 : null; + return memoryByteSize?.toInt(); + } + + SentryOrientation? _getScreenOrientation() { + // https://developer.mozilla.org/en-US/docs/Web/API/ScreenOrientation + final screenOrientation = _window.screen?.orientation; + if (screenOrientation != null) { + if (screenOrientation.type?.startsWith('portrait') ?? false) { + return SentryOrientation.portrait; + } + if (screenOrientation.type?.startsWith('landscape') ?? false) { + return SentryOrientation.landscape; + } + } + return null; + } + + Map _getDartContext() { + return { + 'compile_mode': _options.platformChecker.compileMode, + }; + } + + SentryCulture _getSentryCulture(SentryCulture? culture) { + return (culture ?? SentryCulture()).copyWith( + timezone: culture?.timezone ?? DateTime.now().timeZoneName, + ); + } +} diff --git a/dart/lib/src/event_processor/enricher/web_enricher_event_processor.dart b/dart/lib/src/event_processor/enricher/web_enricher_event_processor.dart index e51cff4b71..d6d588ac0a 100644 --- a/dart/lib/src/event_processor/enricher/web_enricher_event_processor.dart +++ b/dart/lib/src/event_processor/enricher/web_enricher_event_processor.dart @@ -1,11 +1,13 @@ -import 'dart:html' as html show window, Window; +// We would lose compatibility with old dart versions by adding web to pubspec. +// ignore: depend_on_referenced_packages +import 'package:web/web.dart' as web show window, Window, Navigator; import '../../../sentry.dart'; import 'enricher_event_processor.dart'; EnricherEventProcessor enricherEventProcessor(SentryOptions options) { return WebEnricherEventProcessor( - html.window, + web.window, options, ); } @@ -16,7 +18,7 @@ class WebEnricherEventProcessor implements EnricherEventProcessor { this._options, ); - final html.Window _window; + final web.Window _window; final SentryOptions _options; @@ -59,10 +61,9 @@ class WebEnricherEventProcessor implements EnricherEventProcessor { online: device?.online ?? _window.navigator.onLine, memorySize: device?.memorySize ?? _getMemorySize(), orientation: device?.orientation ?? _getScreenOrientation(), - screenHeightPixels: device?.screenHeightPixels ?? - _window.screen?.available.height.toInt(), - screenWidthPixels: - device?.screenWidthPixels ?? _window.screen?.available.width.toInt(), + screenHeightPixels: + device?.screenHeightPixels ?? _window.screen.availHeight, + screenWidthPixels: device?.screenWidthPixels ?? _window.screen.availWidth, screenDensity: device?.screenDensity ?? _window.devicePixelRatio.toDouble(), ); @@ -77,14 +78,12 @@ class WebEnricherEventProcessor implements EnricherEventProcessor { SentryOrientation? _getScreenOrientation() { // https://developer.mozilla.org/en-US/docs/Web/API/ScreenOrientation - final screenOrientation = _window.screen?.orientation; - if (screenOrientation != null) { - if (screenOrientation.type?.startsWith('portrait') ?? false) { - return SentryOrientation.portrait; - } - if (screenOrientation.type?.startsWith('landscape') ?? false) { - return SentryOrientation.landscape; - } + final screenOrientation = _window.screen.orientation; + if (screenOrientation.type.startsWith('portrait')) { + return SentryOrientation.portrait; + } + if (screenOrientation.type.startsWith('landscape')) { + return SentryOrientation.landscape; } return null; } @@ -101,3 +100,7 @@ class WebEnricherEventProcessor implements EnricherEventProcessor { ); } } + +extension on web.Navigator { + external double? get deviceMemory; +} diff --git a/dart/lib/src/event_processor/exception/exception_event_processor.dart b/dart/lib/src/event_processor/exception/exception_event_processor.dart index e928f476f0..ab4f5e9878 100644 --- a/dart/lib/src/event_processor/exception/exception_event_processor.dart +++ b/dart/lib/src/event_processor/exception/exception_event_processor.dart @@ -1,7 +1,8 @@ import '../../event_processor.dart'; import '../../sentry_options.dart'; import 'io_exception_event_processor.dart' - if (dart.library.html) 'web_exception_event_processor.dart'; + if (dart.library.html) 'web_exception_event_processor.dart' + if (dart.library.js_interop) 'web_exception_event_processor.dart'; abstract class ExceptionEventProcessor implements EventProcessor { factory ExceptionEventProcessor(SentryOptions options) => diff --git a/dart/lib/src/origin.dart b/dart/lib/src/origin.dart index ed1e066c5e..1d5b3dc4bf 100644 --- a/dart/lib/src/origin.dart +++ b/dart/lib/src/origin.dart @@ -1,4 +1,3 @@ -import 'dart:html'; - -/// request origin, used for browser stacktrace -String get eventOrigin => '${window.location.origin}/'; +export 'origin_io.dart' + if (dart.library.html) 'origin_html.dart' + if (dart.library.js_interop) 'origin_web.dart'; diff --git a/dart/lib/src/origin_html.dart b/dart/lib/src/origin_html.dart new file mode 100644 index 0000000000..ed1e066c5e --- /dev/null +++ b/dart/lib/src/origin_html.dart @@ -0,0 +1,4 @@ +import 'dart:html'; + +/// request origin, used for browser stacktrace +String get eventOrigin => '${window.location.origin}/'; diff --git a/dart/lib/src/noop_origin.dart b/dart/lib/src/origin_io.dart similarity index 100% rename from dart/lib/src/noop_origin.dart rename to dart/lib/src/origin_io.dart diff --git a/dart/lib/src/origin_web.dart b/dart/lib/src/origin_web.dart new file mode 100644 index 0000000000..db99f33c56 --- /dev/null +++ b/dart/lib/src/origin_web.dart @@ -0,0 +1,6 @@ +// We would lose compatibility with old dart versions by adding web to pubspec. +// ignore: depend_on_referenced_packages +import 'package:web/web.dart'; + +/// request origin, used for browser stacktrace +String get eventOrigin => '${window.location.origin}/'; diff --git a/dart/lib/src/platform/_html_platform.dart b/dart/lib/src/platform/_html_platform.dart new file mode 100644 index 0000000000..d3fa84eed9 --- /dev/null +++ b/dart/lib/src/platform/_html_platform.dart @@ -0,0 +1,51 @@ +import 'dart:html' as html; +import 'platform.dart'; + +const Platform instance = WebPlatform(); + +/// [Platform] implementation that delegates to `dart:html`. +class WebPlatform extends Platform { + /// Creates a new [Platform]. + const WebPlatform(); + + @override + String get operatingSystem => _browserPlatform(); + + @override + String get operatingSystemVersion => 'unknown'; + + @override + String get localHostname => html.window.location.hostname ?? 'unknown'; + + String _browserPlatform() { + final navigatorPlatform = + html.window.navigator.platform?.toLowerCase() ?? ''; + if (navigatorPlatform.startsWith('mac')) { + return 'macos'; + } + if (navigatorPlatform.startsWith('win')) { + return 'windows'; + } + if (navigatorPlatform.contains('iphone') || + navigatorPlatform.contains('ipad') || + navigatorPlatform.contains('ipod')) { + return 'ios'; + } + if (navigatorPlatform.contains('android')) { + return 'android'; + } + if (navigatorPlatform.contains('fuchsia')) { + return 'fuchsia'; + } + + // Since some phones can report a window.navigator.platform as Linux, fall + // back to use CSS to disambiguate Android vs Linux desktop. If the CSS + // indicates that a device has a "fine pointer" (mouse) as the primary + // pointing device, then we'll assume desktop linux, and otherwise we'll + // assume Android. + if (html.window.matchMedia('only screen and (pointer: fine)').matches) { + return 'linux'; + } + return 'android'; + } +} diff --git a/dart/lib/src/platform/_web_platform.dart b/dart/lib/src/platform/_web_platform.dart index d3fa84eed9..da403b254d 100644 --- a/dart/lib/src/platform/_web_platform.dart +++ b/dart/lib/src/platform/_web_platform.dart @@ -1,9 +1,12 @@ -import 'dart:html' as html; +// We would lose compatibility with old dart versions by adding web to pubspec. +// ignore: depend_on_referenced_packages +import 'package:web/web.dart' as web; + import 'platform.dart'; const Platform instance = WebPlatform(); -/// [Platform] implementation that delegates to `dart:html`. +/// [Platform] implementation that delegates to `dart:web`. class WebPlatform extends Platform { /// Creates a new [Platform]. const WebPlatform(); @@ -15,11 +18,10 @@ class WebPlatform extends Platform { String get operatingSystemVersion => 'unknown'; @override - String get localHostname => html.window.location.hostname ?? 'unknown'; + String get localHostname => web.window.location.hostname; String _browserPlatform() { - final navigatorPlatform = - html.window.navigator.platform?.toLowerCase() ?? ''; + final navigatorPlatform = web.window.navigator.platform.toLowerCase(); if (navigatorPlatform.startsWith('mac')) { return 'macos'; } @@ -43,7 +45,7 @@ class WebPlatform extends Platform { // indicates that a device has a "fine pointer" (mouse) as the primary // pointing device, then we'll assume desktop linux, and otherwise we'll // assume Android. - if (html.window.matchMedia('only screen and (pointer: fine)').matches) { + if (web.window.matchMedia('only screen and (pointer: fine)').matches) { return 'linux'; } return 'android'; diff --git a/dart/lib/src/platform/platform.dart b/dart/lib/src/platform/platform.dart index 8f6d0760e8..dffd3e81fd 100644 --- a/dart/lib/src/platform/platform.dart +++ b/dart/lib/src/platform/platform.dart @@ -1,5 +1,6 @@ -import '_io_platform.dart' if (dart.library.html) '_web_platform.dart' - as platform; +import '_io_platform.dart' + if (dart.library.html) '_html_platform.dart' + if (dart.library.js_interop) '_web_platform.dart' as platform; const Platform instance = platform.instance; diff --git a/dart/lib/src/sentry_client_stub.dart b/dart/lib/src/sentry_client_stub.dart deleted file mode 100644 index e212b39a0d..0000000000 --- a/dart/lib/src/sentry_client_stub.dart +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'sentry_client.dart'; -import 'sentry_options.dart'; - -/// Implemented in `sentry_browser_client.dart` and `sentry_io_client.dart`. -SentryClient createSentryClient(SentryOptions options) => - throw UnsupportedError( - 'Cannot create a client without dart:html or dart:io.'); diff --git a/dart/lib/src/sentry_stack_trace_factory.dart b/dart/lib/src/sentry_stack_trace_factory.dart index 9d4a42bffc..25a97e6eab 100644 --- a/dart/lib/src/sentry_stack_trace_factory.dart +++ b/dart/lib/src/sentry_stack_trace_factory.dart @@ -1,7 +1,7 @@ import 'package:meta/meta.dart'; import 'package:stack_trace/stack_trace.dart'; -import 'noop_origin.dart' if (dart.library.html) 'origin.dart'; +import 'origin.dart'; import 'protocol.dart'; import 'sentry_options.dart'; diff --git a/dart/lib/src/utils/isolate_utils.dart b/dart/lib/src/utils/isolate_utils.dart index 3e9c4b20bc..6575965ff9 100644 --- a/dart/lib/src/utils/isolate_utils.dart +++ b/dart/lib/src/utils/isolate_utils.dart @@ -1,7 +1,8 @@ import 'package:meta/meta.dart'; import '_io_get_isolate_name.dart' - if (dart.library.html) '_web_get_isolate_name.dart' as isolate_getter; + if (dart.library.html) '_web_get_isolate_name.dart' + if (dart.library.js_interop) '_web_get_isolate_name.dart' as isolate_getter; @internal String? getIsolateName() => isolate_getter.getIsolateName(); diff --git a/dart/pubspec.yaml b/dart/pubspec.yaml index 41aa1b7d0c..9e63a7b079 100644 --- a/dart/pubspec.yaml +++ b/dart/pubspec.yaml @@ -26,11 +26,12 @@ dependencies: uuid: '>=3.0.0 <5.0.0' dev_dependencies: - build_runner: ^2.4.2 + build_runner: ^2.3.0 mockito: ^5.1.0 - lints: ^4.0.0 + lints: '>=2.0.0 <5.0.0' test: ^1.21.1 yaml: ^3.1.0 # needed for version match (code and pubspec) collection: ^1.16.0 coverage: ^1.3.0 intl: '>=0.17.0 <1.0.0' + version: ^3.0.2 diff --git a/dart/test/event_processor/enricher/web_enricher_test.dart b/dart/test/event_processor/enricher/web_enricher_test.dart index cdc7310fab..d2590a09fa 100644 --- a/dart/test/event_processor/enricher/web_enricher_test.dart +++ b/dart/test/event_processor/enricher/web_enricher_test.dart @@ -1,10 +1,10 @@ @TestOn('browser') library dart_test; -import 'dart:html' as html; - import 'package:sentry/sentry.dart'; -import 'package:sentry/src/event_processor/enricher/web_enricher_event_processor.dart'; +import 'package:sentry/src/event_processor/enricher/html_enricher_event_processor.dart' + if (dart.library.html) 'package:sentry/src/event_processor/enricher/html_enricher_event_processor.dart' + if (dart.library.js_interop) 'package:sentry/src/event_processor/enricher/web_enricher_event_processor.dart'; import 'package:test/test.dart'; import '../../mocks.dart'; @@ -193,10 +193,8 @@ void main() { ); await Sentry.close(); - final ioEnricherCount = sentryOptions.eventProcessors - .whereType() - .length; - expect(ioEnricherCount, 1); + expect(sentryOptions.eventProcessors.map((e) => e.runtimeType.toString()), + contains('$WebEnricherEventProcessor')); }); }); } @@ -206,10 +204,6 @@ class Fixture { final options = SentryOptions( dsn: fakeDsn, checker: MockPlatformChecker(hasNativeIntegration: false)); - - return WebEnricherEventProcessor( - html.window, - options, - ); + return enricherEventProcessor(options) as WebEnricherEventProcessor; } } diff --git a/dart/test/example_web_compile_test.dart b/dart/test/example_web_compile_test.dart index 4199a47dda..1a2a0cf13f 100644 --- a/dart/test/example_web_compile_test.dart +++ b/dart/test/example_web_compile_test.dart @@ -5,29 +5,35 @@ import 'dart:async'; import 'dart:convert'; import 'dart:io'; +import 'package:version/version.dart'; import 'package:test/test.dart'; // Tests for the following issue // https://github.com/getsentry/sentry-dart/issues/1893 void main() { - group('Compile example_web', () { + final dartVersion = Version.parse(Platform.version.split(' ')[0]); + final isLegacy = dartVersion < Version.parse('3.3.0'); + final exampleAppDir = isLegacy ? 'example_web_legacy' : 'example_web'; + final exampleAppWorkingDir = + '${Directory.current.path}${Platform.pathSeparator}$exampleAppDir'; + group('Compile $exampleAppDir', () { test( 'dart pub get and compilation should run successfully', () async { final result = await _runProcess('dart pub get', - workingDirectory: _exampleWebWorkingDir); + workingDirectory: exampleAppWorkingDir); expect(result.exitCode, 0, - reason: 'Could run `dart pub get` for example_web. ' + reason: 'Could run `dart pub get` for $exampleAppDir. ' 'Likely caused by outdated dependencies'); // running this test locally require clean working directory final cleanResult = await _runProcess('dart run build_runner clean', - workingDirectory: _exampleWebWorkingDir); + workingDirectory: exampleAppWorkingDir); expect(cleanResult.exitCode, 0); final compileResult = await _runProcess( 'dart run build_runner build -r web -o build --delete-conflicting-outputs', - workingDirectory: _exampleWebWorkingDir); + workingDirectory: exampleAppWorkingDir); expect(compileResult.exitCode, 0, - reason: 'Could not compile example_web project'); + reason: 'Could not compile $exampleAppDir project'); expect( compileResult.stdout, isNot(contains( @@ -36,8 +42,9 @@ void main() { 'Could not compile main.dart, likely because of dart:io import.'); expect( compileResult.stdout, - contains( - 'build_web_compilers:entrypoint on web/main.dart:Compiled')); + contains(isLegacy + ? 'Succeeded after ' + : 'build_web_compilers:entrypoint on web/main.dart:Compiled')); }, timeout: Timeout(const Duration(minutes: 1)), // double of detault timeout ); @@ -76,10 +83,6 @@ Future<_CommandResult> _runProcess(String command, return _CommandResult(exitCode: exitCode, stdout: processOut); } -String get _exampleWebWorkingDir { - return '${Directory.current.path}${Platform.pathSeparator}example_web'; -} - class _CommandResult { final int exitCode; final String stdout; diff --git a/dart/test/sentry_client_test.dart b/dart/test/sentry_client_test.dart index b8c6bee716..153c1515f0 100644 --- a/dart/test/sentry_client_test.dart +++ b/dart/test/sentry_client_test.dart @@ -139,7 +139,10 @@ void main() { capturedEvent.threads?.first.id, ); }, - onPlatform: {'js': Skip("Isolates don't exist on the web")}, + onPlatform: { + 'js': Skip("Isolates don't exist on the web"), + 'wasm': Skip("Isolates don't exist on the web") + }, ); test( diff --git a/dart/test/stack_trace_test.dart b/dart/test/stack_trace_test.dart index 6524581794..3ab8f9d116 100644 --- a/dart/test/stack_trace_test.dart +++ b/dart/test/stack_trace_test.dart @@ -3,8 +3,7 @@ // found in the LICENSE file. import 'package:sentry/sentry.dart'; -import 'package:sentry/src/noop_origin.dart' - if (dart.library.html) 'package:sentry/src/origin.dart'; +import 'package:sentry/src/origin.dart'; import 'package:sentry/src/sentry_stack_trace_factory.dart'; import 'package:stack_trace/stack_trace.dart'; import 'package:test/test.dart'; diff --git a/dart/test/test_utils.dart b/dart/test/test_utils.dart index 627d19903d..87a0be0f0a 100644 --- a/dart/test/test_utils.dart +++ b/dart/test/test_utils.dart @@ -117,6 +117,11 @@ Future testCaptureException( final topFrame = (stacktrace['frames'] as Iterable).last as Map; + if (topFrame['function'].contains('browser_test.dart.wasm')) { + // TODO stacktrace parsing for wasm is not implemented yet + // {filename: unparsed, function: at testCaptureException (http://localhost:59959/9R3KYfjvkWCySr4h2hI0pVO7PqmPFeE6/test/sentry_browser_test.dart.browser_test.dart.wasm:wasm-function[1007]:0x4bc18), abs_path: http://localhost:59959/unparsed, in_app: true} + return; + } expect( topFrame.keys, ['filename', 'function', 'lineno', 'colno', 'abs_path', 'in_app'], diff --git a/file/lib/src/sentry_file_extension.dart b/file/lib/src/sentry_file_extension.dart index f6f0c70de2..3cc764c36e 100644 --- a/file/lib/src/sentry_file_extension.dart +++ b/file/lib/src/sentry_file_extension.dart @@ -1,6 +1,8 @@ // ignore_for_file: invalid_use_of_internal_member -import 'dart:io' if (dart.library.html) 'dart:html'; +import 'dart:io' + if (dart.library.html) 'dart:html' + if (dart.library.js_interop) 'dart:js_interop'; import 'package:meta/meta.dart'; import 'package:sentry/sentry.dart'; diff --git a/flutter/lib/src/integrations/connectivity/connectivity_provider.dart b/flutter/lib/src/integrations/connectivity/connectivity_provider.dart index 30095dda0d..ea27f80f72 100644 --- a/flutter/lib/src/integrations/connectivity/connectivity_provider.dart +++ b/flutter/lib/src/integrations/connectivity/connectivity_provider.dart @@ -1,5 +1,6 @@ import 'noop_connectivity_provider.dart' - if (dart.library.html) 'web_connectivity_provider.dart'; + if (dart.library.html) 'html_connectivity_provider.dart' + if (dart.library.js_interop) 'web_connectivity_provider.dart'; abstract class ConnectivityProvider { factory ConnectivityProvider() => connectivityProvider(); diff --git a/flutter/lib/src/integrations/connectivity/html_connectivity_provider.dart b/flutter/lib/src/integrations/connectivity/html_connectivity_provider.dart new file mode 100644 index 0000000000..34d0e0ab42 --- /dev/null +++ b/flutter/lib/src/integrations/connectivity/html_connectivity_provider.dart @@ -0,0 +1,32 @@ +import 'dart:async'; +import 'dart:html' as html; + +import 'connectivity_provider.dart'; + +ConnectivityProvider connectivityProvider() { + return WebConnectivityProvider(); +} + +class WebConnectivityProvider implements ConnectivityProvider { + StreamSubscription? _onOnlineSub; + StreamSubscription? _onOfflineSub; + + @override + void listen(void Function(String connectivity) onChange) { + _onOnlineSub = html.window.onOnline.listen((_) { + onChange('wifi'); + }); + _onOfflineSub = html.window.onOffline.listen((_) { + onChange('none'); + }); + } + + @override + void cancel() { + _onOnlineSub?.cancel(); + _onOnlineSub = null; + + _onOfflineSub?.cancel(); + _onOfflineSub = null; + } +} diff --git a/flutter/lib/src/integrations/connectivity/web_connectivity_provider.dart b/flutter/lib/src/integrations/connectivity/web_connectivity_provider.dart index 34d0e0ab42..d1c18af777 100644 --- a/flutter/lib/src/integrations/connectivity/web_connectivity_provider.dart +++ b/flutter/lib/src/integrations/connectivity/web_connectivity_provider.dart @@ -1,5 +1,8 @@ import 'dart:async'; -import 'dart:html' as html; + +// We would lose compatibility with old dart versions by adding web to pubspec. +// ignore: depend_on_referenced_packages +import 'package:web/web.dart' as web; import 'connectivity_provider.dart'; @@ -8,15 +11,19 @@ ConnectivityProvider connectivityProvider() { } class WebConnectivityProvider implements ConnectivityProvider { - StreamSubscription? _onOnlineSub; - StreamSubscription? _onOfflineSub; + StreamSubscription? _onOnlineSub; + StreamSubscription? _onOfflineSub; @override void listen(void Function(String connectivity) onChange) { - _onOnlineSub = html.window.onOnline.listen((_) { + _onOnlineSub = web.EventStreamProviders.onlineEvent + .forElement(web.document.body!) + .listen((_) { onChange('wifi'); }); - _onOfflineSub = html.window.onOffline.listen((_) { + _onOfflineSub = web.EventStreamProviders.offlineEvent + .forElement(web.document.body!) + .listen((_) { onChange('none'); }); } diff --git a/flutter/lib/src/native/factory.dart b/flutter/lib/src/native/factory.dart index 981e1d6ead..c81c526594 100644 --- a/flutter/lib/src/native/factory.dart +++ b/flutter/lib/src/native/factory.dart @@ -1 +1,3 @@ -export 'factory_real.dart' if (dart.library.html) 'factory_web.dart'; +export 'factory_real.dart' + if (dart.library.html) 'factory_web.dart' + if (dart.library.js_interop) 'factory_web.dart'; diff --git a/flutter/lib/src/renderer/renderer.dart b/flutter/lib/src/renderer/renderer.dart index 3e41eced70..dc9d81276b 100644 --- a/flutter/lib/src/renderer/renderer.dart +++ b/flutter/lib/src/renderer/renderer.dart @@ -2,6 +2,7 @@ import 'package:meta/meta.dart'; import 'unknown_renderer.dart' if (dart.library.html) 'html_renderer.dart' + if (dart.library.js_interop) 'web_renderer.dart' if (dart.library.io) 'io_renderer.dart' as implementation; @internal diff --git a/flutter/lib/src/renderer/web_renderer.dart b/flutter/lib/src/renderer/web_renderer.dart new file mode 100644 index 0000000000..6baa3ca8b4 --- /dev/null +++ b/flutter/lib/src/renderer/web_renderer.dart @@ -0,0 +1,18 @@ +import 'dart:js_interop'; + +import 'renderer.dart'; + +FlutterRenderer? getRenderer() { + return isCanvasKitRenderer ? FlutterRenderer.canvasKit : FlutterRenderer.html; +} + +bool get isCanvasKitRenderer { + return _windowFlutterCanvasKit != null; +} + +// These values are set by the engine. They are used to determine if the +// application is using canvaskit or skwasm. +// +// See https://github.com/flutter/flutter/blob/414d9238720a3cde85475f49ce0ba313f95046f7/packages/flutter/lib/src/foundation/_capabilities_web.dart#L10 +@JS('window.flutterCanvasKit') +external JSAny? get _windowFlutterCanvasKit; diff --git a/hive/lib/src/sentry_box_collection.dart b/hive/lib/src/sentry_box_collection.dart index d4c605efe2..0dee9e9831 100644 --- a/hive/lib/src/sentry_box_collection.dart +++ b/hive/lib/src/sentry_box_collection.dart @@ -10,6 +10,7 @@ import 'package:hive/src/box_collection/box_collection_stub.dart' as stub; // ignore: implementation_imports import 'package:hive/src/box_collection/box_collection_stub.dart' if (dart.library.html) 'package:hive/src/box_collection/box_collection_indexed_db.dart' + if (dart.library.js_interop) 'package:hive/src/box_collection/box_collection_indexed_db.dart' if (dart.library.io) 'package:hive/src/box_collection/box_collection.dart' as impl; diff --git a/hive/test/mocks/mocks.dart b/hive/test/mocks/mocks.dart index 9b2db0e30d..8b6d7f4db9 100644 --- a/hive/test/mocks/mocks.dart +++ b/hive/test/mocks/mocks.dart @@ -4,6 +4,7 @@ import 'package:sentry/sentry.dart'; import 'package:hive/src/box_collection/box_collection_stub.dart' if (dart.library.html) 'package:hive/src/box_collection/box_collection_indexed_db.dart' + if (dart.library.js_interop) 'package:hive/src/box_collection/box_collection_indexed_db.dart' if (dart.library.io) 'package:hive/src/box_collection/box_collection.dart' as impl; diff --git a/hive/test/mocks/mocks.mocks.dart b/hive/test/mocks/mocks.mocks.dart index 6d1bb907d7..5cd8fc7e30 100644 --- a/hive/test/mocks/mocks.mocks.dart +++ b/hive/test/mocks/mocks.mocks.dart @@ -18,6 +18,7 @@ import 'package:hive/src/box_collection/box_collection_stub.dart' as stub; // ignore: implementation_imports import 'package:hive/src/box_collection/box_collection_stub.dart' if (dart.library.html) 'package:hive/src/box_collection/box_collection_indexed_db.dart' + if (dart.library.js_interop) 'package:hive/src/box_collection/box_collection_indexed_db.dart' if (dart.library.io) 'package:hive/src/box_collection/box_collection.dart' as impl; diff --git a/min_version_test/lib/main.dart b/min_version_test/lib/main.dart index 72a8aea404..504c706a43 100644 --- a/min_version_test/lib/main.dart +++ b/min_version_test/lib/main.dart @@ -1,8 +1,9 @@ import 'package:flutter/material.dart'; -import 'package:min_version_test/transaction/transaction_locator.dart' - if (dart.library.html) 'package:min_version_test/transaction/file_transaction.dart' - if (dart.library.io) 'package:min_version_test/transaction/web_transaction.dart'; +import 'package:min_version_test/transaction/transaction_stub.dart' + if (dart.library.html) 'package:min_version_test/transaction/web_transaction.dart' + if (dart.library.js_interop) 'package:min_version_test/transaction/web_transaction.dart' + if (dart.library.io) 'package:min_version_test/transaction/file_transaction.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:sentry_logging/sentry_logging.dart'; diff --git a/min_version_test/lib/transaction/file_transaction.dart b/min_version_test/lib/transaction/file_transaction.dart index 6f85ddc337..5afa62f6ce 100644 --- a/min_version_test/lib/transaction/file_transaction.dart +++ b/min_version_test/lib/transaction/file_transaction.dart @@ -1,12 +1,12 @@ -import 'package:min_version_test/transaction/transaction.dart'; import 'dart:io'; import 'package:logging/logging.dart'; import 'package:dio/dio.dart'; - import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:sentry_dio/sentry_dio.dart'; +import 'transaction.dart'; + class FileTransaction implements Transaction { @override Future start() async { diff --git a/min_version_test/lib/transaction/transaction_locator.dart b/min_version_test/lib/transaction/transaction_stub.dart similarity index 60% rename from min_version_test/lib/transaction/transaction_locator.dart rename to min_version_test/lib/transaction/transaction_stub.dart index 7e3a3f75d5..1869f2ee17 100644 --- a/min_version_test/lib/transaction/transaction_locator.dart +++ b/min_version_test/lib/transaction/transaction_stub.dart @@ -1,4 +1,4 @@ -import 'package:min_version_test/transaction/transaction.dart'; +import 'transaction.dart'; Transaction getTransaction() => throw UnsupportedError('Cannot create sample transaction.'); diff --git a/min_version_test/lib/transaction/web_transaction.dart b/min_version_test/lib/transaction/web_transaction.dart index 99ce8f3508..03c8cdd368 100644 --- a/min_version_test/lib/transaction/web_transaction.dart +++ b/min_version_test/lib/transaction/web_transaction.dart @@ -1,11 +1,10 @@ -import 'package:min_version_test/transaction/transaction.dart'; - import 'package:logging/logging.dart'; import 'package:dio/dio.dart'; - import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:sentry_dio/sentry_dio.dart'; +import 'transaction.dart'; + class WebTransaction implements Transaction { @override Future start() async { diff --git a/min_version_test/pubspec.yaml b/min_version_test/pubspec.yaml index 8fdfe47329..e8e76dc9df 100644 --- a/min_version_test/pubspec.yaml +++ b/min_version_test/pubspec.yaml @@ -91,4 +91,3 @@ flutter: # # For details regarding fonts from package dependencies, # see https://flutter.dev/custom-fonts/#from-packages - \ No newline at end of file From acbd5d337084ff1876a793d78161d7c4fb9e1f6d Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Tue, 25 Jun 2024 14:00:39 +0200 Subject: [PATCH 224/237] feat(performance): report total frames, frame delay, slow & frozen frames (#2106) * Add frame tracking option * Current state * Update * Update * Update * Update * Update * Update Changelog * Update * update * Format * Update * Remove _isFinished * clean up * format * Clean up * Add native channel to span frame collector * Clean up * Update * Fix has scheduled frame * Clean up * Clean up * Update * Format * Revert main.dart * Docs * Update docs and naming * Improve naming * Move adding performance collector to _initDefaultValues * Implement fallback display refreshrate on Android using WindowManager.DefaultDisplay * Calculate frame metrics in one loop and use SplayTreeSet for the active spans * Use clock instead of getUtcDateTime * Remove span directly * Merge mocks from main * Fix merge stuff * increase test ranges * Increase ranges and run format * Remove unnecessary test * improve test * Fix ktlitn * See if this fixes windows test * see if this fixes * log infos why it's failing * Fix tests * increase delay * Fix test (at least on web) * try with future.foreach * try fix * Fix * fix * fix * fix? * Remove enablesFrameTracking checking in onSpanFinished * Fix macos refresh rate fetching * Fix ktlint * fix dart analyze * Fix analyze * Update implementation * Break early out of metrics calculation due to sorted frames * Update macos impl * Use core graphics * swift lint * Add comment why we don't use CADisplayLink in macos --- CHANGELOG.md | 1 + dart/lib/sentry.dart | 1 + dart/lib/src/performance_collector.dart | 13 + dart/lib/src/protocol/sentry_span.dart | 33 ++- dart/lib/src/sentry_options.dart | 8 + dart/lib/src/sentry_tracer.dart | 13 + .../io/sentry/flutter/SentryFlutterPlugin.kt | 25 ++ .../Classes/SentryFlutterPluginApple.swift | 62 ++++ flutter/lib/src/frame_callback_handler.dart | 21 ++ .../lib/src/native/sentry_native_binding.dart | 2 + .../lib/src/native/sentry_native_channel.dart | 4 + flutter/lib/src/sentry_flutter.dart | 3 + flutter/lib/src/sentry_flutter_options.dart | 14 + .../lib/src/span_frame_metrics_collector.dart | 256 ++++++++++++++++ flutter/test/fake_frame_callback_handler.dart | 19 +- flutter/test/mocks.dart | 15 + flutter/test/mocks.mocks.dart | 24 ++ .../span_frame_metrics_collector_test.dart | 274 ++++++++++++++++++ 18 files changed, 779 insertions(+), 9 deletions(-) create mode 100644 dart/lib/src/performance_collector.dart create mode 100644 flutter/lib/src/span_frame_metrics_collector.dart create mode 100644 flutter/test/span_frame_metrics_collector_test.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index 0bc2f45ab2..0df11587c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### Features +- Capture total frames, frames delay, slow & frozen frames and attach to spans ([#2106](https://github.com/getsentry/sentry-dart/pull/2106)) - Support WebAssembly compilation (dart2wasm) ([#2113](https://github.com/getsentry/sentry-dart/pull/2113)) ### Dependencies diff --git a/dart/lib/sentry.dart b/dart/lib/sentry.dart index f416d0b797..fd88a49fc5 100644 --- a/dart/lib/sentry.dart +++ b/dart/lib/sentry.dart @@ -30,6 +30,7 @@ export 'src/http_client/sentry_http_client_error.dart'; export 'src/sentry_attachment/sentry_attachment.dart'; export 'src/sentry_user_feedback.dart'; export 'src/utils/tracing_utils.dart'; +export 'src/performance_collector.dart'; // tracing export 'src/tracing.dart'; export 'src/hint.dart'; diff --git a/dart/lib/src/performance_collector.dart b/dart/lib/src/performance_collector.dart new file mode 100644 index 0000000000..736534fb03 --- /dev/null +++ b/dart/lib/src/performance_collector.dart @@ -0,0 +1,13 @@ +import '../sentry.dart'; + +abstract class PerformanceCollector {} + +/// Used for collecting continuous data about vitals (slow, frozen frames, etc.) +/// during a transaction/span. +abstract class PerformanceContinuousCollector extends PerformanceCollector { + Future onSpanStarted(ISentrySpan span); + + Future onSpanFinished(ISentrySpan span, DateTime endTimestamp); + + void clear(); +} diff --git a/dart/lib/src/protocol/sentry_span.dart b/dart/lib/src/protocol/sentry_span.dart index 780578d182..6358b4802a 100644 --- a/dart/lib/src/protocol/sentry_span.dart +++ b/dart/lib/src/protocol/sentry_span.dart @@ -1,12 +1,11 @@ import 'dart:async'; -import '../hub.dart'; +import 'package:meta/meta.dart'; + +import '../../sentry.dart'; import '../metrics/local_metrics_aggregator.dart'; -import '../protocol.dart'; import '../sentry_tracer.dart'; -import '../tracing.dart'; -import '../utils.dart'; typedef OnFinishedCallback = Future Function({DateTime? endTimestamp}); @@ -17,7 +16,15 @@ class SentrySpan extends ISentrySpan { late final DateTime _startTimestamp; final Hub _hub; + bool _isRootSpan = false; + + bool get isRootSpan => _isRootSpan; + + @internal + SentryTracer get tracer => _tracer; + final SentryTracer _tracer; + final Map _data = {}; dynamic _throwable; @@ -36,6 +43,7 @@ class SentrySpan extends ISentrySpan { DateTime? startTimestamp, this.samplingDecision, OnFinishedCallback? finishedCallback, + isRootSpan = false, }) { _startTimestamp = startTimestamp?.toUtc() ?? _hub.options.clock(); _finishedCallback = finishedCallback; @@ -43,6 +51,7 @@ class SentrySpan extends ISentrySpan { _localMetricsAggregator = _hub.options.enableSpanLocalMetricAggregation ? LocalMetricsAggregator() : null; + _isRootSpan = isRootSpan; } @override @@ -56,17 +65,27 @@ class SentrySpan extends ISentrySpan { } if (endTimestamp == null) { - _endTimestamp = _hub.options.clock(); + endTimestamp = _hub.options.clock(); } else if (endTimestamp.isBefore(_startTimestamp)) { _hub.options.logger( SentryLevel.warning, 'End timestamp ($endTimestamp) cannot be before start timestamp ($_startTimestamp)', ); - _endTimestamp = _hub.options.clock(); + endTimestamp = _hub.options.clock(); } else { - _endTimestamp = endTimestamp.toUtc(); + endTimestamp = endTimestamp.toUtc(); } + for (final collector in _hub.options.performanceCollectors) { + if (collector is PerformanceContinuousCollector) { + await collector.onSpanFinished(this, endTimestamp); + } + } + + // The finished flag depends on the _endTimestamp + // If we set this earlier then finished is true and then we cannot use setData etc... + _endTimestamp = endTimestamp; + // associate error if (_throwable != null) { _hub.setSpanContext(_throwable, this, _tracer.name); diff --git a/dart/lib/src/sentry_options.dart b/dart/lib/src/sentry_options.dart index 956f81c056..f3f3c65a50 100644 --- a/dart/lib/src/sentry_options.dart +++ b/dart/lib/src/sentry_options.dart @@ -501,6 +501,14 @@ class SentryOptions { return tracesSampleRate != null || tracesSampler != null; } + List get performanceCollectors => + _performanceCollectors; + final List _performanceCollectors = []; + + void addPerformanceCollector(PerformanceCollector collector) { + _performanceCollectors.add(collector); + } + @internal late SentryExceptionFactory exceptionFactory = SentryExceptionFactory(this); diff --git a/dart/lib/src/sentry_tracer.dart b/dart/lib/src/sentry_tracer.dart index 2326db0716..350552a9ee 100644 --- a/dart/lib/src/sentry_tracer.dart +++ b/dart/lib/src/sentry_tracer.dart @@ -69,6 +69,7 @@ class SentryTracer extends ISentrySpan { _hub, samplingDecision: transactionContext.samplingDecision, startTimestamp: startTimestamp, + isRootSpan: true, ); _waitForChildren = waitForChildren; _autoFinishAfter = autoFinishAfter; @@ -80,6 +81,12 @@ class SentryTracer extends ISentrySpan { SentryTransactionNameSource.custom; _trimEnd = trimEnd; _onFinish = onFinish; + + for (final collector in _hub.options.performanceCollectors) { + if (collector is PerformanceContinuousCollector) { + collector.onSpanStarted(_rootSpan); + } + } } @override @@ -256,6 +263,12 @@ class SentryTracer extends ISentrySpan { _children.add(child); + for (final collector in _hub.options.performanceCollectors) { + if (collector is PerformanceContinuousCollector) { + collector.onSpanStarted(child); + } + } + return child; } diff --git a/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutterPlugin.kt b/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutterPlugin.kt index 424e51c6b7..26b84a6f5d 100644 --- a/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutterPlugin.kt +++ b/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutterPlugin.kt @@ -2,6 +2,7 @@ package io.sentry.flutter import android.app.Activity import android.content.Context +import android.os.Build import android.util.Log import io.flutter.embedding.engine.plugins.FlutterPlugin import io.flutter.embedding.engine.plugins.activity.ActivityAware @@ -72,6 +73,7 @@ class SentryFlutterPlugin : FlutterPlugin, MethodCallHandler, ActivityAware { "setTag" -> setTag(call.argument("key"), call.argument("value"), result) "removeTag" -> removeTag(call.argument("key"), result) "loadContexts" -> loadContexts(result) + "displayRefreshRate" -> displayRefreshRate(result) else -> result.notImplemented() } } @@ -179,6 +181,29 @@ class SentryFlutterPlugin : FlutterPlugin, MethodCallHandler, ActivityAware { } } + private fun displayRefreshRate(result: Result) { + var refreshRate: Int? = null + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + val display = activity?.get()?.display + if (display != null) { + refreshRate = display.refreshRate.toInt() + } + } else { + val display = + activity + ?.get() + ?.window + ?.windowManager + ?.defaultDisplay + if (display != null) { + refreshRate = display.refreshRate.toInt() + } + } + + result.success(refreshRate) + } + private fun TimeSpan.addToMap(map: MutableMap) { if (startTimestamp == null) return diff --git a/flutter/ios/Classes/SentryFlutterPluginApple.swift b/flutter/ios/Classes/SentryFlutterPluginApple.swift index fc8fb42f9c..cee6266564 100644 --- a/flutter/ios/Classes/SentryFlutterPluginApple.swift +++ b/flutter/ios/Classes/SentryFlutterPluginApple.swift @@ -5,6 +5,7 @@ import UIKit #elseif os(macOS) import FlutterMacOS import AppKit +import CoreVideo #endif // swiftlint:disable file_length function_body_length @@ -164,6 +165,9 @@ public class SentryFlutterPluginApple: NSObject, FlutterPlugin { collectProfile(call, result) #endif + case "displayRefreshRate": + displayRefreshRate(result) + default: result(FlutterMethodNotImplemented) } @@ -651,6 +655,64 @@ public class SentryFlutterPluginApple: NSObject, FlutterPlugin { PrivateSentrySDKOnly.discardProfiler(forTrace: SentryId(uuidString: traceId)) result(nil) } + + #if os(iOS) + // Taken from the Flutter engine: + // https://github.com/flutter/engine/blob/main/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.mm#L150 + private func displayRefreshRate(_ result: @escaping FlutterResult) { + let displayLink = CADisplayLink(target: self, selector: #selector(onDisplayLink(_:))) + displayLink.add(to: .main, forMode: .common) + displayLink.isPaused = true + + let preferredFPS = displayLink.preferredFramesPerSecond + displayLink.invalidate() + + if preferredFPS != 0 { + result(preferredFPS) + return + } + + if #available(iOS 13.0, *) { + guard let windowScene = UIApplication.shared.windows.first?.windowScene else { + result(nil) + return + } + result(windowScene.screen.maximumFramesPerSecond) + } else { + result(UIScreen.main.maximumFramesPerSecond) + } + } + + @objc private func onDisplayLink(_ displayLink: CADisplayLink) { + // No-op + } + #elseif os(macOS) + private func displayRefreshRate(_ result: @escaping FlutterResult) { + // We don't use CADisplayLink for macOS because it's only available starting with macOS 14 + guard let window = NSApplication.shared.keyWindow else { + result(nil) + return + } + + guard let screen = window.screen else { + result(nil) + return + } + + guard let displayID = + screen.deviceDescription[NSDeviceDescriptionKey("NSScreenNumber")] as? CGDirectDisplayID else { + result(nil) + return + } + + guard let mode = CGDisplayCopyDisplayMode(displayID) else { + result(nil) + return + } + + result(Int(mode.refreshRate)) + } + #endif } // swiftlint:enable function_body_length diff --git a/flutter/lib/src/frame_callback_handler.dart b/flutter/lib/src/frame_callback_handler.dart index 71a8f928b1..139d3cbde9 100644 --- a/flutter/lib/src/frame_callback_handler.dart +++ b/flutter/lib/src/frame_callback_handler.dart @@ -1,7 +1,11 @@ +import 'package:flutter/cupertino.dart'; import 'package:flutter/scheduler.dart'; abstract class FrameCallbackHandler { void addPostFrameCallback(FrameCallback callback); + void addPersistentFrameCallback(FrameCallback callback); + Future get endOfFrame; + bool get hasScheduledFrame; } class DefaultFrameCallbackHandler implements FrameCallbackHandler { @@ -12,4 +16,21 @@ class DefaultFrameCallbackHandler implements FrameCallbackHandler { SchedulerBinding.instance.addPostFrameCallback(callback); } catch (_) {} } + + @override + void addPersistentFrameCallback(FrameCallback callback) { + try { + WidgetsBinding.instance.addPersistentFrameCallback(callback); + } catch (_) {} + } + + @override + Future get endOfFrame async { + try { + await WidgetsBinding.instance.endOfFrame; + } catch (_) {} + } + + @override + bool get hasScheduledFrame => WidgetsBinding.instance.hasScheduledFrame; } diff --git a/flutter/lib/src/native/sentry_native_binding.dart b/flutter/lib/src/native/sentry_native_binding.dart index 96962a0575..54223b5561 100644 --- a/flutter/lib/src/native/sentry_native_binding.dart +++ b/flutter/lib/src/native/sentry_native_binding.dart @@ -46,6 +46,8 @@ abstract class SentryNativeBinding { Future discardProfiler(SentryId traceId); + Future displayRefreshRate(); + Future?> collectProfile( SentryId traceId, int startTimeNs, int endTimeNs); diff --git a/flutter/lib/src/native/sentry_native_channel.dart b/flutter/lib/src/native/sentry_native_channel.dart index 2b3e703065..e6888eecac 100644 --- a/flutter/lib/src/native/sentry_native_channel.dart +++ b/flutter/lib/src/native/sentry_native_channel.dart @@ -178,4 +178,8 @@ class SentryNativeChannel .map(DebugImage.fromJson) .toList(); }); + + @override + Future displayRefreshRate() => + _channel.invokeMethod('displayRefreshRate'); } diff --git a/flutter/lib/src/sentry_flutter.dart b/flutter/lib/src/sentry_flutter.dart index f9914d7eaa..8cf3d995ba 100644 --- a/flutter/lib/src/sentry_flutter.dart +++ b/flutter/lib/src/sentry_flutter.dart @@ -3,6 +3,7 @@ import 'dart:ui'; import 'package:flutter/widgets.dart'; import 'package:meta/meta.dart'; +import 'span_frame_metrics_collector.dart'; import '../sentry_flutter.dart'; import 'event_processor/android_platform_exception_event_processor.dart'; import 'event_processor/flutter_exception_event_processor.dart'; @@ -135,6 +136,8 @@ mixin SentryFlutter { options.addEventProcessor(PlatformExceptionEventProcessor()); + options.addPerformanceCollector(SpanFrameMetricsCollector(options)); + _setSdk(options); } diff --git a/flutter/lib/src/sentry_flutter_options.dart b/flutter/lib/src/sentry_flutter_options.dart index ae83de611e..913070e9ca 100644 --- a/flutter/lib/src/sentry_flutter_options.dart +++ b/flutter/lib/src/sentry_flutter_options.dart @@ -232,6 +232,20 @@ class SentryFlutterOptions extends SentryOptions { /// Read timeout. This will only be synced to the Android native SDK. Duration readTimeout = Duration(seconds: 5); + /// Enable or disable Frames Tracking, which is used to report frame information + /// for every [ISentrySpan]. + /// + /// When enabled, the following metrics are reported for each span: + /// - Slow frames: The number of frames that exceeded a specified threshold for frame duration. + /// - Frozen frames: The number of frames that took an unusually long time to render, indicating a potential freeze or hang. + /// - Total frames count: The total number of frames rendered during the span. + /// - Frames delay: The delayed frame render duration of all frames. + + /// Read more about frames tracking here: https://develop.sentry.dev/sdk/performance/frames-delay/ + /// + /// Defaults to `true` + bool enableFramesTracking = true; + /// By using this, you are disabling native [Breadcrumb] tracking and instead /// you are just tracking [Breadcrumb]s which result from events available /// in the current Flutter environment. diff --git a/flutter/lib/src/span_frame_metrics_collector.dart b/flutter/lib/src/span_frame_metrics_collector.dart new file mode 100644 index 0000000000..ecf0ca961c --- /dev/null +++ b/flutter/lib/src/span_frame_metrics_collector.dart @@ -0,0 +1,256 @@ +import 'dart:collection'; +import 'dart:math'; + +import 'package:flutter/cupertino.dart'; +import 'package:meta/meta.dart'; + +import '../sentry_flutter.dart'; + +import 'frame_callback_handler.dart'; +import 'native/sentry_native_binding.dart'; + +@internal +class SpanFrameMetricsCollector implements PerformanceContinuousCollector { + static const _frozenFrameThresholdMs = 700; + static const totalFramesKey = 'frames.total'; + static const framesDelayKey = 'frames.delay'; + static const slowFramesKey = 'frames.slow'; + static const frozenFramesKey = 'frames.frozen'; + + final SentryFlutterOptions options; + final FrameCallbackHandler _frameCallbackHandler; + final SentryNativeBinding? _native; + + final bool _isTestMode; + + /// Stores frame timestamps and their durations in milliseconds. + /// Keys are frame timestamps, values are frame durations. + /// The timestamps mark the end of the frame. + final frames = SplayTreeMap(); + + /// Stores the spans that are actively being tracked. + /// After the frames are calculated and stored in the span the span is removed from this list. + final activeSpans = SplayTreeSet( + (a, b) => a.startTimestamp.compareTo(b.startTimestamp)); + + bool get isTrackingPaused => _isTrackingPaused; + bool _isTrackingPaused = true; + + bool get isTrackingRegistered => _isTrackingRegistered; + bool _isTrackingRegistered = false; + + int displayRefreshRate = 60; + + final _stopwatch = Stopwatch(); + + SpanFrameMetricsCollector(this.options, + {FrameCallbackHandler? frameCallbackHandler, + SentryNativeBinding? native, + @internal bool isTestMode = false}) + : _frameCallbackHandler = + frameCallbackHandler ?? DefaultFrameCallbackHandler(), + _native = native ?? SentryFlutter.native, + _isTestMode = isTestMode; + + @override + Future onSpanStarted(ISentrySpan span) async { + if (span is NoOpSentrySpan || !options.enableFramesTracking) { + return; + } + + final fetchedDisplayRefreshRate = await _native?.displayRefreshRate(); + if (fetchedDisplayRefreshRate != null) { + options.logger(SentryLevel.debug, + 'Retrieved display refresh rate at $fetchedDisplayRefreshRate'); + displayRefreshRate = fetchedDisplayRefreshRate; + } else { + options.logger(SentryLevel.debug, + 'Could not fetch display refresh rate, keeping at 60hz by default'); + } + + activeSpans.add(span); + startFrameTracking(); + } + + @override + Future onSpanFinished(ISentrySpan span, DateTime endTimestamp) async { + if (span is NoOpSentrySpan || !activeSpans.contains(span)) return; + + final frameMetrics = + calculateFrameMetrics(span, endTimestamp, displayRefreshRate); + _applyFrameMetricsToSpan(span, frameMetrics); + + activeSpans.remove(span); + if (activeSpans.isEmpty) { + clear(); + } else { + frames.removeWhere((frameTimestamp, _) => + frameTimestamp.isBefore(activeSpans.first.startTimestamp)); + } + } + + /// Calls [WidgetsBinding.instance.addPersistentFrameCallback] which cannot be unregistered + /// and exists for the duration of the application's lifetime. + /// + /// Stopping the frame tracking means setting [isTrackingPaused] is `true` + /// to prevent actions being done when the frame callback is triggered. + void startFrameTracking() { + _isTrackingPaused = false; + + if (!_isTrackingRegistered) { + _frameCallbackHandler.addPersistentFrameCallback(measureFrameDuration); + _isTrackingRegistered = true; + } + } + + /// Records the duration of a single frame and stores it in [frames]. + /// + /// This method is called for each frame when frame tracking is active. + Future measureFrameDuration(Duration duration) async { + // Using the stopwatch to measure the frame duration is flaky in ci + if (_isTestMode) { + // ignore: invalid_use_of_internal_member + frames[options.clock().add(duration)] = duration.inMilliseconds; + return; + } + + if (_isTrackingPaused) return; + + if (!_stopwatch.isRunning) { + _stopwatch.start(); + } + + await _frameCallbackHandler.endOfFrame; + + final frameDuration = _stopwatch.elapsedMilliseconds; + // ignore: invalid_use_of_internal_member + frames[options.clock()] = frameDuration; + + _stopwatch.reset(); + + if (_frameCallbackHandler.hasScheduledFrame == true) { + _stopwatch.start(); + } + } + + void _applyFrameMetricsToSpan( + ISentrySpan span, Map frameMetrics) { + frameMetrics.forEach((key, value) { + span.setData(key, value); + }); + + // This will call the methods on the tracer, not on the span directly + if (span is SentrySpan && span.isRootSpan) { + frameMetrics.forEach((key, value) { + // ignore: invalid_use_of_internal_member + span.tracer.setData(key, value); + + // In measurements we change e.g frames.total to frames_total + // We don't do span.tracer.setMeasurement because setMeasurement in SentrySpan + // uses the tracer internally + span.setMeasurement(key.replaceAll('.', '_'), value); + }); + } + } + + @visibleForTesting + Map calculateFrameMetrics( + ISentrySpan span, DateTime spanEndTimestamp, int displayRefreshRate) { + if (frames.isEmpty) { + options.logger( + SentryLevel.info, 'No frame durations available in frame tracker.'); + return {}; + } + + final expectedFrameDuration = ((1 / displayRefreshRate) * 1000).toInt(); + + int slowFramesCount = 0; + int frozenFramesCount = 0; + int slowFramesDuration = 0; + int frozenFramesDuration = 0; + int framesDelay = 0; + + for (final entry in frames.entries) { + final frameDuration = entry.value; + final frameEndTimestamp = entry.key; + final frameStartMs = + frameEndTimestamp.millisecondsSinceEpoch - frameDuration; + final frameEndMs = frameEndTimestamp.millisecondsSinceEpoch; + final spanStartMs = span.startTimestamp.millisecondsSinceEpoch; + final spanEndMs = spanEndTimestamp.millisecondsSinceEpoch; + + final frameFullyContainedInSpan = + frameEndMs <= spanEndMs && frameStartMs >= spanStartMs; + final frameStartsBeforeSpan = + frameStartMs < spanStartMs && frameEndMs > spanStartMs; + final frameEndsAfterSpan = + frameStartMs < spanEndMs && frameEndMs > spanEndMs; + final framePartiallyContainedInSpan = + frameStartsBeforeSpan || frameEndsAfterSpan; + + int effectiveDuration = 0; + int effectiveDelay = 0; + + if (frameFullyContainedInSpan) { + effectiveDuration = frameDuration; + effectiveDelay = max(0, frameDuration - expectedFrameDuration); + } else if (framePartiallyContainedInSpan) { + final intersectionStart = max(frameStartMs, spanStartMs); + final intersectionEnd = min(frameEndMs, spanEndMs); + effectiveDuration = intersectionEnd - intersectionStart; + + final fullFrameDelay = max(0, frameDuration - expectedFrameDuration); + final intersectionRatio = effectiveDuration / frameDuration; + effectiveDelay = (fullFrameDelay * intersectionRatio).round(); + } else if (frameStartMs > spanEndMs) { + // Other frames will be newer than this span, as frames are ordered + break; + } else { + // Frame is completely outside the span, skip it + continue; + } + + if (effectiveDuration > _frozenFrameThresholdMs) { + frozenFramesCount++; + frozenFramesDuration += effectiveDuration; + } else if (effectiveDuration > expectedFrameDuration) { + slowFramesCount++; + slowFramesDuration += effectiveDuration; + } + + framesDelay += effectiveDelay; + } + + final spanDuration = + spanEndTimestamp.difference(span.startTimestamp).inMilliseconds; + final totalFramesCount = + ((spanDuration - (slowFramesDuration + frozenFramesDuration)) / + expectedFrameDuration) + + slowFramesCount + + frozenFramesCount; + + if (totalFramesCount < 0 || + framesDelay < 0 || + slowFramesCount < 0 || + frozenFramesCount < 0) { + options.logger(SentryLevel.warning, + 'Negative frame metrics calculated. Dropping frame metrics.'); + return {}; + } + + return { + SpanFrameMetricsCollector.totalFramesKey: totalFramesCount.toInt(), + SpanFrameMetricsCollector.framesDelayKey: framesDelay, + SpanFrameMetricsCollector.slowFramesKey: slowFramesCount, + SpanFrameMetricsCollector.frozenFramesKey: frozenFramesCount, + }; + } + + @override + void clear() { + _isTrackingPaused = true; + frames.clear(); + activeSpans.clear(); + displayRefreshRate = 60; + } +} diff --git a/flutter/test/fake_frame_callback_handler.dart b/flutter/test/fake_frame_callback_handler.dart index 0dc968f22c..aa450a7911 100644 --- a/flutter/test/fake_frame_callback_handler.dart +++ b/flutter/test/fake_frame_callback_handler.dart @@ -1,9 +1,9 @@ import 'package:flutter/scheduler.dart'; import 'package:sentry_flutter/src/frame_callback_handler.dart'; -class FakeFrameCallbackHandler implements FrameCallbackHandler { - FrameCallback? storedCallback; +import 'mocks.dart'; +class FakeFrameCallbackHandler implements FrameCallbackHandler { final Duration finishAfterDuration; FakeFrameCallbackHandler( @@ -15,4 +15,19 @@ class FakeFrameCallbackHandler implements FrameCallbackHandler { await Future.delayed(finishAfterDuration); callback(Duration.zero); } + + @override + Future addPersistentFrameCallback(FrameCallback callback) async { + for (final duration in fakeFrameDurations) { + // Let's wait a bit so the timestamp intervals are large enough + await Future.delayed(Duration(milliseconds: 20)); + callback(duration); + } + } + + @override + bool hasScheduledFrame = true; + + @override + Future get endOfFrame => Future.value(); } diff --git a/flutter/test/mocks.dart b/flutter/test/mocks.dart index 4b7ff1aed5..f5e5cb65ce 100644 --- a/flutter/test/mocks.dart +++ b/flutter/test/mocks.dart @@ -191,3 +191,18 @@ class TestBindingWrapper implements BindingWrapper { } class MockSentryClient with NoSuchMethodProvider implements SentryClient {} + +// All these values are based on the fakeFrameDurations list. +// The expected total frames is also based on the span duration of 1000ms and the slow and frozen frames. +const expectedTotalFrames = 17; +const expectedFramesDelay = 722; +const expectedSlowFrames = 2; +const expectedFrozenFrames = 1; + +final fakeFrameDurations = [ + Duration(milliseconds: 0), + Duration(milliseconds: 10), + Duration(milliseconds: 20), + Duration(milliseconds: 40), + Duration(milliseconds: 710), +]; diff --git a/flutter/test/mocks.mocks.dart b/flutter/test/mocks.mocks.dart index bf6114a638..7e595ab4cf 100644 --- a/flutter/test/mocks.mocks.dart +++ b/flutter/test/mocks.mocks.dart @@ -755,6 +755,21 @@ class MockSentrySpan extends _i1.Mock implements _i3.SentrySpan { _i1.throwOnMissingStub(this); } + @override + bool get isRootSpan => (super.noSuchMethod( + Invocation.getter(#isRootSpan), + returnValue: false, + ) as bool); + + @override + _i4.SentryTracer get tracer => (super.noSuchMethod( + Invocation.getter(#tracer), + returnValue: _FakeSentryTracer_4( + this, + Invocation.getter(#tracer), + ), + ) as _i4.SentryTracer); + @override set status(_i3.SpanStatus? status) => super.noSuchMethod( Invocation.setter( @@ -1270,6 +1285,15 @@ class MockSentryNativeBinding extends _i1.Mock returnValueForMissingStub: _i8.Future.value(), ) as _i8.Future); + @override + _i8.Future displayRefreshRate() => (super.noSuchMethod( + Invocation.method( + #displayRefreshRate, + [], + ), + returnValue: _i8.Future.value(), + ) as _i8.Future); + @override _i8.Future?> collectProfile( _i3.SentryId? traceId, diff --git a/flutter/test/span_frame_metrics_collector_test.dart b/flutter/test/span_frame_metrics_collector_test.dart new file mode 100644 index 0000000000..70c3348070 --- /dev/null +++ b/flutter/test/span_frame_metrics_collector_test.dart @@ -0,0 +1,274 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mockito/mockito.dart'; +import 'package:sentry_flutter/sentry_flutter.dart'; +import 'package:sentry_flutter/src/span_frame_metrics_collector.dart'; + +import 'fake_frame_callback_handler.dart'; +import 'mocks.dart'; + +// ignore: implementation_imports +import 'package:sentry/src/sentry_tracer.dart'; + +import 'mocks.mocks.dart'; + +void main() { + late Fixture fixture; + + setUp(() { + fixture = Fixture(); + WidgetsFlutterBinding.ensureInitialized(); + + when(fixture.mockSentryNative.displayRefreshRate()) + .thenAnswer((_) async => 60); + }); + + test('clear() clears frames, running spans and pauses frame tracking', () { + final sut = fixture.sut; + sut.frames[DateTime.now()] = 1; + final mockSpan = MockSentrySpan(); + when(mockSpan.startTimestamp).thenReturn(DateTime.now()); + + sut.onSpanStarted(mockSpan); + sut.clear(); + + expect(sut.frames, isEmpty); + expect(sut.activeSpans, isEmpty); + expect(sut.isTrackingPaused, isTrue); + }); + + test('does not start frame tracking if frames tracking is disabled', () { + final sut = fixture.sut; + fixture.options.enableFramesTracking = false; + + final span = MockSentrySpan(); + sut.onSpanStarted(span); + + expect(sut.isTrackingRegistered, isFalse); + }); + + test( + 'captures metrics with display refresh rate of 60 if native refresh rate is null', + () async { + final sut = fixture.sut; + fixture.options.tracesSampleRate = 1.0; + fixture.options.addPerformanceCollector(sut); + final startTimestamp = DateTime.now(); + final endTimestamp = + startTimestamp.add(Duration(milliseconds: 1000)).toUtc(); + + when(fixture.mockSentryNative.displayRefreshRate()) + .thenAnswer((_) async => null); + + final tracer = SentryTracer( + SentryTransactionContext('name', 'op', description: 'tracerDesc'), + fixture.hub, + startTimestamp: startTimestamp); + + await Future.delayed(Duration(milliseconds: 500)); + await tracer.finish(endTimestamp: endTimestamp); + + expect(tracer.data['frames.slow'], expectedSlowFrames); + expect(tracer.data['frames.frozen'], expectedFrozenFrames); + expect(tracer.data['frames.delay'], expectedFramesDelay); + expect(tracer.data['frames.total'], expectedTotalFrames); + }); + + test('onSpanFinished removes frames older than span start timestamp', + () async { + // Using multiple spans to test frame removal. When the last span is finished, + // the tracker clears all data, so we need at least two spans to observe partial removal. + final sut = fixture.sut; + final span1 = MockSentrySpan(); + final span2 = MockSentrySpan(); + final spanStartTimestamp = DateTime.now(); + final spanEndTimestamp = spanStartTimestamp.add(Duration(seconds: 1)); + + when(span1.isRootSpan).thenReturn(false); + when(span1.startTimestamp).thenReturn(spanStartTimestamp); + when(span1.context).thenReturn(SentrySpanContext(operation: 'op')); + + when(span2.isRootSpan).thenReturn(false); + when(span2.startTimestamp) + .thenReturn(spanStartTimestamp.add(Duration(seconds: 2))); + when(span2.context).thenReturn(SentrySpanContext(operation: 'op')); + + sut.activeSpans.add(span1); + sut.activeSpans.add(span2); + + sut.frames[spanStartTimestamp.subtract(Duration(seconds: 5))] = 1; + sut.frames[spanStartTimestamp.subtract(Duration(seconds: 3))] = 1; + sut.frames[spanStartTimestamp.add(Duration(seconds: 4))] = 1; + + await sut.onSpanFinished(span1, spanEndTimestamp); + + expect(sut.frames, hasLength(1)); + expect(sut.frames.keys.first, spanStartTimestamp.add(Duration(seconds: 4))); + }); + + test( + 'starting and finishing a span calculates and attaches frame metrics to span', + () async { + final sut = fixture.sut; + fixture.options.tracesSampleRate = 1.0; + fixture.options.addPerformanceCollector(sut); + final startTimestamp = DateTime.now(); + final endTimestamp = startTimestamp.add(Duration(milliseconds: 1000)); + + final tracer = SentryTracer( + SentryTransactionContext('name1', 'op1'), fixture.hub, + startTimestamp: startTimestamp); + + await Future.delayed(Duration(milliseconds: 500)); + await tracer.finish(endTimestamp: endTimestamp); + + expect(tracer.data['frames.slow'], expectedSlowFrames); + expect(tracer.data['frames.frozen'], expectedFrozenFrames); + expect(tracer.data['frames.delay'], expectedFramesDelay); + expect(tracer.data['frames.total'], expectedTotalFrames); + + expect(tracer.measurements['frames_delay']!.value, expectedFramesDelay); + expect(tracer.measurements['frames_total']!.value, expectedTotalFrames); + expect(tracer.measurements['frames_slow']!.value, expectedSlowFrames); + expect(tracer.measurements['frames_frozen']!.value, expectedFrozenFrames); + }); + + test('frame fully contained in span should contribute to frame metrics', () { + final sut = fixture.sut; + final span = MockSentrySpan(); + + final now = DateTime.now(); + when(span.startTimestamp).thenReturn(now); + when(span.endTimestamp).thenReturn(now.add(Duration(milliseconds: 500))); + sut.frames[now.add(Duration(milliseconds: 200))] = 100; + + final metrics = sut.calculateFrameMetrics(span, span.endTimestamp!, 60); + + expect(metrics['frames.total'], 26); + expect(metrics['frames.slow'], 1); + expect(metrics['frames.delay'], 84); + expect(metrics['frames.frozen'], 0); + }); + + test('frame fully outside of span should not contribute to frame metrics', + () { + final sut = fixture.sut; + final span = MockSentrySpan(); + + final now = DateTime.now(); + when(span.startTimestamp).thenReturn(now); + when(span.endTimestamp).thenReturn(now.add(Duration(milliseconds: 500))); + sut.frames[now.subtract(Duration(milliseconds: 200))] = 100; + + final metrics = sut.calculateFrameMetrics(span, span.endTimestamp!, 60); + + expect(metrics['frames.total'], 31); + expect(metrics['frames.slow'], 0); + expect(metrics['frames.delay'], 0); + expect(metrics['frames.frozen'], 0); + }); + + test( + 'frame partially contained in span (starts before span and ends within span) should contribute to frame metrics', + () { + final sut = fixture.sut; + final span = MockSentrySpan(); + + final now = DateTime.now(); + when(span.startTimestamp).thenReturn(now); + when(span.endTimestamp).thenReturn(now.add(Duration(milliseconds: 500))); + // 50ms before span starts and ends 50ms after span starts + sut.frames[now.add(Duration(milliseconds: 50))] = 100; + + final metrics = sut.calculateFrameMetrics(span, span.endTimestamp!, 60); + + expect(metrics['frames.total'], 29); + expect(metrics['frames.slow'], 1); + expect(metrics['frames.delay'], 42); + expect(metrics['frames.frozen'], 0); + }); + + test( + 'frame partially contained in span (starts withing span and ends after span end) should contribute to frame metrics', + () { + final sut = fixture.sut; + final span = MockSentrySpan(); + + final now = DateTime.now(); + when(span.startTimestamp).thenReturn(now); + when(span.endTimestamp).thenReturn(now.add(Duration(milliseconds: 500))); + sut.frames[now.add(Duration(milliseconds: 550))] = 100; + + final metrics = sut.calculateFrameMetrics(span, span.endTimestamp!, 60); + + expect(metrics['frames.total'], 29); + expect(metrics['frames.slow'], 1); + expect(metrics['frames.delay'], 42); + expect(metrics['frames.frozen'], 0); + }); + + test('calculates frame metrics correctly for multiple simultaneous spans', + () async { + final sut = fixture.sut; + fixture.options.tracesSampleRate = 1.0; + fixture.options.addPerformanceCollector(sut); + final startTimestamp = DateTime.now(); + final endTimestamp = startTimestamp.add(Duration(milliseconds: 1000)); + + final tracer = SentryTracer( + SentryTransactionContext('name1', 'op1'), fixture.hub, + startTimestamp: startTimestamp); + + final child = tracer.startChild('child', + startTimestamp: startTimestamp.add(Duration(milliseconds: 1))) + as SentrySpan; + + await Future.delayed(Duration(milliseconds: 500)); + await child.finish(endTimestamp: endTimestamp); + + await Future.delayed(Duration(milliseconds: 500)); + await tracer.finish(endTimestamp: endTimestamp); + + expect(child.data['frames.slow'], expectedSlowFrames); + expect(child.data['frames.frozen'], expectedFrozenFrames); + expect(child.data['frames.delay'], expectedFramesDelay); + expect(child.data['frames.total'], expectedTotalFrames); + + // total frames is hardcoded here since it depends on span duration as well + // and we are deviating from the default 800ms to 1600ms for the whole transaction + expect(tracer.data['frames.slow'], expectedSlowFrames); + expect(tracer.data['frames.frozen'], expectedFrozenFrames); + expect(tracer.data['frames.delay'], expectedFramesDelay); + // expect(tracer.data['frames.total'], 54); + expect(tracer.measurements['frames_delay']!.value, expectedFramesDelay); + // expect(tracer.measurements['frames_total']!.value, 54); + expect(tracer.measurements['frames_slow']!.value, expectedSlowFrames); + expect(tracer.measurements['frames_frozen']!.value, expectedFrozenFrames); + }); + + test('frame tracker is paused after finishing a span', () async { + final sut = fixture.sut; + fixture.options.tracesSampleRate = 1.0; + fixture.options.addPerformanceCollector(sut); + + final tracer = + SentryTracer(SentryTransactionContext('name', 'op'), fixture.hub); + + await Future.delayed(Duration(milliseconds: 100)); + await tracer.finish(); + + expect(sut.isTrackingPaused, isTrue); + }); +} + +class Fixture { + final options = SentryFlutterOptions(dsn: fakeDsn); + late final hub = Hub(options); + final fakeFrameCallbackHandler = FakeFrameCallbackHandler(); + final mockSentryNative = MockSentryNativeBinding(); + + SpanFrameMetricsCollector get sut => SpanFrameMetricsCollector(options, + frameCallbackHandler: fakeFrameCallbackHandler, + native: mockSentryNative, + isTestMode: true); +} From e4d5aa8c2d59f501c1b158b4236384eadc0b7f4b Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Tue, 25 Jun 2024 14:15:07 +0200 Subject: [PATCH 225/237] deprecate: user segment (#2119) * Update * update * Add deprecation to setUserSegment --- CHANGELOG.md | 4 ++++ dart/lib/src/protocol/sentry_user.dart | 4 ++++ dart/lib/src/sentry_baggage.dart | 4 ++++ dart/lib/src/sentry_trace_context_header.dart | 5 +++++ dart/lib/src/sentry_tracer.dart | 1 + dart/test/protocol/sentry_baggage_header_test.dart | 1 + dart/test/protocol/sentry_user_test.dart | 1 + dart/test/sentry_trace_context_header_test.dart | 1 + dart/test/sentry_tracer_test.dart | 1 + 9 files changed, 22 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0df11587c9..f40482e232 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ - Capture total frames, frames delay, slow & frozen frames and attach to spans ([#2106](https://github.com/getsentry/sentry-dart/pull/2106)) - Support WebAssembly compilation (dart2wasm) ([#2113](https://github.com/getsentry/sentry-dart/pull/2113)) +### Deprecated + +- User segment is now deprecated and will be removed in version 9.0.0. Use a custom tag or context instead. ([#2119](https://github.com/getsentry/sentry-dart/pull/2119)) + ### Dependencies - Bump Cocoa SDK from v8.29.0 to v8.29.1 ([#2109](https://github.com/getsentry/sentry-dart/pull/2109)) diff --git a/dart/lib/src/protocol/sentry_user.dart b/dart/lib/src/protocol/sentry_user.dart index 3b2f2cab1c..c173432fcd 100644 --- a/dart/lib/src/protocol/sentry_user.dart +++ b/dart/lib/src/protocol/sentry_user.dart @@ -68,6 +68,8 @@ class SentryUser { final String? ipAddress; /// The user segment, for apps that divide users in user segments. + @Deprecated( + 'Will be removed in v9. Use a custom tag or context instead to capture this information.') final String? segment; /// Any other user context information that may be helpful. @@ -129,6 +131,7 @@ class SentryUser { if (username != null) 'username': username, if (email != null) 'email': email, if (ipAddress != null) 'ip_address': ipAddress, + // ignore: deprecated_member_use_from_same_package if (segment != null) 'segment': segment, if (data?.isNotEmpty ?? false) 'data': data, // ignore: deprecated_member_use_from_same_package @@ -155,6 +158,7 @@ class SentryUser { username: username ?? this.username, email: email ?? this.email, ipAddress: ipAddress ?? this.ipAddress, + // ignore: deprecated_member_use_from_same_package segment: segment ?? this.segment, data: data ?? this.data, // ignore: deprecated_member_use_from_same_package diff --git a/dart/lib/src/sentry_baggage.dart b/dart/lib/src/sentry_baggage.dart index 25aab900f4..ebed8765b1 100644 --- a/dart/lib/src/sentry_baggage.dart +++ b/dart/lib/src/sentry_baggage.dart @@ -106,7 +106,9 @@ class SentryBaggage { if (scope.user?.id != null) { setUserId(scope.user!.id!); } + // ignore: deprecated_member_use_from_same_package if (scope.user?.segment != null) { + // ignore: deprecated_member_use_from_same_package setUserSegment(scope.user!.segment!); } } @@ -176,6 +178,8 @@ class SentryBaggage { set('sentry-user_id', value); } + @Deprecated( + 'Will be removed in v9 since functionality has been removed from Sentry') void setUserSegment(String value) { set('sentry-user_segment', value); } diff --git a/dart/lib/src/sentry_trace_context_header.dart b/dart/lib/src/sentry_trace_context_header.dart index bcb1d0b1bb..d1ee5368af 100644 --- a/dart/lib/src/sentry_trace_context_header.dart +++ b/dart/lib/src/sentry_trace_context_header.dart @@ -20,6 +20,8 @@ class SentryTraceContextHeader { final String? release; final String? environment; final String? userId; + @Deprecated( + 'Will be removed in v9 since functionality has been removed from Sentry') final String? userSegment; final String? transaction; final String? sampleRate; @@ -48,6 +50,7 @@ class SentryTraceContextHeader { if (release != null) 'release': release, if (environment != null) 'environment': environment, if (userId != null) 'user_id': userId, + // ignore: deprecated_member_use_from_same_package if (userSegment != null) 'user_segment': userSegment, if (transaction != null) 'transaction': transaction, if (sampleRate != null) 'sample_rate': sampleRate, @@ -71,7 +74,9 @@ class SentryTraceContextHeader { if (userId != null) { baggage.setUserId(userId!); } + // ignore: deprecated_member_use_from_same_package if (userSegment != null) { + // ignore: deprecated_member_use_from_same_package baggage.setUserSegment(userSegment!); } if (transaction != null) { diff --git a/dart/lib/src/sentry_tracer.dart b/dart/lib/src/sentry_tracer.dart index 350552a9ee..66c179e386 100644 --- a/dart/lib/src/sentry_tracer.dart +++ b/dart/lib/src/sentry_tracer.dart @@ -374,6 +374,7 @@ class SentryTracer extends ISentrySpan { release: _hub.options.release, environment: _hub.options.environment, userId: null, // because of PII not sending it for now + // ignore: deprecated_member_use_from_same_package userSegment: user?.segment, transaction: _isHighQualityTransactionName(transactionNameSource) ? name : null, diff --git a/dart/test/protocol/sentry_baggage_header_test.dart b/dart/test/protocol/sentry_baggage_header_test.dart index 38428be41a..3e8555aba9 100644 --- a/dart/test/protocol/sentry_baggage_header_test.dart +++ b/dart/test/protocol/sentry_baggage_header_test.dart @@ -17,6 +17,7 @@ void main() { baggage.setRelease('release'); baggage.setEnvironment('environment'); baggage.setUserId('userId'); + // ignore: deprecated_member_use_from_same_package baggage.setUserSegment('userSegment'); baggage.setTransaction('transaction'); baggage.setSampleRate('1.0'); diff --git a/dart/test/protocol/sentry_user_test.dart b/dart/test/protocol/sentry_user_test.dart index 2a958624e2..d3c8e078ba 100644 --- a/dart/test/protocol/sentry_user_test.dart +++ b/dart/test/protocol/sentry_user_test.dart @@ -91,6 +91,7 @@ void main() { expect('email1', copy.email); expect('ipAddress1', copy.ipAddress); expect({'key1': 'value1'}, copy.data); + // ignore: deprecated_member_use_from_same_package expect('seg1', copy.segment); }); }); diff --git a/dart/test/sentry_trace_context_header_test.dart b/dart/test/sentry_trace_context_header_test.dart index 6ba6d93bc2..c4f856f344 100644 --- a/dart/test/sentry_trace_context_header_test.dart +++ b/dart/test/sentry_trace_context_header_test.dart @@ -24,6 +24,7 @@ void main() { expect(context.release, 'release'); expect(context.environment, 'environment'); expect(context.userId, 'user_id'); + // ignore: deprecated_member_use_from_same_package expect(context.userSegment, 'user_segment'); expect(context.transaction, 'transaction'); expect(context.sampleRate, '1.0'); diff --git a/dart/test/sentry_tracer_test.dart b/dart/test/sentry_tracer_test.dart index 7ba5e80fac..a1251c224b 100644 --- a/dart/test/sentry_tracer_test.dart +++ b/dart/test/sentry_tracer_test.dart @@ -582,6 +582,7 @@ void main() { expect(context.publicKey, 'abc'); expect(context.release, 'release'); expect(context.environment, 'environment'); + // ignore: deprecated_member_use_from_same_package expect(context.userSegment, 'segment'); expect(context.transaction, 'name'); expect(context.sampleRate, '1'); From 98d9a4ac558d7be8936b44827ff392e9de508e21 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 25 Jun 2024 19:19:09 +0200 Subject: [PATCH 226/237] chore(deps): update Cocoa SDK to v8.30.0 (#2132) * chore: update flutter/scripts/update-cocoa.sh to 8.30.0 * Update --------- Co-authored-by: GitHub Co-authored-by: GIancarlo Buenaflor --- flutter/ios/sentry_flutter.podspec | 2 +- flutter/lib/src/native/cocoa/binding.dart | 27 ----------------------- 2 files changed, 1 insertion(+), 28 deletions(-) diff --git a/flutter/ios/sentry_flutter.podspec b/flutter/ios/sentry_flutter.podspec index 8881fdefec..00b575b956 100644 --- a/flutter/ios/sentry_flutter.podspec +++ b/flutter/ios/sentry_flutter.podspec @@ -16,7 +16,7 @@ Sentry SDK for Flutter with support to native through sentry-cocoa. :tag => s.version.to_s } s.source_files = 'Classes/**/*' s.public_header_files = 'Classes/**/*.h' - s.dependency 'Sentry/HybridSDK', '8.29.1' + s.dependency 'Sentry/HybridSDK', '8.30.0' s.ios.dependency 'Flutter' s.osx.dependency 'FlutterMacOS' s.ios.deployment_target = '12.0' diff --git a/flutter/lib/src/native/cocoa/binding.dart b/flutter/lib/src/native/cocoa/binding.dart index 4af31cfc57..62afabb4cf 100644 --- a/flutter/lib/src/native/cocoa/binding.dart +++ b/flutter/lib/src/native/cocoa/binding.dart @@ -30112,12 +30112,6 @@ class SentryCocoa { ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); - late final _sel_captureReplay1 = _registerName1("captureReplay"); - late final _sel_getReplayId1 = _registerName1("getReplayId"); - late final _sel_addReplayIgnoreClasses_1 = - _registerName1("addReplayIgnoreClasses:"); - late final _sel_addReplayRedactClasses_1 = - _registerName1("addReplayRedactClasses:"); late final _class_SentryCurrentDateProvider1 = _getClass1("SentryCurrentDateProvider"); late final _sel_timezoneOffset1 = _registerName1("timezoneOffset"); @@ -70897,27 +70891,6 @@ class PrivateSentrySDKOnly extends NSObject { return SentryBreadcrumb._(_ret, _lib, retain: true, release: true); } - static void captureReplay(SentryCocoa _lib) { - _lib._objc_msgSend_1( - _lib._class_PrivateSentrySDKOnly1, _lib._sel_captureReplay1); - } - - static NSString getReplayId(SentryCocoa _lib) { - final _ret = _lib._objc_msgSend_20( - _lib._class_PrivateSentrySDKOnly1, _lib._sel_getReplayId1); - return NSString._(_ret, _lib, retain: true, release: true); - } - - static void addReplayIgnoreClasses_(SentryCocoa _lib, NSArray? classes) { - _lib._objc_msgSend_441(_lib._class_PrivateSentrySDKOnly1, - _lib._sel_addReplayIgnoreClasses_1, classes?._id ?? ffi.nullptr); - } - - static void addReplayRedactClasses_(SentryCocoa _lib, NSArray? classes) { - _lib._objc_msgSend_441(_lib._class_PrivateSentrySDKOnly1, - _lib._sel_addReplayRedactClasses_1, classes?._id ?? ffi.nullptr); - } - @override PrivateSentrySDKOnly init() { final _ret = _lib._objc_msgSend_2(_id, _lib._sel_init1); From 66e0270957648ac5354fdf20b2b2d9f8a589a8a7 Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Wed, 26 Jun 2024 15:16:50 +0200 Subject: [PATCH 227/237] Add api for pausing/resuming cocoa app hang tracking (#2134) * Add api * Add docs * Format * Update * Add test * Add test * Changelog * Add failure test * Swiftlint * typo fix * Update log message to include the function name --- CHANGELOG.md | 3 ++ .../Classes/SentryFlutterPluginApple.swift | 16 +++++++++ .../lib/src/native/sentry_native_binding.dart | 4 +++ .../lib/src/native/sentry_native_channel.dart | 8 +++++ flutter/lib/src/sentry_flutter.dart | 28 +++++++++++++++ flutter/test/mocks.mocks.dart | 20 +++++++++++ flutter/test/sentry_flutter_test.dart | 35 +++++++++++++++++++ flutter/test/sentry_native_channel_test.dart | 18 ++++++++++ 8 files changed, 132 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f40482e232..66c7f7f8c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ ### Features +- Add API for pausing/resuming **iOS** and **macOS** app hang tracking ([#2134](https://github.com/getsentry/sentry-dart/pull/2134)) + - This is useful to prevent the Cocoa SDK from reporting wrongly detected app hangs when the OS shows a system dialog for asking specific permissions. + - Use `SentryFlutter.pauseAppHangTracking()` and `SentryFlutter.resumeAppHangTracking()` - Capture total frames, frames delay, slow & frozen frames and attach to spans ([#2106](https://github.com/getsentry/sentry-dart/pull/2106)) - Support WebAssembly compilation (dart2wasm) ([#2113](https://github.com/getsentry/sentry-dart/pull/2113)) diff --git a/flutter/ios/Classes/SentryFlutterPluginApple.swift b/flutter/ios/Classes/SentryFlutterPluginApple.swift index cee6266564..35249ef5d1 100644 --- a/flutter/ios/Classes/SentryFlutterPluginApple.swift +++ b/flutter/ios/Classes/SentryFlutterPluginApple.swift @@ -168,6 +168,12 @@ public class SentryFlutterPluginApple: NSObject, FlutterPlugin { case "displayRefreshRate": displayRefreshRate(result) + case "pauseAppHangTracking": + pauseAppHangTracking(result) + + case "resumeAppHangTracking": + resumeAppHangTracking(result) + default: result(FlutterMethodNotImplemented) } @@ -713,6 +719,16 @@ public class SentryFlutterPluginApple: NSObject, FlutterPlugin { result(Int(mode.refreshRate)) } #endif + + private func pauseAppHangTracking(_ result: @escaping FlutterResult) { + SentrySDK.pauseAppHangTracking() + result("") + } + + private func resumeAppHangTracking(_ result: @escaping FlutterResult) { + SentrySDK.resumeAppHangTracking() + result("") + } } // swiftlint:enable function_body_length diff --git a/flutter/lib/src/native/sentry_native_binding.dart b/flutter/lib/src/native/sentry_native_binding.dart index 54223b5561..07ea5969fe 100644 --- a/flutter/lib/src/native/sentry_native_binding.dart +++ b/flutter/lib/src/native/sentry_native_binding.dart @@ -52,4 +52,8 @@ abstract class SentryNativeBinding { SentryId traceId, int startTimeNs, int endTimeNs); Future?> loadDebugImages(); + + Future pauseAppHangTracking(); + + Future resumeAppHangTracking(); } diff --git a/flutter/lib/src/native/sentry_native_channel.dart b/flutter/lib/src/native/sentry_native_channel.dart index e6888eecac..fe00683b0e 100644 --- a/flutter/lib/src/native/sentry_native_channel.dart +++ b/flutter/lib/src/native/sentry_native_channel.dart @@ -182,4 +182,12 @@ class SentryNativeChannel @override Future displayRefreshRate() => _channel.invokeMethod('displayRefreshRate'); + + @override + Future pauseAppHangTracking() => + _channel.invokeMethod('pauseAppHangTracking'); + + @override + Future resumeAppHangTracking() => + _channel.invokeMethod('resumeAppHangTracking'); } diff --git a/flutter/lib/src/sentry_flutter.dart b/flutter/lib/src/sentry_flutter.dart index 8cf3d995ba..4b0deb8541 100644 --- a/flutter/lib/src/sentry_flutter.dart +++ b/flutter/lib/src/sentry_flutter.dart @@ -236,6 +236,34 @@ mixin SentryFlutter { return SentryNavigatorObserver.timeToDisplayTracker?.reportFullyDisplayed(); } + /// Pauses the app hang tracking. + /// Only for iOS and macOS. + static Future pauseAppHangTracking() { + if (_native == null) { + // ignore: invalid_use_of_internal_member + Sentry.currentHub.options.logger( + SentryLevel.debug, + 'Native integration is not available. Make sure SentryFlutter is initialized before accessing the pauseAppHangTracking API.', + ); + return Future.value(); + } + return _native!.pauseAppHangTracking(); + } + + /// Resumes the app hang tracking. + /// Only for iOS and macOS + static Future resumeAppHangTracking() { + if (_native == null) { + // ignore: invalid_use_of_internal_member + Sentry.currentHub.options.logger( + SentryLevel.debug, + 'Native integration is not available. Make sure SentryFlutter is initialized before accessing the resumeAppHangTracking API.', + ); + return Future.value(); + } + return _native!.resumeAppHangTracking(); + } + @internal static SentryNativeBinding? get native => _native; diff --git a/flutter/test/mocks.mocks.dart b/flutter/test/mocks.mocks.dart index 7e595ab4cf..214b15b588 100644 --- a/flutter/test/mocks.mocks.dart +++ b/flutter/test/mocks.mocks.dart @@ -1320,6 +1320,26 @@ class MockSentryNativeBinding extends _i1.Mock ), returnValue: _i8.Future?>.value(), ) as _i8.Future?>); + + @override + _i8.Future pauseAppHangTracking() => (super.noSuchMethod( + Invocation.method( + #pauseAppHangTracking, + [], + ), + returnValue: _i8.Future.value(), + returnValueForMissingStub: _i8.Future.value(), + ) as _i8.Future); + + @override + _i8.Future resumeAppHangTracking() => (super.noSuchMethod( + Invocation.method( + #resumeAppHangTracking, + [], + ), + returnValue: _i8.Future.value(), + returnValueForMissingStub: _i8.Future.value(), + ) as _i8.Future); } /// A class which mocks [Hub]. diff --git a/flutter/test/sentry_flutter_test.dart b/flutter/test/sentry_flutter_test.dart index 0c9590dc92..3987cdfb7e 100644 --- a/flutter/test/sentry_flutter_test.dart +++ b/flutter/test/sentry_flutter_test.dart @@ -1,6 +1,7 @@ // ignore_for_file: invalid_use_of_internal_member import 'package:flutter_test/flutter_test.dart'; +import 'package:mockito/mockito.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:sentry/src/platform/platform.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; @@ -624,6 +625,40 @@ void main() { await Sentry.close(); }); }); + + test('resumeAppHangTracking calls native method when available', () async { + SentryFlutter.native = MockSentryNativeBinding(); + when(SentryFlutter.native?.resumeAppHangTracking()) + .thenAnswer((_) => Future.value()); + + await SentryFlutter.resumeAppHangTracking(); + + verify(SentryFlutter.native?.resumeAppHangTracking()).called(1); + }); + + test('resumeAppHangTracking does nothing when native is null', () async { + SentryFlutter.native = null; + + // This should complete without throwing an error + await expectLater(SentryFlutter.resumeAppHangTracking(), completes); + }); + + test('pauseAppHangTracking calls native method when available', () async { + SentryFlutter.native = MockSentryNativeBinding(); + when(SentryFlutter.native?.pauseAppHangTracking()) + .thenAnswer((_) => Future.value()); + + await SentryFlutter.pauseAppHangTracking(); + + verify(SentryFlutter.native?.pauseAppHangTracking()).called(1); + }); + + test('pauseAppHangTracking does nothing when native is null', () async { + SentryFlutter.native = null; + + // This should complete without throwing an error + await expectLater(SentryFlutter.pauseAppHangTracking(), completes); + }); } void appRunner() {} diff --git a/flutter/test/sentry_native_channel_test.dart b/flutter/test/sentry_native_channel_test.dart index 6a10400d3c..cc2e67dfd5 100644 --- a/flutter/test/sentry_native_channel_test.dart +++ b/flutter/test/sentry_native_channel_test.dart @@ -284,6 +284,24 @@ void main() { expect(data?.map((v) => v.toJson()), json); }); + + test('pauseAppHangTracking', () async { + when(channel.invokeMethod('pauseAppHangTracking')) + .thenAnswer((_) => Future.value()); + + await sut.pauseAppHangTracking(); + + verify(channel.invokeMethod('pauseAppHangTracking')); + }); + + test('resumeAppHangTracking', () async { + when(channel.invokeMethod('resumeAppHangTracking')) + .thenAnswer((_) => Future.value()); + + await sut.resumeAppHangTracking(); + + verify(channel.invokeMethod('resumeAppHangTracking')); + }); }); } } From 2d125d38b75e68a216b9f785927eb9e51aece6c8 Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Wed, 26 Jun 2024 15:37:18 +0200 Subject: [PATCH 228/237] fix changelog Cocoa dependency bump to v8.30.0 (#2135) --- CHANGELOG.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 66c7f7f8c0..219a11d0a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,9 +16,9 @@ ### Dependencies -- Bump Cocoa SDK from v8.29.0 to v8.29.1 ([#2109](https://github.com/getsentry/sentry-dart/pull/2109)) - - [changelog](https://github.com/getsentry/sentry-cocoa/blob/main/CHANGELOG.md#8291) - - [diff](https://github.com/getsentry/sentry-cocoa/compare/8.29.0...8.29.1) +- Bump Cocoa SDK from v8.29.0 to v8.30.0 ([#2132](https://github.com/getsentry/sentry-dart/pull/2132)) + - [changelog](https://github.com/getsentry/sentry-cocoa/blob/main/CHANGELOG.md#8300) + - [diff](https://github.com/getsentry/sentry-cocoa/compare/8.29.0...8.30.0) ## 8.3.0 From d20b8677a5f76aec2dc467d1cf2cfb3a0be21464 Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Thu, 4 Jul 2024 10:18:16 +0200 Subject: [PATCH 229/237] Update .craft.yml to include skipValidation (#2138) * Update .craft.yml to include skipValidation * Add comments * bump craft version --------- Co-authored-by: Ivan Dlugos <6349682+vaind@users.noreply.github.com> --- .craft.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.craft.yml b/.craft.yml index 5ff7ad5d33..51ef0dd728 100644 --- a/.craft.yml +++ b/.craft.yml @@ -1,9 +1,12 @@ -minVersion: 0.29.2 +minVersion: 1.21.0 changelogPolicy: auto artifactProvider: name: none targets: - name: pub-dev + # This is temporarily needed because we keep the package:web dependency implicit + # See https://github.com/getsentry/sentry-dart/pull/2113 for more context + skipValidation: true packages: dart: flutter: From 05fdc9a22496610edf1153f46b3dacf97a323999 Mon Sep 17 00:00:00 2001 From: getsentry-bot Date: Thu, 4 Jul 2024 13:48:55 +0000 Subject: [PATCH 230/237] release: 8.4.0-beta.1 --- CHANGELOG.md | 2 +- dart/lib/src/version.dart | 2 +- dart/pubspec.yaml | 2 +- dio/lib/src/version.dart | 2 +- dio/pubspec.yaml | 4 ++-- drift/lib/src/version.dart | 2 +- drift/pubspec.yaml | 4 ++-- file/lib/src/version.dart | 2 +- file/pubspec.yaml | 4 ++-- flutter/example/pubspec.yaml | 2 +- flutter/lib/src/version.dart | 2 +- flutter/pubspec.yaml | 4 ++-- hive/lib/src/version.dart | 2 +- hive/pubspec.yaml | 4 ++-- isar/lib/src/version.dart | 2 +- isar/pubspec.yaml | 4 ++-- logging/lib/src/version.dart | 2 +- logging/pubspec.yaml | 4 ++-- sqflite/lib/src/version.dart | 2 +- sqflite/pubspec.yaml | 4 ++-- 20 files changed, 28 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 219a11d0a8..d9d73810fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## Unreleased +## 8.4.0-beta.1 ### Features diff --git a/dart/lib/src/version.dart b/dart/lib/src/version.dart index 961566fdc3..33e5ba6503 100644 --- a/dart/lib/src/version.dart +++ b/dart/lib/src/version.dart @@ -9,7 +9,7 @@ library version; /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.3.0'; +const String sdkVersion = '8.4.0-beta.1'; String sdkName(bool isWeb) => isWeb ? _browserSdkName : _ioSdkName; diff --git a/dart/pubspec.yaml b/dart/pubspec.yaml index 9e63a7b079..bfe40f38c2 100644 --- a/dart/pubspec.yaml +++ b/dart/pubspec.yaml @@ -1,5 +1,5 @@ name: sentry -version: 8.3.0 +version: 8.4.0-beta.1 description: > A crash reporting library for Dart that sends crash reports to Sentry.io. This library supports Dart VM and Web. For Flutter consider sentry_flutter instead. diff --git a/dio/lib/src/version.dart b/dio/lib/src/version.dart index 4b219aa09a..b6552c547c 100644 --- a/dio/lib/src/version.dart +++ b/dio/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.3.0'; +const String sdkVersion = '8.4.0-beta.1'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_dio'; diff --git a/dio/pubspec.yaml b/dio/pubspec.yaml index b4865df495..690af6b9ab 100644 --- a/dio/pubspec.yaml +++ b/dio/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_dio description: An integration which adds support for performance tracing for the Dio package. -version: 8.3.0 +version: 8.4.0-beta.1 homepage: https://docs.sentry.io/platforms/dart/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -19,7 +19,7 @@ platforms: dependencies: dio: ^5.0.0 - sentry: 8.3.0 + sentry: 8.4.0-beta.1 dev_dependencies: meta: ^1.3.0 diff --git a/drift/lib/src/version.dart b/drift/lib/src/version.dart index f56b0af46f..ae721deab9 100644 --- a/drift/lib/src/version.dart +++ b/drift/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.3.0'; +const String sdkVersion = '8.4.0-beta.1'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_drift'; diff --git a/drift/pubspec.yaml b/drift/pubspec.yaml index b3a529de9c..ef7f846b6a 100644 --- a/drift/pubspec.yaml +++ b/drift/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_drift description: An integration which adds support for performance tracing for the drift package. -version: 8.3.0 +version: 8.4.0-beta.1 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -17,7 +17,7 @@ platforms: web: dependencies: - sentry: 8.3.0 + sentry: 8.4.0-beta.1 meta: ^1.3.0 drift: ^2.13.0 diff --git a/file/lib/src/version.dart b/file/lib/src/version.dart index 6e9dc3050c..d30a72a6e7 100644 --- a/file/lib/src/version.dart +++ b/file/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.3.0'; +const String sdkVersion = '8.4.0-beta.1'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_file'; diff --git a/file/pubspec.yaml b/file/pubspec.yaml index 9a2027e8c7..17417ab6d3 100644 --- a/file/pubspec.yaml +++ b/file/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_file description: An integration which adds support for performance tracing for dart.io.File. -version: 8.3.0 +version: 8.4.0-beta.1 homepage: https://docs.sentry.io/platforms/dart/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -17,7 +17,7 @@ platforms: windows: dependencies: - sentry: 8.3.0 + sentry: 8.4.0-beta.1 meta: ^1.3.0 dev_dependencies: diff --git a/flutter/example/pubspec.yaml b/flutter/example/pubspec.yaml index 1f53f5d1c3..73988305ce 100644 --- a/flutter/example/pubspec.yaml +++ b/flutter/example/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_flutter_example description: Demonstrates how to use the sentry_flutter plugin. -version: 8.3.0 +version: 8.4.0-beta.1 publish_to: 'none' # Remove this line if you wish to publish to pub.dev diff --git a/flutter/lib/src/version.dart b/flutter/lib/src/version.dart index 0a431dd2de..c28ec2f5eb 100644 --- a/flutter/lib/src/version.dart +++ b/flutter/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.3.0'; +const String sdkVersion = '8.4.0-beta.1'; /// The default SDK name reported to Sentry.io in the submitted events. const String sdkName = 'sentry.dart.flutter'; diff --git a/flutter/pubspec.yaml b/flutter/pubspec.yaml index d2a244f171..5c3c03d051 100644 --- a/flutter/pubspec.yaml +++ b/flutter/pubspec.yaml @@ -1,5 +1,5 @@ name: sentry_flutter -version: 8.3.0 +version: 8.4.0-beta.1 description: Sentry SDK for Flutter. This package aims to support different Flutter targets by relying on the many platforms supported by Sentry with native SDKs. homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart @@ -23,7 +23,7 @@ dependencies: sdk: flutter flutter_web_plugins: sdk: flutter - sentry: 8.3.0 + sentry: 8.4.0-beta.1 package_info_plus: '>=1.0.0' meta: ^1.3.0 ffi: ^2.0.0 diff --git a/hive/lib/src/version.dart b/hive/lib/src/version.dart index 18932a8818..315e1edcf1 100644 --- a/hive/lib/src/version.dart +++ b/hive/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.3.0'; +const String sdkVersion = '8.4.0-beta.1'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_hive'; diff --git a/hive/pubspec.yaml b/hive/pubspec.yaml index a065329ce4..17d431741d 100644 --- a/hive/pubspec.yaml +++ b/hive/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_hive description: An integration which adds support for performance tracing for the hive package. -version: 8.3.0 +version: 8.4.0-beta.1 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -17,7 +17,7 @@ platforms: web: dependencies: - sentry: 8.3.0 + sentry: 8.4.0-beta.1 hive: ^2.2.3 meta: ^1.3.0 diff --git a/isar/lib/src/version.dart b/isar/lib/src/version.dart index c215620372..ada16a7695 100644 --- a/isar/lib/src/version.dart +++ b/isar/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.3.0'; +const String sdkVersion = '8.4.0-beta.1'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_isar'; diff --git a/isar/pubspec.yaml b/isar/pubspec.yaml index cbafa2af80..dd7730269c 100644 --- a/isar/pubspec.yaml +++ b/isar/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_isar description: An integration which adds support for performance tracing for the isar package. -version: 8.3.0 +version: 8.4.0-beta.1 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -20,7 +20,7 @@ platforms: dependencies: isar: ^3.1.0 isar_flutter_libs: ^3.1.0 # contains Isar Core - sentry: 8.3.0 + sentry: 8.4.0-beta.1 meta: ^1.3.0 path: ^1.8.3 diff --git a/logging/lib/src/version.dart b/logging/lib/src/version.dart index 58dbea03c7..618089c0f9 100644 --- a/logging/lib/src/version.dart +++ b/logging/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.3.0'; +const String sdkVersion = '8.4.0-beta.1'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_logging'; diff --git a/logging/pubspec.yaml b/logging/pubspec.yaml index 80b484da48..70fd7fa71d 100644 --- a/logging/pubspec.yaml +++ b/logging/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_logging description: An integration which adds support for recording log from the logging package. -version: 8.3.0 +version: 8.4.0-beta.1 homepage: https://docs.sentry.io/platforms/dart/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -19,7 +19,7 @@ platforms: dependencies: logging: ^1.0.0 - sentry: 8.3.0 + sentry: 8.4.0-beta.1 dev_dependencies: lints: ^4.0.0 diff --git a/sqflite/lib/src/version.dart b/sqflite/lib/src/version.dart index a74f25cdbd..4d02ffa9c3 100644 --- a/sqflite/lib/src/version.dart +++ b/sqflite/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.3.0'; +const String sdkVersion = '8.4.0-beta.1'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_sqflite'; diff --git a/sqflite/pubspec.yaml b/sqflite/pubspec.yaml index b8449f13f7..b6575b0a45 100644 --- a/sqflite/pubspec.yaml +++ b/sqflite/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_sqflite description: An integration which adds support for performance tracing for the sqflite package. -version: 8.3.0 +version: 8.4.0-beta.1 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -15,7 +15,7 @@ platforms: macos: dependencies: - sentry: 8.3.0 + sentry: 8.4.0-beta.1 sqflite: ^2.2.8 sqflite_common: ^2.0.0 meta: ^1.3.0 From 89113313e498e8582b9a530d12ab44e62024af7c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Jul 2024 11:11:56 +0200 Subject: [PATCH 231/237] build(deps): bump dart-lang/setup-dart from 1.6.4 to 1.6.5 (#2143) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.6.4 to 1.6.5. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/f0ead981b4d9a35b37f30d36160575d60931ec30...0a8a0fc875eb934c15d08629302413c671d3f672) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/analyze.yml | 2 +- .github/workflows/diagrams.yml | 2 +- .github/workflows/e2e_dart.yml | 2 +- .github/workflows/flutter-symbols.yml | 4 ++-- .github/workflows/format-and-fix.yml | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/analyze.yml b/.github/workflows/analyze.yml index fa3ef62068..5ae2d469a1 100644 --- a/.github/workflows/analyze.yml +++ b/.github/workflows/analyze.yml @@ -32,7 +32,7 @@ jobs: working-directory: ${{ inputs.package }} steps: - uses: actions/checkout@v4 - - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 # pin@v1 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 # pin@v1 if: ${{ inputs.sdk == 'dart' }} - uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 # pin@v2.16.0 if: ${{ inputs.sdk == 'flutter' }} diff --git a/.github/workflows/diagrams.yml b/.github/workflows/diagrams.yml index f78d5bbb67..19f35ee46f 100644 --- a/.github/workflows/diagrams.yml +++ b/.github/workflows/diagrams.yml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-latest name: "Create class diagrams of all packages" steps: - - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 # pin@v1 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 # pin@v1 with: sdk: stable diff --git a/.github/workflows/e2e_dart.yml b/.github/workflows/e2e_dart.yml index 00f52cc0f3..4329e6d29c 100644 --- a/.github/workflows/e2e_dart.yml +++ b/.github/workflows/e2e_dart.yml @@ -37,7 +37,7 @@ jobs: matrix: sdk: [stable, beta] steps: - - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 # pin@v1 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 # pin@v1 with: sdk: ${{ matrix.sdk }} - uses: actions/checkout@v4 diff --git a/.github/workflows/flutter-symbols.yml b/.github/workflows/flutter-symbols.yml index 5eb867b755..ec374f551f 100644 --- a/.github/workflows/flutter-symbols.yml +++ b/.github/workflows/flutter-symbols.yml @@ -21,7 +21,7 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 # pin@v1 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 # pin@v1 - run: dart pub get @@ -33,7 +33,7 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 # pin@v1 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 # pin@v1 - run: dart pub get diff --git a/.github/workflows/format-and-fix.yml b/.github/workflows/format-and-fix.yml index 8d9ab178f5..e58b9bde7f 100644 --- a/.github/workflows/format-and-fix.yml +++ b/.github/workflows/format-and-fix.yml @@ -30,7 +30,7 @@ jobs: working-directory: ${{ matrix.package.name }} steps: - uses: actions/checkout@v4 - - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 # pin@v1 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 # pin@v1 if: ${{ matrix.package.sdk == 'dart' }} - uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 # pin@v2.16.0 if: ${{ matrix.package.sdk == 'flutter' }} From c614bf94132292e294ce4e1678c356ab59aa80b5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Jul 2024 11:17:43 +0200 Subject: [PATCH 232/237] build(deps): bump ruby/setup-ruby from 1.180.1 to 1.183.0 (#2142) Bumps [ruby/setup-ruby](https://github.com/ruby/setup-ruby) from 1.180.1 to 1.183.0. - [Release notes](https://github.com/ruby/setup-ruby/releases) - [Changelog](https://github.com/ruby/setup-ruby/blob/master/release.rb) - [Commits](https://github.com/ruby/setup-ruby/compare/3783f195e29b74ae398d7caca108814bbafde90e...1d0e911f615a112e322369596f10ee0b95b010ae) --- updated-dependencies: - dependency-name: ruby/setup-ruby dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Giancarlo Buenaflor --- .github/workflows/testflight.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/testflight.yml b/.github/workflows/testflight.yml index 4f69c558f8..7841713505 100644 --- a/.github/workflows/testflight.yml +++ b/.github/workflows/testflight.yml @@ -16,7 +16,7 @@ jobs: - uses: actions/checkout@v4 - uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 # pin@v2.16.0 - run: xcodes select 15.0.1 - - uses: ruby/setup-ruby@3783f195e29b74ae398d7caca108814bbafde90e # pin@v1.180.1 + - uses: ruby/setup-ruby@1d0e911f615a112e322369596f10ee0b95b010ae # pin@v1.183.0 with: ruby-version: '2.7.5' bundler-cache: true From f172c4de11085065216c98124283effeb0d0f15e Mon Sep 17 00:00:00 2001 From: Giancarlo Buenaflor Date: Mon, 8 Jul 2024 14:35:00 +0200 Subject: [PATCH 233/237] fix: app starts hanging for 30s (#2140) * Update * Update * Add CHANGELOG * Update comment * Update CHANGELOG.md --- CHANGELOG.md | 8 +++++ .../native_app_start_event_processor.dart | 6 ++-- .../native_app_start_integration.dart | 5 ++- .../native_app_start_integration_test.dart | 33 +++++++++++++++++-- 4 files changed, 46 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d9d73810fe..a6a26c1553 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## Unreleased + +### Fixes + +- App starts hanging for 30s ([#2140](https://github.com/getsentry/sentry-dart/pull/2140)) + - Time out for app start info retrieval has been reduced to 10s + - If `autoAppStarts` is `false` and `setAppStartEnd` has not been called, the app start event processor will now return early instead of waiting for `getAppStartInfo` to finish + ## 8.4.0-beta.1 ### Features diff --git a/flutter/lib/src/event_processor/native_app_start_event_processor.dart b/flutter/lib/src/event_processor/native_app_start_event_processor.dart index 87066aa271..a0da42359e 100644 --- a/flutter/lib/src/event_processor/native_app_start_event_processor.dart +++ b/flutter/lib/src/event_processor/native_app_start_event_processor.dart @@ -24,16 +24,18 @@ class NativeAppStartEventProcessor implements EventProcessor { return event; } - final appStartInfo = await NativeAppStartIntegration.getAppStartInfo(); - + AppStartInfo? appStartInfo; if (!options.autoAppStart) { final appStartEnd = NativeAppStartIntegration.appStartEnd; if (appStartEnd != null) { + appStartInfo = await NativeAppStartIntegration.getAppStartInfo(); appStartInfo?.end = appStartEnd; } else { // If autoAppStart is disabled and appStartEnd is not set, we can't add app starts return event; } + } else { + appStartInfo = await NativeAppStartIntegration.getAppStartInfo(); } final measurement = appStartInfo?.toMeasurement(); diff --git a/flutter/lib/src/integrations/native_app_start_integration.dart b/flutter/lib/src/integrations/native_app_start_integration.dart index c76874d19f..af747dbf36 100644 --- a/flutter/lib/src/integrations/native_app_start_integration.dart +++ b/flutter/lib/src/integrations/native_app_start_integration.dart @@ -34,7 +34,10 @@ class NativeAppStartIntegration extends Integration { static bool didAddAppStartMeasurement = false; /// Timeout duration to wait for the app start info to be fetched. - static const _timeoutDuration = Duration(seconds: 30); + static const _timeoutDuration = Duration(seconds: 10); + + @visibleForTesting + static Duration get timeoutDuration => _timeoutDuration; /// We filter out App starts more than 60s static const _maxAppStartMillis = 60000; diff --git a/flutter/test/integrations/native_app_start_integration_test.dart b/flutter/test/integrations/native_app_start_integration_test.dart index c472b0fa60..707163c790 100644 --- a/flutter/test/integrations/native_app_start_integration_test.dart +++ b/flutter/test/integrations/native_app_start_integration_test.dart @@ -146,6 +146,30 @@ void main() { expect(enriched.spans.isEmpty, true); }); + test( + 'does not trigger timeout if autoAppStart is false and setAppStartEnd is not called', + () async { + // setting a frame callback with a bigger timeout than our app start timeout so the timeout would theoretically be triggered + fixture = Fixture( + frameCallbackTimeout: NativeAppStartIntegration.timeoutDuration + + const Duration(seconds: 5)); + fixture.options.autoAppStart = false; + + await fixture.registerIntegration(); + + final tracer = fixture.createTracer(); + final transaction = SentryTransaction(tracer); + + final processor = fixture.options.eventProcessors.first; + + final stopwatch = Stopwatch()..start(); + await processor.apply(transaction, Hint()) as SentryTransaction; + stopwatch.stop(); + + expect(stopwatch.elapsed < NativeAppStartIntegration.timeoutDuration, + isTrue); + }); + test( 'autoAppStart is false and appStartEnd is set adds app start measurement', () async { @@ -384,9 +408,12 @@ class Fixture extends IntegrationTestFixture { @override MockHub get hub => super.hub as MockHub; - Fixture() - : super((binding) => - NativeAppStartIntegration(binding, FakeFrameCallbackHandler())) { + Fixture({Duration? frameCallbackTimeout}) + : super((binding) => NativeAppStartIntegration( + binding, + FakeFrameCallbackHandler( + finishAfterDuration: frameCallbackTimeout ?? + const Duration(milliseconds: 50)))) { NativeAppStartIntegration.reset(); hub = MockHub(); // ignore: invalid_use_of_internal_member From 9f9dd525e2e259c65148ab57edb92eed23acb995 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20Andra=C5=A1ec?= Date: Tue, 9 Jul 2024 08:34:15 +0000 Subject: [PATCH 234/237] Add memory usage to contexts (#2133) --- CHANGELOG.md | 5 + .../enricher/io_enricher_event_processor.dart | 24 +++- .../enricher/io_platform_memory.dart | 108 ++++++++++++++++++ .../enricher/io_platform_memory_test.dart | 60 ++++++++++ 4 files changed, 192 insertions(+), 5 deletions(-) create mode 100644 dart/lib/src/event_processor/enricher/io_platform_memory.dart create mode 100644 dart/test/event_processor/enricher/io_platform_memory_test.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index a6a26c1553..9d024ca890 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ ## Unreleased +### Features + +- Add memory usage to contexts ([#2133](https://github.com/getsentry/sentry-dart/pull/2133)) + - Only for Linux/Windows applications, as iOS/Android/macOS use native SDKs + ### Fixes - App starts hanging for 30s ([#2140](https://github.com/getsentry/sentry-dart/pull/2140)) diff --git a/dart/lib/src/event_processor/enricher/io_enricher_event_processor.dart b/dart/lib/src/event_processor/enricher/io_enricher_event_processor.dart index 52243a8572..63304cdbf6 100644 --- a/dart/lib/src/event_processor/enricher/io_enricher_event_processor.dart +++ b/dart/lib/src/event_processor/enricher/io_enricher_event_processor.dart @@ -2,6 +2,7 @@ import 'dart:io'; import '../../../sentry.dart'; import 'enricher_event_processor.dart'; +import 'io_platform_memory.dart'; EnricherEventProcessor enricherEventProcessor(SentryOptions options) { return IoEnricherEventProcessor(options); @@ -17,25 +18,29 @@ class IoEnricherEventProcessor implements EnricherEventProcessor { @override SentryEvent? apply(SentryEvent event, Hint hint) { + // Amend app with current memory usage, as this is not available on native. + final app = _getApp(event.contexts.app); + // If there's a native integration available, it probably has better // information available than Flutter. - final os = _options.platformChecker.hasNativeIntegration - ? null - : _getOperatingSystem(event.contexts.operatingSystem); - final device = _options.platformChecker.hasNativeIntegration ? null : _getDevice(event.contexts.device); + final os = _options.platformChecker.hasNativeIntegration + ? null + : _getOperatingSystem(event.contexts.operatingSystem); + final culture = _options.platformChecker.hasNativeIntegration ? null : _getSentryCulture(event.contexts.culture); final contexts = event.contexts.copyWith( - operatingSystem: os, device: device, + operatingSystem: os, runtimes: _getRuntimes(event.contexts.runtimes), + app: app, culture: culture, ); @@ -97,9 +102,18 @@ class IoEnricherEventProcessor implements EnricherEventProcessor { } SentryDevice _getDevice(SentryDevice? device) { + final platformMemory = PlatformMemory(_options); return (device ?? SentryDevice()).copyWith( name: device?.name ?? Platform.localHostname, processorCount: device?.processorCount ?? Platform.numberOfProcessors, + memorySize: device?.memorySize ?? platformMemory.getTotalPhysicalMemory(), + freeMemory: device?.freeMemory ?? platformMemory.getFreePhysicalMemory(), + ); + } + + SentryApp _getApp(SentryApp? app) { + return (app ?? SentryApp()).copyWith( + appMemory: app?.appMemory ?? ProcessInfo.currentRss, ); } diff --git a/dart/lib/src/event_processor/enricher/io_platform_memory.dart b/dart/lib/src/event_processor/enricher/io_platform_memory.dart new file mode 100644 index 0000000000..4acde3f15b --- /dev/null +++ b/dart/lib/src/event_processor/enricher/io_platform_memory.dart @@ -0,0 +1,108 @@ +import 'dart:io'; + +import '../../protocol.dart'; +import '../../sentry_options.dart'; + +// Get total & free platform memory (in bytes) for linux and windows operating systems. +// Source: https://github.com/onepub-dev/system_info/blob/8a9bf6b8eb7c86a09b3c3df4bf6d7fa5a6b50732/lib/src/platform/memory.dart +class PlatformMemory { + PlatformMemory(this.options); + + final SentryOptions options; + + int? getTotalPhysicalMemory() { + if (options.platformChecker.platform.isLinux) { + return _getLinuxMemInfoValue('MemTotal'); + } else if (options.platformChecker.platform.isWindows) { + return _getWindowsWmicValue('ComputerSystem', 'TotalPhysicalMemory'); + } else { + return null; + } + } + + int? getFreePhysicalMemory() { + if (options.platformChecker.platform.isLinux) { + return _getLinuxMemInfoValue('MemFree'); + } else if (options.platformChecker.platform.isWindows) { + return _getWindowsWmicValue('OS', 'FreePhysicalMemory'); + } else { + return null; + } + } + + int? _getWindowsWmicValue(String section, String key) { + final os = _wmicGetValueAsMap(section, [key]); + final totalPhysicalMemoryValue = os?[key]; + if (totalPhysicalMemoryValue == null) { + return null; + } + final size = int.tryParse(totalPhysicalMemoryValue); + if (size == null) { + return null; + } + return size; + } + + int? _getLinuxMemInfoValue(String key) { + final meminfoList = _exec('cat', ['/proc/meminfo']) + ?.trim() + .replaceAll('\r\n', '\n') + .split('\n') ?? + []; + + final meminfoMap = _listToMap(meminfoList, ':'); + final memsizeResults = meminfoMap[key]?.split(' ') ?? []; + + if (memsizeResults.isEmpty) { + return null; + } + final memsizeResult = memsizeResults.first; + + final memsize = int.tryParse(memsizeResult); + if (memsize == null) { + return null; + } + return memsize; + } + + String? _exec(String executable, List arguments, + {bool runInShell = false}) { + try { + final result = + Process.runSync(executable, arguments, runInShell: runInShell); + if (result.exitCode == 0) { + return result.stdout.toString(); + } + } catch (e) { + options.logger(SentryLevel.warning, "Failed to run process: $e"); + } + return null; + } + + Map? _wmicGetValueAsMap(String section, List fields) { + final arguments = [section]; + arguments + ..add('get') + ..addAll(fields.join(', ').split(' ')) + ..add('/VALUE'); + + final list = + _exec('wmic', arguments)?.trim().replaceAll('\r\n', '\n').split('\n') ?? + []; + + return _listToMap(list, '='); + } + + Map _listToMap(List list, String separator) { + final map = {}; + for (final string in list) { + final index = string.indexOf(separator); + if (index != -1) { + final key = string.substring(0, index).trim(); + final value = string.substring(index + 1).trim(); + map[key] = value; + } + } + return map; + } +} diff --git a/dart/test/event_processor/enricher/io_platform_memory_test.dart b/dart/test/event_processor/enricher/io_platform_memory_test.dart new file mode 100644 index 0000000000..0f987b935c --- /dev/null +++ b/dart/test/event_processor/enricher/io_platform_memory_test.dart @@ -0,0 +1,60 @@ +@TestOn('vm') +library dart_test; + +import 'dart:io'; + +import 'package:sentry/sentry.dart'; +import 'package:sentry/src/event_processor/enricher/io_platform_memory.dart'; +import 'package:test/test.dart'; + +void main() { + late Fixture fixture; + + setUp(() { + fixture = Fixture(); + }); + + test('total physical memory', () { + final sut = fixture.getSut(); + final totalPhysicalMemory = sut.getTotalPhysicalMemory(); + + switch (Platform.operatingSystem) { + case 'linux': + expect(totalPhysicalMemory, isNotNull); + expect(totalPhysicalMemory! > 0, true); + break; + case 'windows': + expect(totalPhysicalMemory, isNotNull); + expect(totalPhysicalMemory! > 0, true); + break; + default: + expect(totalPhysicalMemory, isNull); + } + }); + + test('free physical memory', () { + final sut = fixture.getSut(); + final freePhysicalMemory = sut.getTotalPhysicalMemory(); + + switch (Platform.operatingSystem) { + case 'linux': + expect(freePhysicalMemory, isNotNull); + expect(freePhysicalMemory! > 0, true); + break; + case 'windows': + expect(freePhysicalMemory, isNotNull); + expect(freePhysicalMemory! > 0, true); + break; + default: + expect(freePhysicalMemory, isNull); + } + }); +} + +class Fixture { + var options = SentryOptions(); + + PlatformMemory getSut() { + return PlatformMemory(options); + } +} From df36ae7d02bfb211069b279c9876c71fc99ff13e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Jul 2024 13:55:05 +0200 Subject: [PATCH 235/237] build(deps): bump ruby/setup-ruby from 1.183.0 to 1.185.0 (#2151) Bumps [ruby/setup-ruby](https://github.com/ruby/setup-ruby) from 1.183.0 to 1.185.0. - [Release notes](https://github.com/ruby/setup-ruby/releases) - [Changelog](https://github.com/ruby/setup-ruby/blob/master/release.rb) - [Commits](https://github.com/ruby/setup-ruby/compare/1d0e911f615a112e322369596f10ee0b95b010ae...3a77c29278ae80936b4cb030fefc7d21c96c786f) --- updated-dependencies: - dependency-name: ruby/setup-ruby dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/testflight.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/testflight.yml b/.github/workflows/testflight.yml index 7841713505..0cac9d620f 100644 --- a/.github/workflows/testflight.yml +++ b/.github/workflows/testflight.yml @@ -16,7 +16,7 @@ jobs: - uses: actions/checkout@v4 - uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 # pin@v2.16.0 - run: xcodes select 15.0.1 - - uses: ruby/setup-ruby@1d0e911f615a112e322369596f10ee0b95b010ae # pin@v1.183.0 + - uses: ruby/setup-ruby@3a77c29278ae80936b4cb030fefc7d21c96c786f # pin@v1.185.0 with: ruby-version: '2.7.5' bundler-cache: true From 3d305b96e5469a711cd2c67191b28bbcd997ca41 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 9 Jul 2024 17:41:17 +0200 Subject: [PATCH 236/237] chore(deps): update Android SDK to v7.11.0 (#2144) * chore: update flutter/scripts/update-android.sh to 7.11.0 * Fix capture envelope in SentryFlutterPlugin.kt * Revert SentryFlutterPlugin.kt to previous commit * Add info for unhandled exception * Update * Update * Update * Update mocks * Update * Format * Add test cases * naming * formatting --------- Co-authored-by: GitHub Co-authored-by: Krystof Woldrich <31292499+krystofwoldrich@users.noreply.github.com> Co-authored-by: GIancarlo Buenaflor --- CHANGELOG.md | 3 + dart/lib/src/sentry_envelope.dart | 17 ++++- dart/test/mocks/mock_envelope.dart | 3 + flutter/android/build.gradle | 2 +- .../io/sentry/flutter/SentryFlutterPlugin.kt | 5 +- flutter/lib/src/file_system_transport.dart | 3 +- .../lib/src/native/sentry_native_binding.dart | 3 +- .../lib/src/native/sentry_native_channel.dart | 7 ++- flutter/test/file_system_transport_test.dart | 62 +++++++++++++++++-- flutter/test/mocks.mocks.dart | 10 ++- flutter/test/sentry_native_channel_test.dart | 2 +- 11 files changed, 102 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d024ca890..54158f6b4b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,9 @@ - Bump Cocoa SDK from v8.29.0 to v8.30.0 ([#2132](https://github.com/getsentry/sentry-dart/pull/2132)) - [changelog](https://github.com/getsentry/sentry-cocoa/blob/main/CHANGELOG.md#8300) - [diff](https://github.com/getsentry/sentry-cocoa/compare/8.29.0...8.30.0) +- Bump Android SDK from v7.10.0 to v7.11.0 ([#2144](https://github.com/getsentry/sentry-dart/pull/2144)) + - [changelog](https://github.com/getsentry/sentry-java/blob/main/CHANGELOG.md#7110) + - [diff](https://github.com/getsentry/sentry-java/compare/7.10.0...7.11.0) ## 8.3.0 diff --git a/dart/lib/src/sentry_envelope.dart b/dart/lib/src/sentry_envelope.dart index 7835b7859e..fb7cd1543a 100644 --- a/dart/lib/src/sentry_envelope.dart +++ b/dart/lib/src/sentry_envelope.dart @@ -13,7 +13,8 @@ import 'sentry_user_feedback.dart'; /// Class representation of `Envelope` file. class SentryEnvelope { - SentryEnvelope(this.header, this.items); + SentryEnvelope(this.header, this.items, + {this.containsUnhandledException = false}); /// Header describing envelope content. final SentryEnvelopeHeader header; @@ -21,6 +22,10 @@ class SentryEnvelope { /// All items contained in the envelope. final List items; + /// Whether the envelope contains an unhandled exception. + /// This is used to determine if the native SDK should start a new session. + final bool containsUnhandledException; + /// Create a [SentryEnvelope] containing one [SentryEnvelopeItem] which holds the [SentryEvent] data. factory SentryEnvelope.fromEvent( SentryEvent event, @@ -29,6 +34,15 @@ class SentryEnvelope { SentryTraceContextHeader? traceContext, List? attachments, }) { + bool containsUnhandledException = false; + + if (event.exceptions != null && event.exceptions!.isNotEmpty) { + // Check all exceptions for any unhandled ones + containsUnhandledException = event.exceptions!.any((exception) { + return exception.mechanism?.handled == false; + }); + } + return SentryEnvelope( SentryEnvelopeHeader( event.eventId, @@ -41,6 +55,7 @@ class SentryEnvelope { if (attachments != null) ...attachments.map((e) => SentryEnvelopeItem.fromAttachment(e)) ], + containsUnhandledException: containsUnhandledException, ); } diff --git a/dart/test/mocks/mock_envelope.dart b/dart/test/mocks/mock_envelope.dart index 9b43a41b8a..1009f2e396 100644 --- a/dart/test/mocks/mock_envelope.dart +++ b/dart/test/mocks/mock_envelope.dart @@ -23,4 +23,7 @@ class MockEnvelope implements SentryEnvelope { @override List items = []; + + @override + bool get containsUnhandledException => false; } diff --git a/flutter/android/build.gradle b/flutter/android/build.gradle index 89146e73ff..3242dddd64 100644 --- a/flutter/android/build.gradle +++ b/flutter/android/build.gradle @@ -60,7 +60,7 @@ android { } dependencies { - api 'io.sentry:sentry-android:7.10.0' + api 'io.sentry:sentry-android:7.11.0' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" // Required -- JUnit 4 framework diff --git a/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutterPlugin.kt b/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutterPlugin.kt index 26b84a6f5d..4f154a2465 100644 --- a/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutterPlugin.kt +++ b/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutterPlugin.kt @@ -355,8 +355,9 @@ class SentryFlutterPlugin : FlutterPlugin, MethodCallHandler, ActivityAware { val args = call.arguments() as List? ?: listOf() if (args.isNotEmpty()) { val event = args.first() as ByteArray? - if (event != null && event.isNotEmpty()) { - val id = InternalSentrySdk.captureEnvelope(event) + val containsUnhandledException = args[1] as Boolean + if (event != null && event.isNotEmpty() && containsUnhandledException != null) { + val id = InternalSentrySdk.captureEnvelope(event, containsUnhandledException) if (id != null) { result.success("") } else { diff --git a/flutter/lib/src/file_system_transport.dart b/flutter/lib/src/file_system_transport.dart index 9b7ace7dee..85cc0947a7 100644 --- a/flutter/lib/src/file_system_transport.dart +++ b/flutter/lib/src/file_system_transport.dart @@ -19,7 +19,8 @@ class FileSystemTransport implements Transport { await envelope.envelopeStream(_options).forEach(envelopeData.addAll); try { // TODO avoid copy - await _native.captureEnvelope(Uint8List.fromList(envelopeData)); + await _native.captureEnvelope(Uint8List.fromList(envelopeData), + envelope.containsUnhandledException); } catch (exception, stackTrace) { _options.logger( SentryLevel.error, diff --git a/flutter/lib/src/native/sentry_native_binding.dart b/flutter/lib/src/native/sentry_native_binding.dart index 07ea5969fe..002790fc32 100644 --- a/flutter/lib/src/native/sentry_native_binding.dart +++ b/flutter/lib/src/native/sentry_native_binding.dart @@ -16,7 +16,8 @@ abstract class SentryNativeBinding { Future fetchNativeAppStart(); - Future captureEnvelope(Uint8List envelopeData); + Future captureEnvelope( + Uint8List envelopeData, bool containsUnhandledException); Future beginNativeFrames(); diff --git a/flutter/lib/src/native/sentry_native_channel.dart b/flutter/lib/src/native/sentry_native_channel.dart index fe00683b0e..0a3b97820d 100644 --- a/flutter/lib/src/native/sentry_native_channel.dart +++ b/flutter/lib/src/native/sentry_native_channel.dart @@ -80,8 +80,11 @@ class SentryNativeChannel } @override - Future captureEnvelope(Uint8List envelopeData) => - _channel.invokeMethod('captureEnvelope', [envelopeData]); + Future captureEnvelope( + Uint8List envelopeData, bool containsUnhandledException) { + return _channel.invokeMethod( + 'captureEnvelope', [envelopeData, containsUnhandledException]); + } @override Future?> loadContexts() => diff --git a/flutter/test/file_system_transport_test.dart b/flutter/test/file_system_transport_test.dart index a658ab9f17..5aa0713183 100644 --- a/flutter/test/file_system_transport_test.dart +++ b/flutter/test/file_system_transport_test.dart @@ -2,6 +2,7 @@ library flutter_test; import 'dart:convert'; + // backcompatibility for Flutter < 3.3 // ignore: unnecessary_import import 'dart:typed_data'; @@ -39,7 +40,7 @@ void main() { }); test('$FileSystemTransport returns emptyId if channel throws', () async { - when(fixture.binding.captureEnvelope(any)).thenThrow(Exception()); + when(fixture.binding.captureEnvelope(any, false)).thenThrow(Exception()); final transport = fixture.getSut(); final event = SentryEvent(); @@ -56,6 +57,58 @@ void main() { expect(SentryId.empty(), sentryId); }); + test( + 'sets unhandled exception flag in captureEnvelope to true for unhandled exception', + () async { + final transport = fixture.getSut(); + + final unhandledException = SentryException( + mechanism: Mechanism(type: 'UnhandledException', handled: false), + threadId: 99, + type: 'Exception', + value: 'Unhandled exception', + ); + final event = SentryEvent(exceptions: [unhandledException]); + final sdkVersion = + SdkVersion(name: 'fixture-sdkName', version: 'fixture-sdkVersion'); + final envelope = SentryEnvelope.fromEvent( + event, + sdkVersion, + dsn: fixture.options.dsn, + ); + + await transport.send(envelope); + + verify(fixture.binding.captureEnvelope(captureAny, true)).captured.single + as Uint8List; + }); + + test( + 'sets unhandled exception flag in captureEnvelope to false for handled exception', + () async { + final transport = fixture.getSut(); + + final unhandledException = SentryException( + mechanism: Mechanism(type: 'UnhandledException', handled: true), + threadId: 99, + type: 'Exception', + value: 'Unhandled exception', + ); + final event = SentryEvent(exceptions: [unhandledException]); + final sdkVersion = + SdkVersion(name: 'fixture-sdkName', version: 'fixture-sdkVersion'); + final envelope = SentryEnvelope.fromEvent( + event, + sdkVersion, + dsn: fixture.options.dsn, + ); + + await transport.send(envelope); + + verify(fixture.binding.captureEnvelope(captureAny, false)).captured.single + as Uint8List; + }); + test('$FileSystemTransport asserts the event', () async { final transport = fixture.getSut(); @@ -70,9 +123,10 @@ void main() { ); await transport.send(envelope); - final envelopeData = verify(fixture.binding.captureEnvelope(captureAny)) - .captured - .single as Uint8List; + final envelopeData = + verify(fixture.binding.captureEnvelope(captureAny, false)) + .captured + .single as Uint8List; final envelopeString = utf8.decode(envelopeData); final lines = envelopeString.split('\n'); final envelopeHeader = lines.first; diff --git a/flutter/test/mocks.mocks.dart b/flutter/test/mocks.mocks.dart index 214b15b588..01d2127efe 100644 --- a/flutter/test/mocks.mocks.dart +++ b/flutter/test/mocks.mocks.dart @@ -1116,11 +1116,17 @@ class MockSentryNativeBinding extends _i1.Mock ) as _i8.Future<_i15.NativeAppStart?>); @override - _i8.Future captureEnvelope(_i16.Uint8List? envelopeData) => + _i8.Future captureEnvelope( + _i16.Uint8List? envelopeData, + bool? containsUnhandledException, + ) => (super.noSuchMethod( Invocation.method( #captureEnvelope, - [envelopeData], + [ + envelopeData, + containsUnhandledException, + ], ), returnValue: _i8.Future.value(), returnValueForMissingStub: _i8.Future.value(), diff --git a/flutter/test/sentry_native_channel_test.dart b/flutter/test/sentry_native_channel_test.dart index cc2e67dfd5..5ad5eb2b3f 100644 --- a/flutter/test/sentry_native_channel_test.dart +++ b/flutter/test/sentry_native_channel_test.dart @@ -244,7 +244,7 @@ void main() { (invocation) async => {captured = invocation.positionalArguments[1][0] as Uint8List}); - await sut.captureEnvelope(data); + await sut.captureEnvelope(data, false); expect(captured, data); }); From d72d349cbfb95d225994370524f61e0b7ccbf822 Mon Sep 17 00:00:00 2001 From: Jonatan Mendez Date: Thu, 11 Jul 2024 15:50:03 -0400 Subject: [PATCH 237/237] change to an stable version --- CHANGELOG.md | 44 +- dart/example_web/pubspec.yaml | 1 - dart/example_web/web/main.dart | 33 +- dart/example_web_legacy/.gitignore | 9 - dart/example_web_legacy/README.md | 8 - dart/example_web_legacy/analysis_options.yaml | 5 - dart/example_web_legacy/pubspec.yaml | 17 - dart/example_web_legacy/web/event.dart | 76 --- dart/example_web_legacy/web/favicon.ico | Bin 3559 -> 0 bytes dart/example_web_legacy/web/index.html | 69 --- dart/example_web_legacy/web/main.dart | 135 ----- dart/example_web_legacy/web/styles.css | 14 - dart/lib/sentry.dart | 1 - .../environment/environment_variables.dart | 3 +- .../enricher/enricher_event_processor.dart | 3 +- .../html_enricher_event_processor.dart | 103 ---- .../enricher/io_enricher_event_processor.dart | 24 +- .../enricher/io_platform_memory.dart | 108 ---- .../web_enricher_event_processor.dart | 33 +- .../exception/exception_event_processor.dart | 3 +- .../src/{origin_io.dart => noop_origin.dart} | 0 dart/lib/src/origin.dart | 7 +- dart/lib/src/origin_html.dart | 4 - dart/lib/src/origin_web.dart | 6 - dart/lib/src/performance_collector.dart | 13 - dart/lib/src/platform/_html_platform.dart | 51 -- dart/lib/src/platform/_web_platform.dart | 14 +- dart/lib/src/platform/platform.dart | 5 +- dart/lib/src/protocol/sentry_span.dart | 33 +- dart/lib/src/protocol/sentry_user.dart | 4 - dart/lib/src/sentry_baggage.dart | 4 - dart/lib/src/sentry_client_stub.dart | 11 + dart/lib/src/sentry_envelope.dart | 17 +- dart/lib/src/sentry_options.dart | 8 - dart/lib/src/sentry_stack_trace_factory.dart | 2 +- dart/lib/src/sentry_trace_context_header.dart | 5 - dart/lib/src/sentry_tracer.dart | 14 - dart/lib/src/utils/isolate_utils.dart | 3 +- dart/lib/src/version.dart | 2 +- dart/pubspec.yaml | 7 +- .../enricher/io_platform_memory_test.dart | 60 -- .../enricher/web_enricher_test.dart | 18 +- dart/test/example_web_compile_test.dart | 27 +- dart/test/mocks/mock_envelope.dart | 3 - .../protocol/sentry_baggage_header_test.dart | 1 - dart/test/protocol/sentry_user_test.dart | 1 - dart/test/sentry_client_test.dart | 5 +- .../sentry_trace_context_header_test.dart | 1 - dart/test/sentry_tracer_test.dart | 1 - dart/test/stack_trace_test.dart | 3 +- dart/test/test_utils.dart | 5 - dio/lib/src/version.dart | 2 +- dio/pubspec.yaml | 4 +- drift/lib/src/version.dart | 2 +- drift/pubspec.yaml | 4 +- file/lib/src/sentry_file_extension.dart | 4 +- file/lib/src/version.dart | 2 +- file/pubspec.yaml | 4 +- flutter/android/build.gradle | 2 +- .../io/sentry/flutter/SentryFlutterPlugin.kt | 30 +- flutter/example/pubspec.yaml | 2 +- .../Classes/SentryFlutterPluginApple.swift | 78 --- flutter/ios/sentry_flutter.podspec | 2 +- .../flutter_enricher_event_processor.dart | 11 +- .../native_app_start_event_processor.dart | 19 +- flutter/lib/src/file_system_transport.dart | 12 +- flutter/lib/src/frame_callback_handler.dart | 21 - .../connectivity/connectivity_provider.dart | 3 +- .../html_connectivity_provider.dart | 32 -- .../web_connectivity_provider.dart | 17 +- .../load_contexts_integration.dart | 18 +- .../load_image_list_integration.dart | 52 +- .../native_app_start_integration.dart | 43 +- .../integrations/native_sdk_integration.dart | 4 +- flutter/lib/src/native/cocoa/binding.dart | 27 + .../src/native/cocoa/sentry_native_cocoa.dart | 16 +- flutter/lib/src/native/factory.dart | 4 +- flutter/lib/src/native/factory_real.dart | 14 +- flutter/lib/src/native/factory_web.dart | 3 +- .../src/native/java/sentry_native_java.dart | 2 +- flutter/lib/src/native/native_app_start.dart | 24 - flutter/lib/src/native/native_frames.dart | 18 - .../lib/src/native/native_scope_observer.dart | 24 +- flutter/lib/src/native/sentry_native.dart | 172 ++++++ .../lib/src/native/sentry_native_binding.dart | 18 +- .../lib/src/native/sentry_native_channel.dart | 140 ++--- .../lib/src/native/sentry_native_invoker.dart | 47 -- .../native/sentry_safe_method_channel.dart | 35 -- .../navigation/sentry_navigator_observer.dart | 11 +- flutter/lib/src/profiling.dart | 8 +- flutter/lib/src/renderer/renderer.dart | 1 - flutter/lib/src/renderer/web_renderer.dart | 18 - flutter/lib/src/sentry_flutter.dart | 100 ++-- flutter/lib/src/sentry_flutter_options.dart | 14 - .../lib/src/span_frame_metrics_collector.dart | 256 --------- flutter/lib/src/utils/enum_wrapper.dart | 12 - flutter/lib/src/version.dart | 2 +- flutter/pubspec.yaml | 4 +- flutter/test/fake_frame_callback_handler.dart | 19 +- flutter/test/file_system_transport_test.dart | 99 ++-- flutter/test/integrations/fixture.dart | 26 - .../integrations/init_native_sdk_test.dart | 14 +- .../load_contexts_integration_test.dart | 98 +++- .../load_contexts_integrations_test.dart | 25 +- .../integrations/load_image_list_test.dart | 244 +++++--- .../native_app_start_integration_test.dart | 167 +++--- .../native_sdk_integration_test.dart | 84 ++- flutter/test/load_image_list_test.dart | 183 ++++++ flutter/test/mocks.dart | 282 +++++++++- flutter/test/mocks.mocks.dart | 473 +++------------- flutter/test/native_scope_observer_test.dart | 55 +- .../sentry_display_widget_test.dart | 1 + .../time_to_display_tracker_test.dart | 2 + flutter/test/profiling_test.dart | 31 +- flutter/test/sentry_flutter_test.dart | 38 +- flutter/test/sentry_native_channel_test.dart | 521 ++++++++---------- flutter/test/sentry_native_test.dart | 120 ++++ .../test/sentry_navigator_observer_test.dart | 27 +- .../span_frame_metrics_collector_test.dart | 274 --------- hive/lib/src/sentry_box_collection.dart | 1 - hive/lib/src/version.dart | 2 +- hive/pubspec.yaml | 4 +- hive/test/mocks/mocks.dart | 1 - hive/test/mocks/mocks.mocks.dart | 1 - isar/lib/src/version.dart | 2 +- isar/pubspec.yaml | 4 +- logging/lib/src/version.dart | 2 +- logging/pubspec.yaml | 4 +- metrics/metrics-ios.yml | 4 +- min_version_test/lib/main.dart | 7 +- .../lib/transaction/file_transaction.dart | 4 +- ...ion_stub.dart => transaction_locator.dart} | 2 +- .../lib/transaction/web_transaction.dart | 5 +- min_version_test/pubspec.yaml | 1 + sqflite/lib/src/version.dart | 2 +- sqflite/pubspec.yaml | 4 +- 136 files changed, 1947 insertions(+), 3248 deletions(-) delete mode 100644 dart/example_web_legacy/.gitignore delete mode 100644 dart/example_web_legacy/README.md delete mode 100644 dart/example_web_legacy/analysis_options.yaml delete mode 100644 dart/example_web_legacy/pubspec.yaml delete mode 100644 dart/example_web_legacy/web/event.dart delete mode 100644 dart/example_web_legacy/web/favicon.ico delete mode 100644 dart/example_web_legacy/web/index.html delete mode 100644 dart/example_web_legacy/web/main.dart delete mode 100644 dart/example_web_legacy/web/styles.css delete mode 100644 dart/lib/src/event_processor/enricher/html_enricher_event_processor.dart delete mode 100644 dart/lib/src/event_processor/enricher/io_platform_memory.dart rename dart/lib/src/{origin_io.dart => noop_origin.dart} (100%) delete mode 100644 dart/lib/src/origin_html.dart delete mode 100644 dart/lib/src/origin_web.dart delete mode 100644 dart/lib/src/performance_collector.dart delete mode 100644 dart/lib/src/platform/_html_platform.dart create mode 100644 dart/lib/src/sentry_client_stub.dart delete mode 100644 dart/test/event_processor/enricher/io_platform_memory_test.dart delete mode 100644 flutter/lib/src/integrations/connectivity/html_connectivity_provider.dart delete mode 100644 flutter/lib/src/native/native_app_start.dart delete mode 100644 flutter/lib/src/native/native_frames.dart create mode 100644 flutter/lib/src/native/sentry_native.dart delete mode 100644 flutter/lib/src/native/sentry_native_invoker.dart delete mode 100644 flutter/lib/src/native/sentry_safe_method_channel.dart delete mode 100644 flutter/lib/src/renderer/web_renderer.dart delete mode 100644 flutter/lib/src/span_frame_metrics_collector.dart delete mode 100644 flutter/lib/src/utils/enum_wrapper.dart delete mode 100644 flutter/test/integrations/fixture.dart create mode 100644 flutter/test/load_image_list_test.dart create mode 100644 flutter/test/sentry_native_test.dart delete mode 100644 flutter/test/span_frame_metrics_collector_test.dart rename min_version_test/lib/transaction/{transaction_stub.dart => transaction_locator.dart} (60%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 54158f6b4b..75b24a6314 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,41 +1,5 @@ # Changelog -## Unreleased - -### Features - -- Add memory usage to contexts ([#2133](https://github.com/getsentry/sentry-dart/pull/2133)) - - Only for Linux/Windows applications, as iOS/Android/macOS use native SDKs - -### Fixes - -- App starts hanging for 30s ([#2140](https://github.com/getsentry/sentry-dart/pull/2140)) - - Time out for app start info retrieval has been reduced to 10s - - If `autoAppStarts` is `false` and `setAppStartEnd` has not been called, the app start event processor will now return early instead of waiting for `getAppStartInfo` to finish - -## 8.4.0-beta.1 - -### Features - -- Add API for pausing/resuming **iOS** and **macOS** app hang tracking ([#2134](https://github.com/getsentry/sentry-dart/pull/2134)) - - This is useful to prevent the Cocoa SDK from reporting wrongly detected app hangs when the OS shows a system dialog for asking specific permissions. - - Use `SentryFlutter.pauseAppHangTracking()` and `SentryFlutter.resumeAppHangTracking()` -- Capture total frames, frames delay, slow & frozen frames and attach to spans ([#2106](https://github.com/getsentry/sentry-dart/pull/2106)) -- Support WebAssembly compilation (dart2wasm) ([#2113](https://github.com/getsentry/sentry-dart/pull/2113)) - -### Deprecated - -- User segment is now deprecated and will be removed in version 9.0.0. Use a custom tag or context instead. ([#2119](https://github.com/getsentry/sentry-dart/pull/2119)) - -### Dependencies - -- Bump Cocoa SDK from v8.29.0 to v8.30.0 ([#2132](https://github.com/getsentry/sentry-dart/pull/2132)) - - [changelog](https://github.com/getsentry/sentry-cocoa/blob/main/CHANGELOG.md#8300) - - [diff](https://github.com/getsentry/sentry-cocoa/compare/8.29.0...8.30.0) -- Bump Android SDK from v7.10.0 to v7.11.0 ([#2144](https://github.com/getsentry/sentry-dart/pull/2144)) - - [changelog](https://github.com/getsentry/sentry-java/blob/main/CHANGELOG.md#7110) - - [diff](https://github.com/getsentry/sentry-java/compare/7.10.0...7.11.0) - ## 8.3.0 ### Fixes @@ -150,7 +114,7 @@ This release contains breaking changes, please read the changelog carefully. ### Features -- Experimental: Add support for Sentry Developer Metrics ([#1940](https://github.com/getsentry/sentry-dart/pull/1940), [#1949](https://github.com/getsentry/sentry-dart/pull/1949), [#1954](https://github.com/getsentry/sentry-dart/pull/1954), [#1958](https://github.com/getsentry/sentry-dart/pull/1958)) +- Experimental: Add support for Sentry Developer Metrics ([#1940](https://github.com/getsentry/sentry-dart/pull/1940), [#1949](https://github.com/getsentry/sentry-dart/pull/1949), [#1954](https://github.com/getsentry/sentry-dart/pull/1954), [#1958](https://github.com/getsentry/sentry-dart/pull/1958)) Use the Metrics API to track processing time, download sizes, user signups, and conversion rates and correlate them back to tracing data in order to get deeper insights and solve issues faster. Our API supports counters, distributions, sets, gauges and timers, and it's easy to get started: ```dart Sentry.metrics() @@ -263,14 +227,14 @@ This release contains breaking changes, please read the changelog carefully. - Now the device context from Android is available in `BeforeSendCallback` - Set ip_address to {{auto}} by default, even if sendDefaultPII is disabled ([#1665](https://github.com/getsentry/sentry-dart/pull/1665)) - Instead use the "Prevent Storing of IP Addresses" option in the "Security & Privacy" project settings on sentry.io - -### Fixes + +### Fixes - Remove Flutter dependency from Drift integration ([#1867](https://github.com/getsentry/sentry-dart/pull/1867)) - Remove dead code, cold start bool is now always present ([#1861](https://github.com/getsentry/sentry-dart/pull/1861)) - Fix iOS "Arithmetic Overflow" ([#1874](https://github.com/getsentry/sentry-dart/pull/1874)) -### Dependencies +### Dependencies - Bump Cocoa SDK from v8.19.0 to v8.20.0 ([#1856](https://github.com/getsentry/sentry-dart/pull/1856)) - [changelog](https://github.com/getsentry/sentry-cocoa/blob/main/CHANGELOG.md#8200) diff --git a/dart/example_web/pubspec.yaml b/dart/example_web/pubspec.yaml index 141e5120ac..7bcb64d06e 100644 --- a/dart/example_web/pubspec.yaml +++ b/dart/example_web/pubspec.yaml @@ -9,7 +9,6 @@ environment: dependencies: sentry: path: ../../dart/ - web: ^0.5.1 dev_dependencies: build_runner: ^2.4.2 diff --git a/dart/example_web/web/main.dart b/dart/example_web/web/main.dart index b39a05e0dc..3034effe9b 100644 --- a/dart/example_web/web/main.dart +++ b/dart/example_web/web/main.dart @@ -1,5 +1,5 @@ import 'dart:async'; -import 'package:web/web.dart'; +import 'dart:html'; import 'package:sentry/sentry.dart'; import 'package:sentry/src/version.dart'; @@ -24,7 +24,7 @@ Future main() async { Future runApp() async { print('runApp'); - document.querySelector('#output')?.text = 'Your Dart app is running.'; + querySelector('#output')?.text = 'Your Dart app is running.'; await Sentry.addBreadcrumb( Breadcrumb( @@ -57,20 +57,12 @@ Future runApp() async { ); }); - document - .querySelector('#btEvent') + querySelector('#btEvent') ?.onClick .listen((event) => captureCompleteExampleEvent()); - document - .querySelector('#btMessage') - ?.onClick - .listen((event) => captureMessage()); - document - .querySelector('#btException') - ?.onClick - .listen((event) => captureException()); - document - .querySelector('#btUnhandledException') + querySelector('#btMessage')?.onClick.listen((event) => captureMessage()); + querySelector('#btException')?.onClick.listen((event) => captureException()); + querySelector('#btUnhandledException') ?.onClick .listen((event) => captureUnhandledException()); } @@ -84,8 +76,7 @@ Future captureMessage() async { ); print('capture message result : $sentryId'); if (sentryId != SentryId.empty()) { - (document.querySelector('#messageResult') as HTMLElement?)?.style.display = - 'block'; + querySelector('#messageResult')?.style.display = 'block'; } } @@ -102,16 +93,13 @@ Future captureException() async { print('Capture exception : SentryId: $sentryId'); if (sentryId != SentryId.empty()) { - (document.querySelector('#exceptionResult') as HTMLElement?) - ?.style - .display = 'block'; + querySelector('#exceptionResult')?.style.display = 'block'; } } } Future captureUnhandledException() async { - (document.querySelector('#unhandledResult') as HTMLElement?)?.style.display = - 'block'; + querySelector('#unhandledResult')?.style.display = 'block'; await buildCard(); } @@ -123,8 +111,7 @@ Future captureCompleteExampleEvent() async { print('Response SentryId: $sentryId'); if (sentryId != SentryId.empty()) { - (document.querySelector('#eventResult') as HTMLElement?)?.style.display = - 'block'; + querySelector('#eventResult')?.style.display = 'block'; } } diff --git a/dart/example_web_legacy/.gitignore b/dart/example_web_legacy/.gitignore deleted file mode 100644 index 3d64647b50..0000000000 --- a/dart/example_web_legacy/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -# Files and directories created by pub -.dart_tool/ -.packages - -# Conventional directory for build outputs -build/ - -# Directory created by dartdoc -doc/api/ diff --git a/dart/example_web_legacy/README.md b/dart/example_web_legacy/README.md deleted file mode 100644 index 98202566f6..0000000000 --- a/dart/example_web_legacy/README.md +++ /dev/null @@ -1,8 +0,0 @@ -# Sentry Dart : web example - -```sh -dart pub get - -# run the project ( see https://dart.dev/tools/webdev#serve ) -dart run webdev serve --release -``` diff --git a/dart/example_web_legacy/analysis_options.yaml b/dart/example_web_legacy/analysis_options.yaml deleted file mode 100644 index be16ace7d1..0000000000 --- a/dart/example_web_legacy/analysis_options.yaml +++ /dev/null @@ -1,5 +0,0 @@ -include: package:lints/recommended.yaml - -analyzer: - errors: - path_does_not_exist: ignore diff --git a/dart/example_web_legacy/pubspec.yaml b/dart/example_web_legacy/pubspec.yaml deleted file mode 100644 index 49b7807084..0000000000 --- a/dart/example_web_legacy/pubspec.yaml +++ /dev/null @@ -1,17 +0,0 @@ -name: sentry_dart_web_example -description: An absolute bare-bones web app. - -publish_to: 'none' - -environment: - sdk: '>=2.17.0 <4.0.0' - -dependencies: - sentry: - path: ../../dart/ - -dev_dependencies: - build_runner: ^2.3.0 - build_web_compilers: ^3.2.3 - lints: ^2.0.0 - webdev: ^2.7.0 diff --git a/dart/example_web_legacy/web/event.dart b/dart/example_web_legacy/web/event.dart deleted file mode 100644 index 6e3e8b3e0b..0000000000 --- a/dart/example_web_legacy/web/event.dart +++ /dev/null @@ -1,76 +0,0 @@ -import 'package:sentry/src/protocol.dart'; - -final event = SentryEvent( - logger: 'main', - serverName: 'server.dart', - release: '1.4.0-preview.1', - environment: 'Test', - message: SentryMessage('This is an example Dart event.'), - tags: const {'project-id': '7371'}, - // ignore: deprecated_member_use, deprecated_member_use_from_same_package - extra: const {'section': '1'}, - // fingerprint: const ['example-dart'], - user: SentryUser( - id: '800', - username: 'first-user', - email: 'first@user.lan', - // ipAddress: '127.0.0.1', - data: {'first-sign-in': '2020-01-01'}, - ), - breadcrumbs: [ - Breadcrumb( - message: 'UI Lifecycle', - timestamp: DateTime.now().toUtc(), - category: 'ui.lifecycle', - type: 'navigation', - data: {'screen': 'MainActivity', 'state': 'created'}, - level: SentryLevel.info, - ) - ], - contexts: Contexts( - operatingSystem: const SentryOperatingSystem( - name: 'Android', - version: '5.0.2', - build: 'LRX22G.P900XXS0BPL2', - kernelVersion: - 'Linux version 3.4.39-5726670 (dpi@SWHC3807) (gcc version 4.8 (GCC) ) #1 SMP PREEMPT Thu Dec 1 19:42:39 KST 2016', - rooted: false, - ), - runtimes: [const SentryRuntime(name: 'ART', version: '5')], - app: SentryApp( - name: 'Example Dart App', - version: '1.42.0', - identifier: 'HGT-App-13', - build: '93785', - buildType: 'release', - deviceAppHash: '5afd3a6', - startTime: DateTime.now().toUtc(), - ), - browser: const SentryBrowser(name: 'Firefox', version: '42.0.1'), - device: SentryDevice( - name: 'SM-P900', - family: 'SM-P900', - model: 'SM-P900 (LRX22G)', - modelId: 'LRX22G', - arch: 'armeabi-v7a', - batteryLevel: 99, - orientation: SentryOrientation.landscape, - manufacturer: 'samsung', - brand: 'samsung', - screenDensity: 2.1, - screenDpi: 320, - online: true, - charging: true, - lowMemory: true, - simulator: false, - memorySize: 1500, - freeMemory: 200, - usableMemory: 4294967296, - storageSize: 4294967296, - freeStorage: 2147483648, - externalStorageSize: 8589934592, - externalFreeStorage: 2863311530, - bootTime: DateTime.now().toUtc(), - ), - ), -); diff --git a/dart/example_web_legacy/web/favicon.ico b/dart/example_web_legacy/web/favicon.ico deleted file mode 100644 index 7ba349b3e628d2423d4a2ed217422a4722f73739..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3559 zcmV|z)fLATAcZDKyK$JdGY~s=NSr`PnS}BvP$+3A z8CpoogqBhg+p;Cg51fS9@izOF7~1r6zw|?g zDQ!X_8B4l7_wKH=QY>4NwW55uUP;#D-rxP7bI-kdjtU{9Dpi9&%XV3<*GkWK^P@NG zgWRw6Vb?`n$T_Evx_k{$?y0Rh-E#bYD?-UGV3Tc>$SdfYhb2dG)#K`(KPKx z4IwA0_p^z5A4{(AI%=BqUe-mpgFoo&TY*3Gu!0a29lR)aGV2dpEZ4z|Kc)+FUc-bN zHIDPB&TC8HnJ0tyG0*^nmzmQ?TnN+!QqapY^N|7@`F5AqbYw-`02pC0LNbv4yz60?w^9K&j_>533B&I%i9tFNIn5p2kb+@G0y43>@$)ns6>BLG63+2Wpepx zJ&v#ILasL(C%pe{n)2h>g2u-1wVpgKUaNE4V$J76NI&82+j&+}!O~12Z$~FRKK$`9 zx^J3f|L@(w z@^0VL;CU-=w^+ZF9FR4?4ODJ#62DZXnxe`qk)!2S9)0Z%YeH3TkE!aMNY!YE_0LhF z2ESF$qU+kcNYfp>Oq;_Knx0_qs&4=0WPdHW`-Qyher0=jx5gB?QhDMW+Qc1=t$k|< zt=eZtRI`&@>AfXtZFZz?wIfZ37txkUL?4_$0OBvSIr99C2j2UN)Ni@j77k#SApKPq z|7OZGK1&}QM-|70VjJzpQ8hDwD&8DI6m)83lM`v+s(Btdr*I>`(aIvtK1ZDD;A51L zClILKDAJgMZ)-X|x8@2VC+X9BJv40&^lN&j5M^{HDvl4q-~qts09^Y4!n4Ma6_Lw34kz1b@>qe;tZn9VPT9z@k+{b=Lo2to6L3;F~QIz4!D1T|P-qRdf7Z303(CYKm}t10))3j2!;|tzyS7gc;G1rFhS73B&NU|LN;}mYr{eivPfUF zdm~5DreHsX?W>bdsM|qmnE=2HBnZ`V2&GU0HiPHE4BB~d@G=O*FMxyW35}^c+*y^d zu=LHL8rmGaLUn`myIgTKc-?scBq8(@2<4?z0#?C(P6j}(1UFeFC{V&pSs-Nh`dIqC zkq_zKagZ2z+AcRzw=V!dgs?$W0)eov1WLdv*y|LWVW)c@2!awQQ^c0$7^MT+`37Is z%4jsE07!ol4_@%H1b}B@02vS}j=YN~fUrVwC4dzE;VS8yeRqJ(To9x$c>TNqWIDzpRz&Sr zPzjP57~P9Na0}*O4%=_+^52#;fi&rNW3NA+l7688GL>)?AiTgTsszmeR~7(L6O~|@ zzz|qG+3C{n4%C4}E>qpUB(Ws{kV9bm(b{8HL<58sjR2ud0W;XQkP4(=2|ILf=2+pq z(O1(09&`AwG{n*Q)qw$JVxnF zMFb%C2^hk0fN(%m0*265LNmZ)!wN7*KLbbq8UaA{1auJa2wp!^`o#huDPc4NLNR?p zE@mJB=mh`=BfnEomf&3wBwPRh_zkhFA1nrdt00_4bi2$P+KLn!cjN=0CupO3Leg$3 zp*Vm{2>k+tq!Nk%A+NXX^~lmZ}E0)ru(A`q6O1aeT4#SAh5kY%uwe*{*64`?9{h|TK{lms9t zVMO!^gQrlLafwQR&uH5D+yIa;xWn}w$_&dP-ZmCH63kNx)pmez0+e9HK7lI?Lbe@Z zCIIH03!8~Gbn zf+p*Bct|+_8A_;n`y?vsWCSI&<*x)yyDR;;ESm|WDWSu=9V-Fv4K$Kt?D8OWhX~-< z8M4JKx(QsRgh2tq34qYWSpHUUkm|e@h>8u?io3kMt+jNkPo$fU+`TO^E$=_ zAV@2L(Nh=zdBX|I7zlv)vLWhvxn(AR^nQB+a(@#wUK`rQ52NkQchOw{V?Bles;Gnx zuO~1Di)SVo=CHckmenU{((WCK0PvY$@A#*1=j-)CbAeSgo{@WXVb|Yr24@501Of;Q zgQUdn@s6RV_;ctHhZSwHy^XM+5McC+FpA(acq zkST#cFbNRUG6bnF(C#1)tpLs{oldkvBx7pL^j%9 z^aQ|o(0&Tt4lvfjK-P*ds`G^*Gl%u3PGSg&Ms9I z*zZ)`R3{W-EGbbsnIz4z4?~&D2QBA=kRHntC1hrXOE4OI7(xn09lZ7ozLsW{b=7 zbnCtL2cfv(eDh3zWQflPAv+AgOlsk^pSVZR4(AZM7hvEebZwgR987~DJRT$~4t`JN z@IV4P-6z6hXeZ}5TxI0SRjTv?3$ouKS*60hr&tvtLe{uv^Z_W4m}z-GL@GnHGIPk* zw6ctFod^P(OD!y`KXwnJ@4>QqH;FL@i7G0^fC~dyCpy$y;qkr9N%VyCOuRPafGQLB zzxU5Nx5-m}$bfT6kttLODx@M`to1wZ2XmNi7JNd^g%aAUV6e$$mBbisA;#D$#u!)` zw}J0?$bOnExiyeYuJhSrI5vUQ{Xnh5v4#|I^i3@pb{W7_{P2k5GK==kbAYr zd@D&R#;~Cu!m^6Z1Sv9BK^_RF-@KuRkuuEQ=LX6u&}L20<6F-P1JfjkL^$kk*d@$ZG_p zlDS-4dId>x;8Ix))Ft8KEW?C11O-;*xfWL`Qzk1{Ldf+^h!aB1=lxg-30(gpl+6{; zlAp7sn($go>tSNJPRTIkIh2%t4%H;e)d~Xy$^IHbwmS{eULGp}7eC>K>x%RdXHl9i z=pa>P`f>La2+w!sQ%|I9!8C>-&H_}9-U;=8E{GN8praR|_~}w{8h=S2<}S6&1}__C z{K0ykqcUgtgVR>NYFus(0ow+ctv$LRyQjfxf3DtV-(8H>5U@W7MVi`%u=AlE% - - - - - - - - - - - dart_web - - - - - - - - - - -
- -
- -
Captured
-
- -
- -
Captured
-
- -
- -
Captured
-
- -
- -
Captured
-
- - - diff --git a/dart/example_web_legacy/web/main.dart b/dart/example_web_legacy/web/main.dart deleted file mode 100644 index 3034effe9b..0000000000 --- a/dart/example_web_legacy/web/main.dart +++ /dev/null @@ -1,135 +0,0 @@ -import 'dart:async'; -import 'dart:html'; - -import 'package:sentry/sentry.dart'; -import 'package:sentry/src/version.dart'; - -import 'event.dart'; - -// ATTENTION: Change the DSN below with your own to see the events in Sentry. Get one at sentry.io -const dsn = - 'https://e85b375ffb9f43cf8bdf9787768149e0@o447951.ingest.sentry.io/5428562'; - -Future main() async { - await Sentry.init( - (options) => options - ..dsn = dsn - ..debug = true - ..sendDefaultPii = true - ..addEventProcessor(TagEventProcessor()), - appRunner: runApp, - ); -} - -Future runApp() async { - print('runApp'); - - querySelector('#output')?.text = 'Your Dart app is running.'; - - await Sentry.addBreadcrumb( - Breadcrumb( - message: 'Authenticated user', - category: 'auth', - type: 'debug', - data: { - 'admin': true, - 'permissions': [1, 2, 3] - }, - ), - ); - - await Sentry.configureScope((scope) async { - scope - // ..fingerprint = ['example-dart'] - ..transaction = '/example/app' - ..level = SentryLevel.warning; - await scope.setTag('build', '579'); - await scope.setExtra('company-name', 'Dart Inc'); - - await scope.setUser( - SentryUser( - id: '800', - username: 'first-user', - email: 'first@user.lan', - // ipAddress: '127.0.0.1', - data: {'first-sign-in': '2020-01-01'}, - ), - ); - }); - - querySelector('#btEvent') - ?.onClick - .listen((event) => captureCompleteExampleEvent()); - querySelector('#btMessage')?.onClick.listen((event) => captureMessage()); - querySelector('#btException')?.onClick.listen((event) => captureException()); - querySelector('#btUnhandledException') - ?.onClick - .listen((event) => captureUnhandledException()); -} - -Future captureMessage() async { - print('Capturing Message : '); - final sentryId = await Sentry.captureMessage( - 'Message 2', - template: 'Message %s', - params: ['2'], - ); - print('capture message result : $sentryId'); - if (sentryId != SentryId.empty()) { - querySelector('#messageResult')?.style.display = 'block'; - } -} - -Future captureException() async { - try { - await buildCard(); - } catch (error, stackTrace) { - print('\nReporting the following stack trace: '); - final sentryId = await Sentry.captureException( - error, - stackTrace: stackTrace, - ); - - print('Capture exception : SentryId: $sentryId'); - - if (sentryId != SentryId.empty()) { - querySelector('#exceptionResult')?.style.display = 'block'; - } - } -} - -Future captureUnhandledException() async { - querySelector('#unhandledResult')?.style.display = 'block'; - - await buildCard(); -} - -Future captureCompleteExampleEvent() async { - print('\nReporting a complete event example: $sdkName'); - final sentryId = await Sentry.captureEvent(event); - - print('Response SentryId: $sentryId'); - - if (sentryId != SentryId.empty()) { - querySelector('#eventResult')?.style.display = 'block'; - } -} - -Future buildCard() async { - await loadData(); -} - -Future loadData() async { - await parseData(); -} - -Future parseData() async { - throw StateError('This is a test error'); -} - -class TagEventProcessor implements EventProcessor { - @override - SentryEvent? apply(SentryEvent event, Hint hint) { - return event..tags?.addAll({'page-locale': 'en-us'}); - } -} diff --git a/dart/example_web_legacy/web/styles.css b/dart/example_web_legacy/web/styles.css deleted file mode 100644 index cc035c95c9..0000000000 --- a/dart/example_web_legacy/web/styles.css +++ /dev/null @@ -1,14 +0,0 @@ -@import url(https://fonts.googleapis.com/css?family=Roboto); - -html, body { - width: 100%; - height: 100%; - margin: 0; - padding: 0; - font-family: 'Roboto', sans-serif; -} - -#output { - padding: 20px; - text-align: center; -} diff --git a/dart/lib/sentry.dart b/dart/lib/sentry.dart index fd88a49fc5..f416d0b797 100644 --- a/dart/lib/sentry.dart +++ b/dart/lib/sentry.dart @@ -30,7 +30,6 @@ export 'src/http_client/sentry_http_client_error.dart'; export 'src/sentry_attachment/sentry_attachment.dart'; export 'src/sentry_user_feedback.dart'; export 'src/utils/tracing_utils.dart'; -export 'src/performance_collector.dart'; // tracing export 'src/tracing.dart'; export 'src/hint.dart'; diff --git a/dart/lib/src/environment/environment_variables.dart b/dart/lib/src/environment/environment_variables.dart index 3dcb1674b3..916cdea47d 100644 --- a/dart/lib/src/environment/environment_variables.dart +++ b/dart/lib/src/environment/environment_variables.dart @@ -1,7 +1,6 @@ import '../platform_checker.dart'; import '_io_environment_variables.dart' - if (dart.library.html) '_web_environment_variables.dart' - if (dart.library.js_interop) '_web_environment_variables.dart' as env; + if (dart.library.html) '_web_environment_variables.dart' as env; /// Reads environment variables from the system. /// In an Flutter environment these can be set via diff --git a/dart/lib/src/event_processor/enricher/enricher_event_processor.dart b/dart/lib/src/event_processor/enricher/enricher_event_processor.dart index 779d64b700..78d19738bd 100644 --- a/dart/lib/src/event_processor/enricher/enricher_event_processor.dart +++ b/dart/lib/src/event_processor/enricher/enricher_event_processor.dart @@ -1,8 +1,7 @@ import '../../event_processor.dart'; import '../../sentry_options.dart'; import 'io_enricher_event_processor.dart' - if (dart.library.html) 'html_enricher_event_processor.dart' - if (dart.library.js_interop) 'web_enricher_event_processor.dart'; + if (dart.library.html) 'web_enricher_event_processor.dart'; abstract class EnricherEventProcessor implements EventProcessor { factory EnricherEventProcessor(SentryOptions options) => diff --git a/dart/lib/src/event_processor/enricher/html_enricher_event_processor.dart b/dart/lib/src/event_processor/enricher/html_enricher_event_processor.dart deleted file mode 100644 index e51cff4b71..0000000000 --- a/dart/lib/src/event_processor/enricher/html_enricher_event_processor.dart +++ /dev/null @@ -1,103 +0,0 @@ -import 'dart:html' as html show window, Window; - -import '../../../sentry.dart'; -import 'enricher_event_processor.dart'; - -EnricherEventProcessor enricherEventProcessor(SentryOptions options) { - return WebEnricherEventProcessor( - html.window, - options, - ); -} - -class WebEnricherEventProcessor implements EnricherEventProcessor { - WebEnricherEventProcessor( - this._window, - this._options, - ); - - final html.Window _window; - - final SentryOptions _options; - - @override - SentryEvent? apply(SentryEvent event, Hint hint) { - // Web has no native integration, so no need to check for it - - final contexts = event.contexts.copyWith( - device: _getDevice(event.contexts.device), - culture: _getSentryCulture(event.contexts.culture), - ); - - contexts['dart_context'] = _getDartContext(); - - return event.copyWith( - contexts: contexts, - request: _getRequest(event.request), - transaction: event.transaction ?? _window.location.pathname, - ); - } - - // As seen in - // https://github.com/getsentry/sentry-javascript/blob/a6f8dc26a4c7ae2146ae64995a2018c8578896a6/packages/browser/src/integrations/useragent.ts - SentryRequest _getRequest(SentryRequest? request) { - final requestHeader = request?.headers; - final header = requestHeader == null - ? {} - : Map.from(requestHeader); - - header.putIfAbsent('User-Agent', () => _window.navigator.userAgent); - - final url = request?.url ?? _window.location.toString(); - return (request ?? SentryRequest(url: url)) - .copyWith(headers: header) - .sanitized(); - } - - SentryDevice _getDevice(SentryDevice? device) { - return (device ?? SentryDevice()).copyWith( - online: device?.online ?? _window.navigator.onLine, - memorySize: device?.memorySize ?? _getMemorySize(), - orientation: device?.orientation ?? _getScreenOrientation(), - screenHeightPixels: device?.screenHeightPixels ?? - _window.screen?.available.height.toInt(), - screenWidthPixels: - device?.screenWidthPixels ?? _window.screen?.available.width.toInt(), - screenDensity: - device?.screenDensity ?? _window.devicePixelRatio.toDouble(), - ); - } - - int? _getMemorySize() { - // https://developer.mozilla.org/en-US/docs/Web/API/Navigator/deviceMemory - final size = _window.navigator.deviceMemory?.toDouble(); - final memoryByteSize = size != null ? size * 1024 * 1024 * 1024 : null; - return memoryByteSize?.toInt(); - } - - SentryOrientation? _getScreenOrientation() { - // https://developer.mozilla.org/en-US/docs/Web/API/ScreenOrientation - final screenOrientation = _window.screen?.orientation; - if (screenOrientation != null) { - if (screenOrientation.type?.startsWith('portrait') ?? false) { - return SentryOrientation.portrait; - } - if (screenOrientation.type?.startsWith('landscape') ?? false) { - return SentryOrientation.landscape; - } - } - return null; - } - - Map _getDartContext() { - return { - 'compile_mode': _options.platformChecker.compileMode, - }; - } - - SentryCulture _getSentryCulture(SentryCulture? culture) { - return (culture ?? SentryCulture()).copyWith( - timezone: culture?.timezone ?? DateTime.now().timeZoneName, - ); - } -} diff --git a/dart/lib/src/event_processor/enricher/io_enricher_event_processor.dart b/dart/lib/src/event_processor/enricher/io_enricher_event_processor.dart index 63304cdbf6..52243a8572 100644 --- a/dart/lib/src/event_processor/enricher/io_enricher_event_processor.dart +++ b/dart/lib/src/event_processor/enricher/io_enricher_event_processor.dart @@ -2,7 +2,6 @@ import 'dart:io'; import '../../../sentry.dart'; import 'enricher_event_processor.dart'; -import 'io_platform_memory.dart'; EnricherEventProcessor enricherEventProcessor(SentryOptions options) { return IoEnricherEventProcessor(options); @@ -18,29 +17,25 @@ class IoEnricherEventProcessor implements EnricherEventProcessor { @override SentryEvent? apply(SentryEvent event, Hint hint) { - // Amend app with current memory usage, as this is not available on native. - final app = _getApp(event.contexts.app); - // If there's a native integration available, it probably has better // information available than Flutter. - final device = _options.platformChecker.hasNativeIntegration - ? null - : _getDevice(event.contexts.device); - final os = _options.platformChecker.hasNativeIntegration ? null : _getOperatingSystem(event.contexts.operatingSystem); + final device = _options.platformChecker.hasNativeIntegration + ? null + : _getDevice(event.contexts.device); + final culture = _options.platformChecker.hasNativeIntegration ? null : _getSentryCulture(event.contexts.culture); final contexts = event.contexts.copyWith( - device: device, operatingSystem: os, + device: device, runtimes: _getRuntimes(event.contexts.runtimes), - app: app, culture: culture, ); @@ -102,18 +97,9 @@ class IoEnricherEventProcessor implements EnricherEventProcessor { } SentryDevice _getDevice(SentryDevice? device) { - final platformMemory = PlatformMemory(_options); return (device ?? SentryDevice()).copyWith( name: device?.name ?? Platform.localHostname, processorCount: device?.processorCount ?? Platform.numberOfProcessors, - memorySize: device?.memorySize ?? platformMemory.getTotalPhysicalMemory(), - freeMemory: device?.freeMemory ?? platformMemory.getFreePhysicalMemory(), - ); - } - - SentryApp _getApp(SentryApp? app) { - return (app ?? SentryApp()).copyWith( - appMemory: app?.appMemory ?? ProcessInfo.currentRss, ); } diff --git a/dart/lib/src/event_processor/enricher/io_platform_memory.dart b/dart/lib/src/event_processor/enricher/io_platform_memory.dart deleted file mode 100644 index 4acde3f15b..0000000000 --- a/dart/lib/src/event_processor/enricher/io_platform_memory.dart +++ /dev/null @@ -1,108 +0,0 @@ -import 'dart:io'; - -import '../../protocol.dart'; -import '../../sentry_options.dart'; - -// Get total & free platform memory (in bytes) for linux and windows operating systems. -// Source: https://github.com/onepub-dev/system_info/blob/8a9bf6b8eb7c86a09b3c3df4bf6d7fa5a6b50732/lib/src/platform/memory.dart -class PlatformMemory { - PlatformMemory(this.options); - - final SentryOptions options; - - int? getTotalPhysicalMemory() { - if (options.platformChecker.platform.isLinux) { - return _getLinuxMemInfoValue('MemTotal'); - } else if (options.platformChecker.platform.isWindows) { - return _getWindowsWmicValue('ComputerSystem', 'TotalPhysicalMemory'); - } else { - return null; - } - } - - int? getFreePhysicalMemory() { - if (options.platformChecker.platform.isLinux) { - return _getLinuxMemInfoValue('MemFree'); - } else if (options.platformChecker.platform.isWindows) { - return _getWindowsWmicValue('OS', 'FreePhysicalMemory'); - } else { - return null; - } - } - - int? _getWindowsWmicValue(String section, String key) { - final os = _wmicGetValueAsMap(section, [key]); - final totalPhysicalMemoryValue = os?[key]; - if (totalPhysicalMemoryValue == null) { - return null; - } - final size = int.tryParse(totalPhysicalMemoryValue); - if (size == null) { - return null; - } - return size; - } - - int? _getLinuxMemInfoValue(String key) { - final meminfoList = _exec('cat', ['/proc/meminfo']) - ?.trim() - .replaceAll('\r\n', '\n') - .split('\n') ?? - []; - - final meminfoMap = _listToMap(meminfoList, ':'); - final memsizeResults = meminfoMap[key]?.split(' ') ?? []; - - if (memsizeResults.isEmpty) { - return null; - } - final memsizeResult = memsizeResults.first; - - final memsize = int.tryParse(memsizeResult); - if (memsize == null) { - return null; - } - return memsize; - } - - String? _exec(String executable, List arguments, - {bool runInShell = false}) { - try { - final result = - Process.runSync(executable, arguments, runInShell: runInShell); - if (result.exitCode == 0) { - return result.stdout.toString(); - } - } catch (e) { - options.logger(SentryLevel.warning, "Failed to run process: $e"); - } - return null; - } - - Map? _wmicGetValueAsMap(String section, List fields) { - final arguments = [section]; - arguments - ..add('get') - ..addAll(fields.join(', ').split(' ')) - ..add('/VALUE'); - - final list = - _exec('wmic', arguments)?.trim().replaceAll('\r\n', '\n').split('\n') ?? - []; - - return _listToMap(list, '='); - } - - Map _listToMap(List list, String separator) { - final map = {}; - for (final string in list) { - final index = string.indexOf(separator); - if (index != -1) { - final key = string.substring(0, index).trim(); - final value = string.substring(index + 1).trim(); - map[key] = value; - } - } - return map; - } -} diff --git a/dart/lib/src/event_processor/enricher/web_enricher_event_processor.dart b/dart/lib/src/event_processor/enricher/web_enricher_event_processor.dart index d6d588ac0a..e51cff4b71 100644 --- a/dart/lib/src/event_processor/enricher/web_enricher_event_processor.dart +++ b/dart/lib/src/event_processor/enricher/web_enricher_event_processor.dart @@ -1,13 +1,11 @@ -// We would lose compatibility with old dart versions by adding web to pubspec. -// ignore: depend_on_referenced_packages -import 'package:web/web.dart' as web show window, Window, Navigator; +import 'dart:html' as html show window, Window; import '../../../sentry.dart'; import 'enricher_event_processor.dart'; EnricherEventProcessor enricherEventProcessor(SentryOptions options) { return WebEnricherEventProcessor( - web.window, + html.window, options, ); } @@ -18,7 +16,7 @@ class WebEnricherEventProcessor implements EnricherEventProcessor { this._options, ); - final web.Window _window; + final html.Window _window; final SentryOptions _options; @@ -61,9 +59,10 @@ class WebEnricherEventProcessor implements EnricherEventProcessor { online: device?.online ?? _window.navigator.onLine, memorySize: device?.memorySize ?? _getMemorySize(), orientation: device?.orientation ?? _getScreenOrientation(), - screenHeightPixels: - device?.screenHeightPixels ?? _window.screen.availHeight, - screenWidthPixels: device?.screenWidthPixels ?? _window.screen.availWidth, + screenHeightPixels: device?.screenHeightPixels ?? + _window.screen?.available.height.toInt(), + screenWidthPixels: + device?.screenWidthPixels ?? _window.screen?.available.width.toInt(), screenDensity: device?.screenDensity ?? _window.devicePixelRatio.toDouble(), ); @@ -78,12 +77,14 @@ class WebEnricherEventProcessor implements EnricherEventProcessor { SentryOrientation? _getScreenOrientation() { // https://developer.mozilla.org/en-US/docs/Web/API/ScreenOrientation - final screenOrientation = _window.screen.orientation; - if (screenOrientation.type.startsWith('portrait')) { - return SentryOrientation.portrait; - } - if (screenOrientation.type.startsWith('landscape')) { - return SentryOrientation.landscape; + final screenOrientation = _window.screen?.orientation; + if (screenOrientation != null) { + if (screenOrientation.type?.startsWith('portrait') ?? false) { + return SentryOrientation.portrait; + } + if (screenOrientation.type?.startsWith('landscape') ?? false) { + return SentryOrientation.landscape; + } } return null; } @@ -100,7 +101,3 @@ class WebEnricherEventProcessor implements EnricherEventProcessor { ); } } - -extension on web.Navigator { - external double? get deviceMemory; -} diff --git a/dart/lib/src/event_processor/exception/exception_event_processor.dart b/dart/lib/src/event_processor/exception/exception_event_processor.dart index ab4f5e9878..e928f476f0 100644 --- a/dart/lib/src/event_processor/exception/exception_event_processor.dart +++ b/dart/lib/src/event_processor/exception/exception_event_processor.dart @@ -1,8 +1,7 @@ import '../../event_processor.dart'; import '../../sentry_options.dart'; import 'io_exception_event_processor.dart' - if (dart.library.html) 'web_exception_event_processor.dart' - if (dart.library.js_interop) 'web_exception_event_processor.dart'; + if (dart.library.html) 'web_exception_event_processor.dart'; abstract class ExceptionEventProcessor implements EventProcessor { factory ExceptionEventProcessor(SentryOptions options) => diff --git a/dart/lib/src/origin_io.dart b/dart/lib/src/noop_origin.dart similarity index 100% rename from dart/lib/src/origin_io.dart rename to dart/lib/src/noop_origin.dart diff --git a/dart/lib/src/origin.dart b/dart/lib/src/origin.dart index 1d5b3dc4bf..ed1e066c5e 100644 --- a/dart/lib/src/origin.dart +++ b/dart/lib/src/origin.dart @@ -1,3 +1,4 @@ -export 'origin_io.dart' - if (dart.library.html) 'origin_html.dart' - if (dart.library.js_interop) 'origin_web.dart'; +import 'dart:html'; + +/// request origin, used for browser stacktrace +String get eventOrigin => '${window.location.origin}/'; diff --git a/dart/lib/src/origin_html.dart b/dart/lib/src/origin_html.dart deleted file mode 100644 index ed1e066c5e..0000000000 --- a/dart/lib/src/origin_html.dart +++ /dev/null @@ -1,4 +0,0 @@ -import 'dart:html'; - -/// request origin, used for browser stacktrace -String get eventOrigin => '${window.location.origin}/'; diff --git a/dart/lib/src/origin_web.dart b/dart/lib/src/origin_web.dart deleted file mode 100644 index db99f33c56..0000000000 --- a/dart/lib/src/origin_web.dart +++ /dev/null @@ -1,6 +0,0 @@ -// We would lose compatibility with old dart versions by adding web to pubspec. -// ignore: depend_on_referenced_packages -import 'package:web/web.dart'; - -/// request origin, used for browser stacktrace -String get eventOrigin => '${window.location.origin}/'; diff --git a/dart/lib/src/performance_collector.dart b/dart/lib/src/performance_collector.dart deleted file mode 100644 index 736534fb03..0000000000 --- a/dart/lib/src/performance_collector.dart +++ /dev/null @@ -1,13 +0,0 @@ -import '../sentry.dart'; - -abstract class PerformanceCollector {} - -/// Used for collecting continuous data about vitals (slow, frozen frames, etc.) -/// during a transaction/span. -abstract class PerformanceContinuousCollector extends PerformanceCollector { - Future onSpanStarted(ISentrySpan span); - - Future onSpanFinished(ISentrySpan span, DateTime endTimestamp); - - void clear(); -} diff --git a/dart/lib/src/platform/_html_platform.dart b/dart/lib/src/platform/_html_platform.dart deleted file mode 100644 index d3fa84eed9..0000000000 --- a/dart/lib/src/platform/_html_platform.dart +++ /dev/null @@ -1,51 +0,0 @@ -import 'dart:html' as html; -import 'platform.dart'; - -const Platform instance = WebPlatform(); - -/// [Platform] implementation that delegates to `dart:html`. -class WebPlatform extends Platform { - /// Creates a new [Platform]. - const WebPlatform(); - - @override - String get operatingSystem => _browserPlatform(); - - @override - String get operatingSystemVersion => 'unknown'; - - @override - String get localHostname => html.window.location.hostname ?? 'unknown'; - - String _browserPlatform() { - final navigatorPlatform = - html.window.navigator.platform?.toLowerCase() ?? ''; - if (navigatorPlatform.startsWith('mac')) { - return 'macos'; - } - if (navigatorPlatform.startsWith('win')) { - return 'windows'; - } - if (navigatorPlatform.contains('iphone') || - navigatorPlatform.contains('ipad') || - navigatorPlatform.contains('ipod')) { - return 'ios'; - } - if (navigatorPlatform.contains('android')) { - return 'android'; - } - if (navigatorPlatform.contains('fuchsia')) { - return 'fuchsia'; - } - - // Since some phones can report a window.navigator.platform as Linux, fall - // back to use CSS to disambiguate Android vs Linux desktop. If the CSS - // indicates that a device has a "fine pointer" (mouse) as the primary - // pointing device, then we'll assume desktop linux, and otherwise we'll - // assume Android. - if (html.window.matchMedia('only screen and (pointer: fine)').matches) { - return 'linux'; - } - return 'android'; - } -} diff --git a/dart/lib/src/platform/_web_platform.dart b/dart/lib/src/platform/_web_platform.dart index da403b254d..d3fa84eed9 100644 --- a/dart/lib/src/platform/_web_platform.dart +++ b/dart/lib/src/platform/_web_platform.dart @@ -1,12 +1,9 @@ -// We would lose compatibility with old dart versions by adding web to pubspec. -// ignore: depend_on_referenced_packages -import 'package:web/web.dart' as web; - +import 'dart:html' as html; import 'platform.dart'; const Platform instance = WebPlatform(); -/// [Platform] implementation that delegates to `dart:web`. +/// [Platform] implementation that delegates to `dart:html`. class WebPlatform extends Platform { /// Creates a new [Platform]. const WebPlatform(); @@ -18,10 +15,11 @@ class WebPlatform extends Platform { String get operatingSystemVersion => 'unknown'; @override - String get localHostname => web.window.location.hostname; + String get localHostname => html.window.location.hostname ?? 'unknown'; String _browserPlatform() { - final navigatorPlatform = web.window.navigator.platform.toLowerCase(); + final navigatorPlatform = + html.window.navigator.platform?.toLowerCase() ?? ''; if (navigatorPlatform.startsWith('mac')) { return 'macos'; } @@ -45,7 +43,7 @@ class WebPlatform extends Platform { // indicates that a device has a "fine pointer" (mouse) as the primary // pointing device, then we'll assume desktop linux, and otherwise we'll // assume Android. - if (web.window.matchMedia('only screen and (pointer: fine)').matches) { + if (html.window.matchMedia('only screen and (pointer: fine)').matches) { return 'linux'; } return 'android'; diff --git a/dart/lib/src/platform/platform.dart b/dart/lib/src/platform/platform.dart index dffd3e81fd..8f6d0760e8 100644 --- a/dart/lib/src/platform/platform.dart +++ b/dart/lib/src/platform/platform.dart @@ -1,6 +1,5 @@ -import '_io_platform.dart' - if (dart.library.html) '_html_platform.dart' - if (dart.library.js_interop) '_web_platform.dart' as platform; +import '_io_platform.dart' if (dart.library.html) '_web_platform.dart' + as platform; const Platform instance = platform.instance; diff --git a/dart/lib/src/protocol/sentry_span.dart b/dart/lib/src/protocol/sentry_span.dart index 6358b4802a..780578d182 100644 --- a/dart/lib/src/protocol/sentry_span.dart +++ b/dart/lib/src/protocol/sentry_span.dart @@ -1,11 +1,12 @@ import 'dart:async'; -import 'package:meta/meta.dart'; - -import '../../sentry.dart'; +import '../hub.dart'; import '../metrics/local_metrics_aggregator.dart'; +import '../protocol.dart'; import '../sentry_tracer.dart'; +import '../tracing.dart'; +import '../utils.dart'; typedef OnFinishedCallback = Future Function({DateTime? endTimestamp}); @@ -16,15 +17,7 @@ class SentrySpan extends ISentrySpan { late final DateTime _startTimestamp; final Hub _hub; - bool _isRootSpan = false; - - bool get isRootSpan => _isRootSpan; - - @internal - SentryTracer get tracer => _tracer; - final SentryTracer _tracer; - final Map _data = {}; dynamic _throwable; @@ -43,7 +36,6 @@ class SentrySpan extends ISentrySpan { DateTime? startTimestamp, this.samplingDecision, OnFinishedCallback? finishedCallback, - isRootSpan = false, }) { _startTimestamp = startTimestamp?.toUtc() ?? _hub.options.clock(); _finishedCallback = finishedCallback; @@ -51,7 +43,6 @@ class SentrySpan extends ISentrySpan { _localMetricsAggregator = _hub.options.enableSpanLocalMetricAggregation ? LocalMetricsAggregator() : null; - _isRootSpan = isRootSpan; } @override @@ -65,27 +56,17 @@ class SentrySpan extends ISentrySpan { } if (endTimestamp == null) { - endTimestamp = _hub.options.clock(); + _endTimestamp = _hub.options.clock(); } else if (endTimestamp.isBefore(_startTimestamp)) { _hub.options.logger( SentryLevel.warning, 'End timestamp ($endTimestamp) cannot be before start timestamp ($_startTimestamp)', ); - endTimestamp = _hub.options.clock(); + _endTimestamp = _hub.options.clock(); } else { - endTimestamp = endTimestamp.toUtc(); + _endTimestamp = endTimestamp.toUtc(); } - for (final collector in _hub.options.performanceCollectors) { - if (collector is PerformanceContinuousCollector) { - await collector.onSpanFinished(this, endTimestamp); - } - } - - // The finished flag depends on the _endTimestamp - // If we set this earlier then finished is true and then we cannot use setData etc... - _endTimestamp = endTimestamp; - // associate error if (_throwable != null) { _hub.setSpanContext(_throwable, this, _tracer.name); diff --git a/dart/lib/src/protocol/sentry_user.dart b/dart/lib/src/protocol/sentry_user.dart index c173432fcd..3b2f2cab1c 100644 --- a/dart/lib/src/protocol/sentry_user.dart +++ b/dart/lib/src/protocol/sentry_user.dart @@ -68,8 +68,6 @@ class SentryUser { final String? ipAddress; /// The user segment, for apps that divide users in user segments. - @Deprecated( - 'Will be removed in v9. Use a custom tag or context instead to capture this information.') final String? segment; /// Any other user context information that may be helpful. @@ -131,7 +129,6 @@ class SentryUser { if (username != null) 'username': username, if (email != null) 'email': email, if (ipAddress != null) 'ip_address': ipAddress, - // ignore: deprecated_member_use_from_same_package if (segment != null) 'segment': segment, if (data?.isNotEmpty ?? false) 'data': data, // ignore: deprecated_member_use_from_same_package @@ -158,7 +155,6 @@ class SentryUser { username: username ?? this.username, email: email ?? this.email, ipAddress: ipAddress ?? this.ipAddress, - // ignore: deprecated_member_use_from_same_package segment: segment ?? this.segment, data: data ?? this.data, // ignore: deprecated_member_use_from_same_package diff --git a/dart/lib/src/sentry_baggage.dart b/dart/lib/src/sentry_baggage.dart index ebed8765b1..25aab900f4 100644 --- a/dart/lib/src/sentry_baggage.dart +++ b/dart/lib/src/sentry_baggage.dart @@ -106,9 +106,7 @@ class SentryBaggage { if (scope.user?.id != null) { setUserId(scope.user!.id!); } - // ignore: deprecated_member_use_from_same_package if (scope.user?.segment != null) { - // ignore: deprecated_member_use_from_same_package setUserSegment(scope.user!.segment!); } } @@ -178,8 +176,6 @@ class SentryBaggage { set('sentry-user_id', value); } - @Deprecated( - 'Will be removed in v9 since functionality has been removed from Sentry') void setUserSegment(String value) { set('sentry-user_segment', value); } diff --git a/dart/lib/src/sentry_client_stub.dart b/dart/lib/src/sentry_client_stub.dart new file mode 100644 index 0000000000..e212b39a0d --- /dev/null +++ b/dart/lib/src/sentry_client_stub.dart @@ -0,0 +1,11 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'sentry_client.dart'; +import 'sentry_options.dart'; + +/// Implemented in `sentry_browser_client.dart` and `sentry_io_client.dart`. +SentryClient createSentryClient(SentryOptions options) => + throw UnsupportedError( + 'Cannot create a client without dart:html or dart:io.'); diff --git a/dart/lib/src/sentry_envelope.dart b/dart/lib/src/sentry_envelope.dart index fb7cd1543a..7835b7859e 100644 --- a/dart/lib/src/sentry_envelope.dart +++ b/dart/lib/src/sentry_envelope.dart @@ -13,8 +13,7 @@ import 'sentry_user_feedback.dart'; /// Class representation of `Envelope` file. class SentryEnvelope { - SentryEnvelope(this.header, this.items, - {this.containsUnhandledException = false}); + SentryEnvelope(this.header, this.items); /// Header describing envelope content. final SentryEnvelopeHeader header; @@ -22,10 +21,6 @@ class SentryEnvelope { /// All items contained in the envelope. final List items; - /// Whether the envelope contains an unhandled exception. - /// This is used to determine if the native SDK should start a new session. - final bool containsUnhandledException; - /// Create a [SentryEnvelope] containing one [SentryEnvelopeItem] which holds the [SentryEvent] data. factory SentryEnvelope.fromEvent( SentryEvent event, @@ -34,15 +29,6 @@ class SentryEnvelope { SentryTraceContextHeader? traceContext, List? attachments, }) { - bool containsUnhandledException = false; - - if (event.exceptions != null && event.exceptions!.isNotEmpty) { - // Check all exceptions for any unhandled ones - containsUnhandledException = event.exceptions!.any((exception) { - return exception.mechanism?.handled == false; - }); - } - return SentryEnvelope( SentryEnvelopeHeader( event.eventId, @@ -55,7 +41,6 @@ class SentryEnvelope { if (attachments != null) ...attachments.map((e) => SentryEnvelopeItem.fromAttachment(e)) ], - containsUnhandledException: containsUnhandledException, ); } diff --git a/dart/lib/src/sentry_options.dart b/dart/lib/src/sentry_options.dart index f3f3c65a50..956f81c056 100644 --- a/dart/lib/src/sentry_options.dart +++ b/dart/lib/src/sentry_options.dart @@ -501,14 +501,6 @@ class SentryOptions { return tracesSampleRate != null || tracesSampler != null; } - List get performanceCollectors => - _performanceCollectors; - final List _performanceCollectors = []; - - void addPerformanceCollector(PerformanceCollector collector) { - _performanceCollectors.add(collector); - } - @internal late SentryExceptionFactory exceptionFactory = SentryExceptionFactory(this); diff --git a/dart/lib/src/sentry_stack_trace_factory.dart b/dart/lib/src/sentry_stack_trace_factory.dart index 25a97e6eab..9d4a42bffc 100644 --- a/dart/lib/src/sentry_stack_trace_factory.dart +++ b/dart/lib/src/sentry_stack_trace_factory.dart @@ -1,7 +1,7 @@ import 'package:meta/meta.dart'; import 'package:stack_trace/stack_trace.dart'; -import 'origin.dart'; +import 'noop_origin.dart' if (dart.library.html) 'origin.dart'; import 'protocol.dart'; import 'sentry_options.dart'; diff --git a/dart/lib/src/sentry_trace_context_header.dart b/dart/lib/src/sentry_trace_context_header.dart index d1ee5368af..bcb1d0b1bb 100644 --- a/dart/lib/src/sentry_trace_context_header.dart +++ b/dart/lib/src/sentry_trace_context_header.dart @@ -20,8 +20,6 @@ class SentryTraceContextHeader { final String? release; final String? environment; final String? userId; - @Deprecated( - 'Will be removed in v9 since functionality has been removed from Sentry') final String? userSegment; final String? transaction; final String? sampleRate; @@ -50,7 +48,6 @@ class SentryTraceContextHeader { if (release != null) 'release': release, if (environment != null) 'environment': environment, if (userId != null) 'user_id': userId, - // ignore: deprecated_member_use_from_same_package if (userSegment != null) 'user_segment': userSegment, if (transaction != null) 'transaction': transaction, if (sampleRate != null) 'sample_rate': sampleRate, @@ -74,9 +71,7 @@ class SentryTraceContextHeader { if (userId != null) { baggage.setUserId(userId!); } - // ignore: deprecated_member_use_from_same_package if (userSegment != null) { - // ignore: deprecated_member_use_from_same_package baggage.setUserSegment(userSegment!); } if (transaction != null) { diff --git a/dart/lib/src/sentry_tracer.dart b/dart/lib/src/sentry_tracer.dart index 66c179e386..2326db0716 100644 --- a/dart/lib/src/sentry_tracer.dart +++ b/dart/lib/src/sentry_tracer.dart @@ -69,7 +69,6 @@ class SentryTracer extends ISentrySpan { _hub, samplingDecision: transactionContext.samplingDecision, startTimestamp: startTimestamp, - isRootSpan: true, ); _waitForChildren = waitForChildren; _autoFinishAfter = autoFinishAfter; @@ -81,12 +80,6 @@ class SentryTracer extends ISentrySpan { SentryTransactionNameSource.custom; _trimEnd = trimEnd; _onFinish = onFinish; - - for (final collector in _hub.options.performanceCollectors) { - if (collector is PerformanceContinuousCollector) { - collector.onSpanStarted(_rootSpan); - } - } } @override @@ -263,12 +256,6 @@ class SentryTracer extends ISentrySpan { _children.add(child); - for (final collector in _hub.options.performanceCollectors) { - if (collector is PerformanceContinuousCollector) { - collector.onSpanStarted(child); - } - } - return child; } @@ -374,7 +361,6 @@ class SentryTracer extends ISentrySpan { release: _hub.options.release, environment: _hub.options.environment, userId: null, // because of PII not sending it for now - // ignore: deprecated_member_use_from_same_package userSegment: user?.segment, transaction: _isHighQualityTransactionName(transactionNameSource) ? name : null, diff --git a/dart/lib/src/utils/isolate_utils.dart b/dart/lib/src/utils/isolate_utils.dart index 6575965ff9..3e9c4b20bc 100644 --- a/dart/lib/src/utils/isolate_utils.dart +++ b/dart/lib/src/utils/isolate_utils.dart @@ -1,8 +1,7 @@ import 'package:meta/meta.dart'; import '_io_get_isolate_name.dart' - if (dart.library.html) '_web_get_isolate_name.dart' - if (dart.library.js_interop) '_web_get_isolate_name.dart' as isolate_getter; + if (dart.library.html) '_web_get_isolate_name.dart' as isolate_getter; @internal String? getIsolateName() => isolate_getter.getIsolateName(); diff --git a/dart/lib/src/version.dart b/dart/lib/src/version.dart index 33e5ba6503..961566fdc3 100644 --- a/dart/lib/src/version.dart +++ b/dart/lib/src/version.dart @@ -9,7 +9,7 @@ library version; /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.4.0-beta.1'; +const String sdkVersion = '8.3.0'; String sdkName(bool isWeb) => isWeb ? _browserSdkName : _ioSdkName; diff --git a/dart/pubspec.yaml b/dart/pubspec.yaml index bfe40f38c2..41aa1b7d0c 100644 --- a/dart/pubspec.yaml +++ b/dart/pubspec.yaml @@ -1,5 +1,5 @@ name: sentry -version: 8.4.0-beta.1 +version: 8.3.0 description: > A crash reporting library for Dart that sends crash reports to Sentry.io. This library supports Dart VM and Web. For Flutter consider sentry_flutter instead. @@ -26,12 +26,11 @@ dependencies: uuid: '>=3.0.0 <5.0.0' dev_dependencies: - build_runner: ^2.3.0 + build_runner: ^2.4.2 mockito: ^5.1.0 - lints: '>=2.0.0 <5.0.0' + lints: ^4.0.0 test: ^1.21.1 yaml: ^3.1.0 # needed for version match (code and pubspec) collection: ^1.16.0 coverage: ^1.3.0 intl: '>=0.17.0 <1.0.0' - version: ^3.0.2 diff --git a/dart/test/event_processor/enricher/io_platform_memory_test.dart b/dart/test/event_processor/enricher/io_platform_memory_test.dart deleted file mode 100644 index 0f987b935c..0000000000 --- a/dart/test/event_processor/enricher/io_platform_memory_test.dart +++ /dev/null @@ -1,60 +0,0 @@ -@TestOn('vm') -library dart_test; - -import 'dart:io'; - -import 'package:sentry/sentry.dart'; -import 'package:sentry/src/event_processor/enricher/io_platform_memory.dart'; -import 'package:test/test.dart'; - -void main() { - late Fixture fixture; - - setUp(() { - fixture = Fixture(); - }); - - test('total physical memory', () { - final sut = fixture.getSut(); - final totalPhysicalMemory = sut.getTotalPhysicalMemory(); - - switch (Platform.operatingSystem) { - case 'linux': - expect(totalPhysicalMemory, isNotNull); - expect(totalPhysicalMemory! > 0, true); - break; - case 'windows': - expect(totalPhysicalMemory, isNotNull); - expect(totalPhysicalMemory! > 0, true); - break; - default: - expect(totalPhysicalMemory, isNull); - } - }); - - test('free physical memory', () { - final sut = fixture.getSut(); - final freePhysicalMemory = sut.getTotalPhysicalMemory(); - - switch (Platform.operatingSystem) { - case 'linux': - expect(freePhysicalMemory, isNotNull); - expect(freePhysicalMemory! > 0, true); - break; - case 'windows': - expect(freePhysicalMemory, isNotNull); - expect(freePhysicalMemory! > 0, true); - break; - default: - expect(freePhysicalMemory, isNull); - } - }); -} - -class Fixture { - var options = SentryOptions(); - - PlatformMemory getSut() { - return PlatformMemory(options); - } -} diff --git a/dart/test/event_processor/enricher/web_enricher_test.dart b/dart/test/event_processor/enricher/web_enricher_test.dart index d2590a09fa..cdc7310fab 100644 --- a/dart/test/event_processor/enricher/web_enricher_test.dart +++ b/dart/test/event_processor/enricher/web_enricher_test.dart @@ -1,10 +1,10 @@ @TestOn('browser') library dart_test; +import 'dart:html' as html; + import 'package:sentry/sentry.dart'; -import 'package:sentry/src/event_processor/enricher/html_enricher_event_processor.dart' - if (dart.library.html) 'package:sentry/src/event_processor/enricher/html_enricher_event_processor.dart' - if (dart.library.js_interop) 'package:sentry/src/event_processor/enricher/web_enricher_event_processor.dart'; +import 'package:sentry/src/event_processor/enricher/web_enricher_event_processor.dart'; import 'package:test/test.dart'; import '../../mocks.dart'; @@ -193,8 +193,10 @@ void main() { ); await Sentry.close(); - expect(sentryOptions.eventProcessors.map((e) => e.runtimeType.toString()), - contains('$WebEnricherEventProcessor')); + final ioEnricherCount = sentryOptions.eventProcessors + .whereType() + .length; + expect(ioEnricherCount, 1); }); }); } @@ -204,6 +206,10 @@ class Fixture { final options = SentryOptions( dsn: fakeDsn, checker: MockPlatformChecker(hasNativeIntegration: false)); - return enricherEventProcessor(options) as WebEnricherEventProcessor; + + return WebEnricherEventProcessor( + html.window, + options, + ); } } diff --git a/dart/test/example_web_compile_test.dart b/dart/test/example_web_compile_test.dart index 1a2a0cf13f..4199a47dda 100644 --- a/dart/test/example_web_compile_test.dart +++ b/dart/test/example_web_compile_test.dart @@ -5,35 +5,29 @@ import 'dart:async'; import 'dart:convert'; import 'dart:io'; -import 'package:version/version.dart'; import 'package:test/test.dart'; // Tests for the following issue // https://github.com/getsentry/sentry-dart/issues/1893 void main() { - final dartVersion = Version.parse(Platform.version.split(' ')[0]); - final isLegacy = dartVersion < Version.parse('3.3.0'); - final exampleAppDir = isLegacy ? 'example_web_legacy' : 'example_web'; - final exampleAppWorkingDir = - '${Directory.current.path}${Platform.pathSeparator}$exampleAppDir'; - group('Compile $exampleAppDir', () { + group('Compile example_web', () { test( 'dart pub get and compilation should run successfully', () async { final result = await _runProcess('dart pub get', - workingDirectory: exampleAppWorkingDir); + workingDirectory: _exampleWebWorkingDir); expect(result.exitCode, 0, - reason: 'Could run `dart pub get` for $exampleAppDir. ' + reason: 'Could run `dart pub get` for example_web. ' 'Likely caused by outdated dependencies'); // running this test locally require clean working directory final cleanResult = await _runProcess('dart run build_runner clean', - workingDirectory: exampleAppWorkingDir); + workingDirectory: _exampleWebWorkingDir); expect(cleanResult.exitCode, 0); final compileResult = await _runProcess( 'dart run build_runner build -r web -o build --delete-conflicting-outputs', - workingDirectory: exampleAppWorkingDir); + workingDirectory: _exampleWebWorkingDir); expect(compileResult.exitCode, 0, - reason: 'Could not compile $exampleAppDir project'); + reason: 'Could not compile example_web project'); expect( compileResult.stdout, isNot(contains( @@ -42,9 +36,8 @@ void main() { 'Could not compile main.dart, likely because of dart:io import.'); expect( compileResult.stdout, - contains(isLegacy - ? 'Succeeded after ' - : 'build_web_compilers:entrypoint on web/main.dart:Compiled')); + contains( + 'build_web_compilers:entrypoint on web/main.dart:Compiled')); }, timeout: Timeout(const Duration(minutes: 1)), // double of detault timeout ); @@ -83,6 +76,10 @@ Future<_CommandResult> _runProcess(String command, return _CommandResult(exitCode: exitCode, stdout: processOut); } +String get _exampleWebWorkingDir { + return '${Directory.current.path}${Platform.pathSeparator}example_web'; +} + class _CommandResult { final int exitCode; final String stdout; diff --git a/dart/test/mocks/mock_envelope.dart b/dart/test/mocks/mock_envelope.dart index 1009f2e396..9b43a41b8a 100644 --- a/dart/test/mocks/mock_envelope.dart +++ b/dart/test/mocks/mock_envelope.dart @@ -23,7 +23,4 @@ class MockEnvelope implements SentryEnvelope { @override List items = []; - - @override - bool get containsUnhandledException => false; } diff --git a/dart/test/protocol/sentry_baggage_header_test.dart b/dart/test/protocol/sentry_baggage_header_test.dart index 3e8555aba9..38428be41a 100644 --- a/dart/test/protocol/sentry_baggage_header_test.dart +++ b/dart/test/protocol/sentry_baggage_header_test.dart @@ -17,7 +17,6 @@ void main() { baggage.setRelease('release'); baggage.setEnvironment('environment'); baggage.setUserId('userId'); - // ignore: deprecated_member_use_from_same_package baggage.setUserSegment('userSegment'); baggage.setTransaction('transaction'); baggage.setSampleRate('1.0'); diff --git a/dart/test/protocol/sentry_user_test.dart b/dart/test/protocol/sentry_user_test.dart index d3c8e078ba..2a958624e2 100644 --- a/dart/test/protocol/sentry_user_test.dart +++ b/dart/test/protocol/sentry_user_test.dart @@ -91,7 +91,6 @@ void main() { expect('email1', copy.email); expect('ipAddress1', copy.ipAddress); expect({'key1': 'value1'}, copy.data); - // ignore: deprecated_member_use_from_same_package expect('seg1', copy.segment); }); }); diff --git a/dart/test/sentry_client_test.dart b/dart/test/sentry_client_test.dart index 153c1515f0..b8c6bee716 100644 --- a/dart/test/sentry_client_test.dart +++ b/dart/test/sentry_client_test.dart @@ -139,10 +139,7 @@ void main() { capturedEvent.threads?.first.id, ); }, - onPlatform: { - 'js': Skip("Isolates don't exist on the web"), - 'wasm': Skip("Isolates don't exist on the web") - }, + onPlatform: {'js': Skip("Isolates don't exist on the web")}, ); test( diff --git a/dart/test/sentry_trace_context_header_test.dart b/dart/test/sentry_trace_context_header_test.dart index c4f856f344..6ba6d93bc2 100644 --- a/dart/test/sentry_trace_context_header_test.dart +++ b/dart/test/sentry_trace_context_header_test.dart @@ -24,7 +24,6 @@ void main() { expect(context.release, 'release'); expect(context.environment, 'environment'); expect(context.userId, 'user_id'); - // ignore: deprecated_member_use_from_same_package expect(context.userSegment, 'user_segment'); expect(context.transaction, 'transaction'); expect(context.sampleRate, '1.0'); diff --git a/dart/test/sentry_tracer_test.dart b/dart/test/sentry_tracer_test.dart index a1251c224b..7ba5e80fac 100644 --- a/dart/test/sentry_tracer_test.dart +++ b/dart/test/sentry_tracer_test.dart @@ -582,7 +582,6 @@ void main() { expect(context.publicKey, 'abc'); expect(context.release, 'release'); expect(context.environment, 'environment'); - // ignore: deprecated_member_use_from_same_package expect(context.userSegment, 'segment'); expect(context.transaction, 'name'); expect(context.sampleRate, '1'); diff --git a/dart/test/stack_trace_test.dart b/dart/test/stack_trace_test.dart index 3ab8f9d116..6524581794 100644 --- a/dart/test/stack_trace_test.dart +++ b/dart/test/stack_trace_test.dart @@ -3,7 +3,8 @@ // found in the LICENSE file. import 'package:sentry/sentry.dart'; -import 'package:sentry/src/origin.dart'; +import 'package:sentry/src/noop_origin.dart' + if (dart.library.html) 'package:sentry/src/origin.dart'; import 'package:sentry/src/sentry_stack_trace_factory.dart'; import 'package:stack_trace/stack_trace.dart'; import 'package:test/test.dart'; diff --git a/dart/test/test_utils.dart b/dart/test/test_utils.dart index 87a0be0f0a..627d19903d 100644 --- a/dart/test/test_utils.dart +++ b/dart/test/test_utils.dart @@ -117,11 +117,6 @@ Future testCaptureException( final topFrame = (stacktrace['frames'] as Iterable).last as Map; - if (topFrame['function'].contains('browser_test.dart.wasm')) { - // TODO stacktrace parsing for wasm is not implemented yet - // {filename: unparsed, function: at testCaptureException (http://localhost:59959/9R3KYfjvkWCySr4h2hI0pVO7PqmPFeE6/test/sentry_browser_test.dart.browser_test.dart.wasm:wasm-function[1007]:0x4bc18), abs_path: http://localhost:59959/unparsed, in_app: true} - return; - } expect( topFrame.keys, ['filename', 'function', 'lineno', 'colno', 'abs_path', 'in_app'], diff --git a/dio/lib/src/version.dart b/dio/lib/src/version.dart index b6552c547c..4b219aa09a 100644 --- a/dio/lib/src/version.dart +++ b/dio/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.4.0-beta.1'; +const String sdkVersion = '8.3.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_dio'; diff --git a/dio/pubspec.yaml b/dio/pubspec.yaml index 690af6b9ab..b4865df495 100644 --- a/dio/pubspec.yaml +++ b/dio/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_dio description: An integration which adds support for performance tracing for the Dio package. -version: 8.4.0-beta.1 +version: 8.3.0 homepage: https://docs.sentry.io/platforms/dart/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -19,7 +19,7 @@ platforms: dependencies: dio: ^5.0.0 - sentry: 8.4.0-beta.1 + sentry: 8.3.0 dev_dependencies: meta: ^1.3.0 diff --git a/drift/lib/src/version.dart b/drift/lib/src/version.dart index ae721deab9..f56b0af46f 100644 --- a/drift/lib/src/version.dart +++ b/drift/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.4.0-beta.1'; +const String sdkVersion = '8.3.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_drift'; diff --git a/drift/pubspec.yaml b/drift/pubspec.yaml index ef7f846b6a..b3a529de9c 100644 --- a/drift/pubspec.yaml +++ b/drift/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_drift description: An integration which adds support for performance tracing for the drift package. -version: 8.4.0-beta.1 +version: 8.3.0 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -17,7 +17,7 @@ platforms: web: dependencies: - sentry: 8.4.0-beta.1 + sentry: 8.3.0 meta: ^1.3.0 drift: ^2.13.0 diff --git a/file/lib/src/sentry_file_extension.dart b/file/lib/src/sentry_file_extension.dart index 3cc764c36e..f6f0c70de2 100644 --- a/file/lib/src/sentry_file_extension.dart +++ b/file/lib/src/sentry_file_extension.dart @@ -1,8 +1,6 @@ // ignore_for_file: invalid_use_of_internal_member -import 'dart:io' - if (dart.library.html) 'dart:html' - if (dart.library.js_interop) 'dart:js_interop'; +import 'dart:io' if (dart.library.html) 'dart:html'; import 'package:meta/meta.dart'; import 'package:sentry/sentry.dart'; diff --git a/file/lib/src/version.dart b/file/lib/src/version.dart index d30a72a6e7..6e9dc3050c 100644 --- a/file/lib/src/version.dart +++ b/file/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.4.0-beta.1'; +const String sdkVersion = '8.3.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_file'; diff --git a/file/pubspec.yaml b/file/pubspec.yaml index 17417ab6d3..9a2027e8c7 100644 --- a/file/pubspec.yaml +++ b/file/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_file description: An integration which adds support for performance tracing for dart.io.File. -version: 8.4.0-beta.1 +version: 8.3.0 homepage: https://docs.sentry.io/platforms/dart/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -17,7 +17,7 @@ platforms: windows: dependencies: - sentry: 8.4.0-beta.1 + sentry: 8.3.0 meta: ^1.3.0 dev_dependencies: diff --git a/flutter/android/build.gradle b/flutter/android/build.gradle index 3242dddd64..89146e73ff 100644 --- a/flutter/android/build.gradle +++ b/flutter/android/build.gradle @@ -60,7 +60,7 @@ android { } dependencies { - api 'io.sentry:sentry-android:7.11.0' + api 'io.sentry:sentry-android:7.10.0' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" // Required -- JUnit 4 framework diff --git a/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutterPlugin.kt b/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutterPlugin.kt index 4f154a2465..424e51c6b7 100644 --- a/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutterPlugin.kt +++ b/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutterPlugin.kt @@ -2,7 +2,6 @@ package io.sentry.flutter import android.app.Activity import android.content.Context -import android.os.Build import android.util.Log import io.flutter.embedding.engine.plugins.FlutterPlugin import io.flutter.embedding.engine.plugins.activity.ActivityAware @@ -73,7 +72,6 @@ class SentryFlutterPlugin : FlutterPlugin, MethodCallHandler, ActivityAware { "setTag" -> setTag(call.argument("key"), call.argument("value"), result) "removeTag" -> removeTag(call.argument("key"), result) "loadContexts" -> loadContexts(result) - "displayRefreshRate" -> displayRefreshRate(result) else -> result.notImplemented() } } @@ -181,29 +179,6 @@ class SentryFlutterPlugin : FlutterPlugin, MethodCallHandler, ActivityAware { } } - private fun displayRefreshRate(result: Result) { - var refreshRate: Int? = null - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { - val display = activity?.get()?.display - if (display != null) { - refreshRate = display.refreshRate.toInt() - } - } else { - val display = - activity - ?.get() - ?.window - ?.windowManager - ?.defaultDisplay - if (display != null) { - refreshRate = display.refreshRate.toInt() - } - } - - result.success(refreshRate) - } - private fun TimeSpan.addToMap(map: MutableMap) { if (startTimestamp == null) return @@ -355,9 +330,8 @@ class SentryFlutterPlugin : FlutterPlugin, MethodCallHandler, ActivityAware { val args = call.arguments() as List? ?: listOf() if (args.isNotEmpty()) { val event = args.first() as ByteArray? - val containsUnhandledException = args[1] as Boolean - if (event != null && event.isNotEmpty() && containsUnhandledException != null) { - val id = InternalSentrySdk.captureEnvelope(event, containsUnhandledException) + if (event != null && event.isNotEmpty()) { + val id = InternalSentrySdk.captureEnvelope(event) if (id != null) { result.success("") } else { diff --git a/flutter/example/pubspec.yaml b/flutter/example/pubspec.yaml index 73988305ce..1f53f5d1c3 100644 --- a/flutter/example/pubspec.yaml +++ b/flutter/example/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_flutter_example description: Demonstrates how to use the sentry_flutter plugin. -version: 8.4.0-beta.1 +version: 8.3.0 publish_to: 'none' # Remove this line if you wish to publish to pub.dev diff --git a/flutter/ios/Classes/SentryFlutterPluginApple.swift b/flutter/ios/Classes/SentryFlutterPluginApple.swift index 35249ef5d1..fc8fb42f9c 100644 --- a/flutter/ios/Classes/SentryFlutterPluginApple.swift +++ b/flutter/ios/Classes/SentryFlutterPluginApple.swift @@ -5,7 +5,6 @@ import UIKit #elseif os(macOS) import FlutterMacOS import AppKit -import CoreVideo #endif // swiftlint:disable file_length function_body_length @@ -165,15 +164,6 @@ public class SentryFlutterPluginApple: NSObject, FlutterPlugin { collectProfile(call, result) #endif - case "displayRefreshRate": - displayRefreshRate(result) - - case "pauseAppHangTracking": - pauseAppHangTracking(result) - - case "resumeAppHangTracking": - resumeAppHangTracking(result) - default: result(FlutterMethodNotImplemented) } @@ -661,74 +651,6 @@ public class SentryFlutterPluginApple: NSObject, FlutterPlugin { PrivateSentrySDKOnly.discardProfiler(forTrace: SentryId(uuidString: traceId)) result(nil) } - - #if os(iOS) - // Taken from the Flutter engine: - // https://github.com/flutter/engine/blob/main/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.mm#L150 - private func displayRefreshRate(_ result: @escaping FlutterResult) { - let displayLink = CADisplayLink(target: self, selector: #selector(onDisplayLink(_:))) - displayLink.add(to: .main, forMode: .common) - displayLink.isPaused = true - - let preferredFPS = displayLink.preferredFramesPerSecond - displayLink.invalidate() - - if preferredFPS != 0 { - result(preferredFPS) - return - } - - if #available(iOS 13.0, *) { - guard let windowScene = UIApplication.shared.windows.first?.windowScene else { - result(nil) - return - } - result(windowScene.screen.maximumFramesPerSecond) - } else { - result(UIScreen.main.maximumFramesPerSecond) - } - } - - @objc private func onDisplayLink(_ displayLink: CADisplayLink) { - // No-op - } - #elseif os(macOS) - private func displayRefreshRate(_ result: @escaping FlutterResult) { - // We don't use CADisplayLink for macOS because it's only available starting with macOS 14 - guard let window = NSApplication.shared.keyWindow else { - result(nil) - return - } - - guard let screen = window.screen else { - result(nil) - return - } - - guard let displayID = - screen.deviceDescription[NSDeviceDescriptionKey("NSScreenNumber")] as? CGDirectDisplayID else { - result(nil) - return - } - - guard let mode = CGDisplayCopyDisplayMode(displayID) else { - result(nil) - return - } - - result(Int(mode.refreshRate)) - } - #endif - - private func pauseAppHangTracking(_ result: @escaping FlutterResult) { - SentrySDK.pauseAppHangTracking() - result("") - } - - private func resumeAppHangTracking(_ result: @escaping FlutterResult) { - SentrySDK.resumeAppHangTracking() - result("") - } } // swiftlint:enable function_body_length diff --git a/flutter/ios/sentry_flutter.podspec b/flutter/ios/sentry_flutter.podspec index 00b575b956..bd76cc2f2f 100644 --- a/flutter/ios/sentry_flutter.podspec +++ b/flutter/ios/sentry_flutter.podspec @@ -16,7 +16,7 @@ Sentry SDK for Flutter with support to native through sentry-cocoa. :tag => s.version.to_s } s.source_files = 'Classes/**/*' s.public_header_files = 'Classes/**/*.h' - s.dependency 'Sentry/HybridSDK', '8.30.0' + s.dependency 'Sentry/HybridSDK', '8.29.0' s.ios.dependency 'Flutter' s.osx.dependency 'FlutterMacOS' s.ios.deployment_target = '12.0' diff --git a/flutter/lib/src/event_processor/flutter_enricher_event_processor.dart b/flutter/lib/src/event_processor/flutter_enricher_event_processor.dart index 5a6a2e0397..0ea1b731d6 100644 --- a/flutter/lib/src/event_processor/flutter_enricher_event_processor.dart +++ b/flutter/lib/src/event_processor/flutter_enricher_event_processor.dart @@ -8,8 +8,6 @@ import 'package:sentry/sentry.dart'; import '../navigation/sentry_navigator_observer.dart'; import '../sentry_flutter_options.dart'; -import '../utils/enum_wrapper.dart'; - typedef WidgetBindingGetter = WidgetsBinding? Function(); /// Enriches [SentryEvent]s with various kinds of information. @@ -141,16 +139,15 @@ class FlutterEnricherEventProcessor implements EventProcessor { return { 'has_render_view': hasRenderView.toString(), if (tempDebugBrightnessOverride != null) - 'debug_brightness_override': pDescribeEnum(tempDebugBrightnessOverride), + 'debug_brightness_override': tempDebugBrightnessOverride.name, if (debugPlatformOverride != null) - 'debug_default_target_platform_override': - pDescribeEnum(debugPlatformOverride), + 'debug_default_target_platform_override': debugPlatformOverride.name, if (initialLifecycleState != null && initialLifecycleState.isNotEmpty) 'initial_lifecycle_state': initialLifecycleState, if (defaultRouteName != null && defaultRouteName.isNotEmpty) 'default_route_name': defaultRouteName, if (currentLifecycle != null) - 'current_lifecycle_state': pDescribeEnum(currentLifecycle), + 'current_lifecycle_state': currentLifecycle.name, // Seems to always return false. // Also always fails in tests. // See https://github.com/flutter/flutter/issues/83919 @@ -198,7 +195,7 @@ class FlutterEnricherEventProcessor implements EventProcessor { SentryOperatingSystem _getOperatingSystem(SentryOperatingSystem? os) { return (os ?? SentryOperatingSystem()).copyWith( // ignore: deprecated_member_use - theme: os?.theme ?? pDescribeEnum(window.platformBrightness), + theme: os?.theme ?? describeEnum(window.platformBrightness), ); } diff --git a/flutter/lib/src/event_processor/native_app_start_event_processor.dart b/flutter/lib/src/event_processor/native_app_start_event_processor.dart index a0da42359e..f8ea23b265 100644 --- a/flutter/lib/src/event_processor/native_app_start_event_processor.dart +++ b/flutter/lib/src/event_processor/native_app_start_event_processor.dart @@ -4,6 +4,7 @@ import 'dart:async'; import '../../sentry_flutter.dart'; import '../integrations/integrations.dart'; +import '../native/sentry_native.dart'; // ignore: implementation_imports import 'package:sentry/src/sentry_tracer.dart'; @@ -11,37 +12,39 @@ import 'package:sentry/src/sentry_tracer.dart'; /// EventProcessor that enriches [SentryTransaction] objects with app start /// measurement. class NativeAppStartEventProcessor implements EventProcessor { + final SentryNative _native; final Hub _hub; - NativeAppStartEventProcessor({Hub? hub}) : _hub = hub ?? HubAdapter(); + NativeAppStartEventProcessor( + this._native, { + Hub? hub, + }) : _hub = hub ?? HubAdapter(); @override Future apply(SentryEvent event, Hint hint) async { final options = _hub.options; - if (NativeAppStartIntegration.didAddAppStartMeasurement || + if (_native.didAddAppStartMeasurement || event is! SentryTransaction || options is! SentryFlutterOptions) { return event; } - AppStartInfo? appStartInfo; + final appStartInfo = await NativeAppStartIntegration.getAppStartInfo(); + + final appStartEnd = _native.appStartEnd; if (!options.autoAppStart) { - final appStartEnd = NativeAppStartIntegration.appStartEnd; if (appStartEnd != null) { - appStartInfo = await NativeAppStartIntegration.getAppStartInfo(); appStartInfo?.end = appStartEnd; } else { // If autoAppStart is disabled and appStartEnd is not set, we can't add app starts return event; } - } else { - appStartInfo = await NativeAppStartIntegration.getAppStartInfo(); } final measurement = appStartInfo?.toMeasurement(); if (measurement != null) { event.measurements[measurement.name] = measurement; - NativeAppStartIntegration.didAddAppStartMeasurement = true; + _native.didAddAppStartMeasurement = true; } if (appStartInfo != null) { diff --git a/flutter/lib/src/file_system_transport.dart b/flutter/lib/src/file_system_transport.dart index 85cc0947a7..cf073a38ea 100644 --- a/flutter/lib/src/file_system_transport.dart +++ b/flutter/lib/src/file_system_transport.dart @@ -5,22 +5,20 @@ import 'dart:typed_data'; import 'package:flutter/services.dart'; import 'package:sentry/sentry.dart'; -import 'native/sentry_native_binding.dart'; - class FileSystemTransport implements Transport { - FileSystemTransport(this._native, this._options); + FileSystemTransport(this._channel, this._options); - final SentryNativeBinding _native; + final MethodChannel _channel; final SentryOptions _options; @override Future send(SentryEnvelope envelope) async { final envelopeData = []; await envelope.envelopeStream(_options).forEach(envelopeData.addAll); + // https://flutter.dev/docs/development/platform-integration/platform-channels#codec + final args = [Uint8List.fromList(envelopeData)]; try { - // TODO avoid copy - await _native.captureEnvelope(Uint8List.fromList(envelopeData), - envelope.containsUnhandledException); + await _channel.invokeMethod('captureEnvelope', args); } catch (exception, stackTrace) { _options.logger( SentryLevel.error, diff --git a/flutter/lib/src/frame_callback_handler.dart b/flutter/lib/src/frame_callback_handler.dart index 139d3cbde9..71a8f928b1 100644 --- a/flutter/lib/src/frame_callback_handler.dart +++ b/flutter/lib/src/frame_callback_handler.dart @@ -1,11 +1,7 @@ -import 'package:flutter/cupertino.dart'; import 'package:flutter/scheduler.dart'; abstract class FrameCallbackHandler { void addPostFrameCallback(FrameCallback callback); - void addPersistentFrameCallback(FrameCallback callback); - Future get endOfFrame; - bool get hasScheduledFrame; } class DefaultFrameCallbackHandler implements FrameCallbackHandler { @@ -16,21 +12,4 @@ class DefaultFrameCallbackHandler implements FrameCallbackHandler { SchedulerBinding.instance.addPostFrameCallback(callback); } catch (_) {} } - - @override - void addPersistentFrameCallback(FrameCallback callback) { - try { - WidgetsBinding.instance.addPersistentFrameCallback(callback); - } catch (_) {} - } - - @override - Future get endOfFrame async { - try { - await WidgetsBinding.instance.endOfFrame; - } catch (_) {} - } - - @override - bool get hasScheduledFrame => WidgetsBinding.instance.hasScheduledFrame; } diff --git a/flutter/lib/src/integrations/connectivity/connectivity_provider.dart b/flutter/lib/src/integrations/connectivity/connectivity_provider.dart index ea27f80f72..30095dda0d 100644 --- a/flutter/lib/src/integrations/connectivity/connectivity_provider.dart +++ b/flutter/lib/src/integrations/connectivity/connectivity_provider.dart @@ -1,6 +1,5 @@ import 'noop_connectivity_provider.dart' - if (dart.library.html) 'html_connectivity_provider.dart' - if (dart.library.js_interop) 'web_connectivity_provider.dart'; + if (dart.library.html) 'web_connectivity_provider.dart'; abstract class ConnectivityProvider { factory ConnectivityProvider() => connectivityProvider(); diff --git a/flutter/lib/src/integrations/connectivity/html_connectivity_provider.dart b/flutter/lib/src/integrations/connectivity/html_connectivity_provider.dart deleted file mode 100644 index 34d0e0ab42..0000000000 --- a/flutter/lib/src/integrations/connectivity/html_connectivity_provider.dart +++ /dev/null @@ -1,32 +0,0 @@ -import 'dart:async'; -import 'dart:html' as html; - -import 'connectivity_provider.dart'; - -ConnectivityProvider connectivityProvider() { - return WebConnectivityProvider(); -} - -class WebConnectivityProvider implements ConnectivityProvider { - StreamSubscription? _onOnlineSub; - StreamSubscription? _onOfflineSub; - - @override - void listen(void Function(String connectivity) onChange) { - _onOnlineSub = html.window.onOnline.listen((_) { - onChange('wifi'); - }); - _onOfflineSub = html.window.onOffline.listen((_) { - onChange('none'); - }); - } - - @override - void cancel() { - _onOnlineSub?.cancel(); - _onOnlineSub = null; - - _onOfflineSub?.cancel(); - _onOfflineSub = null; - } -} diff --git a/flutter/lib/src/integrations/connectivity/web_connectivity_provider.dart b/flutter/lib/src/integrations/connectivity/web_connectivity_provider.dart index d1c18af777..34d0e0ab42 100644 --- a/flutter/lib/src/integrations/connectivity/web_connectivity_provider.dart +++ b/flutter/lib/src/integrations/connectivity/web_connectivity_provider.dart @@ -1,8 +1,5 @@ import 'dart:async'; - -// We would lose compatibility with old dart versions by adding web to pubspec. -// ignore: depend_on_referenced_packages -import 'package:web/web.dart' as web; +import 'dart:html' as html; import 'connectivity_provider.dart'; @@ -11,19 +8,15 @@ ConnectivityProvider connectivityProvider() { } class WebConnectivityProvider implements ConnectivityProvider { - StreamSubscription? _onOnlineSub; - StreamSubscription? _onOfflineSub; + StreamSubscription? _onOnlineSub; + StreamSubscription? _onOfflineSub; @override void listen(void Function(String connectivity) onChange) { - _onOnlineSub = web.EventStreamProviders.onlineEvent - .forElement(web.document.body!) - .listen((_) { + _onOnlineSub = html.window.onOnline.listen((_) { onChange('wifi'); }); - _onOfflineSub = web.EventStreamProviders.offlineEvent - .forElement(web.document.body!) - .listen((_) { + _onOfflineSub = html.window.onOffline.listen((_) { onChange('none'); }); } diff --git a/flutter/lib/src/integrations/load_contexts_integration.dart b/flutter/lib/src/integrations/load_contexts_integration.dart index a6ed4effcc..df8b52b97a 100644 --- a/flutter/lib/src/integrations/load_contexts_integration.dart +++ b/flutter/lib/src/integrations/load_contexts_integration.dart @@ -1,7 +1,7 @@ import 'dart:async'; +import 'package:flutter/services.dart'; import 'package:sentry/sentry.dart'; -import '../native/sentry_native_binding.dart'; import '../sentry_flutter_options.dart'; /// Load Device's Contexts from the iOS & Android SDKs. @@ -15,30 +15,32 @@ import '../sentry_flutter_options.dart'; /// /// This integration is only executed on iOS, macOS & Android Apps. class LoadContextsIntegration extends Integration { - final SentryNativeBinding _native; + final MethodChannel _channel; - LoadContextsIntegration(this._native); + LoadContextsIntegration(this._channel); @override void call(Hub hub, SentryFlutterOptions options) { options.addEventProcessor( - _LoadContextsIntegrationEventProcessor(_native, options), + _LoadContextsIntegrationEventProcessor(_channel, options), ); options.sdk.addIntegration('loadContextsIntegration'); } } class _LoadContextsIntegrationEventProcessor implements EventProcessor { - _LoadContextsIntegrationEventProcessor(this._native, this._options); + _LoadContextsIntegrationEventProcessor(this._channel, this._options); - final SentryNativeBinding _native; + final MethodChannel _channel; final SentryFlutterOptions _options; @override Future apply(SentryEvent event, Hint hint) async { - // TODO don't copy everything (i.e. avoid unnecessary Map.from()) try { - final infos = await _native.loadContexts() ?? {}; + final loadContexts = await _channel.invokeMethod('loadContexts'); + + final infos = + Map.from(loadContexts is Map ? loadContexts : {}); final contextsMap = infos['contexts'] as Map?; if (contextsMap != null && contextsMap.isNotEmpty) { final contexts = Contexts.fromJson( diff --git a/flutter/lib/src/integrations/load_image_list_integration.dart b/flutter/lib/src/integrations/load_image_list_integration.dart index a3a1c9fc9d..ae08d93946 100644 --- a/flutter/lib/src/integrations/load_image_list_integration.dart +++ b/flutter/lib/src/integrations/load_image_list_integration.dart @@ -1,19 +1,19 @@ import 'dart:async'; +import 'package:flutter/services.dart'; import 'package:sentry/sentry.dart'; -import '../native/sentry_native_binding.dart'; import '../sentry_flutter_options.dart'; /// Loads the native debug image list for stack trace symbolication. class LoadImageListIntegration extends Integration { - final SentryNativeBinding _native; + final MethodChannel _channel; - LoadImageListIntegration(this._native); + LoadImageListIntegration(this._channel); @override void call(Hub hub, SentryFlutterOptions options) { options.addEventProcessor( - _LoadImageListIntegrationEventProcessor(_native), + _LoadImageListIntegrationEventProcessor(_channel, options), ); options.sdk.addIntegration('loadImageListIntegration'); @@ -32,7 +32,7 @@ extension _NeedsSymbolication on SentryEvent { return frames.any((frame) => 'native' == frame?.platform); } - Iterable? _getStacktraceFrames() { + List? _getStacktraceFrames() { if (exceptions?.isNotEmpty == true) { return exceptions?.first.stackTrace?.frames; } @@ -40,26 +40,56 @@ extension _NeedsSymbolication on SentryEvent { var stacktraces = threads?.map((e) => e.stacktrace); return stacktraces ?.where((element) => element != null) - .expand((element) => element!.frames); + .expand((element) => element!.frames) + .toList(); } return null; } } class _LoadImageListIntegrationEventProcessor implements EventProcessor { - _LoadImageListIntegrationEventProcessor(this._native); + _LoadImageListIntegrationEventProcessor(this._channel, this._options); - final SentryNativeBinding _native; + final MethodChannel _channel; + final SentryFlutterOptions _options; @override Future apply(SentryEvent event, Hint hint) async { if (event.needsSymbolication()) { - final images = await _native.loadDebugImages(); - if (images != null) { - return event.copyWith(debugMeta: DebugMeta(images: images)); + try { + // we call on every event because the loaded image list is cached + // and it could be changed on the Native side. + final loadImageList = await _channel.invokeMethod('loadImageList'); + final imageList = List>.from( + loadImageList is List ? loadImageList : [], + ); + return copyWithDebugImages(event, imageList); + } catch (exception, stackTrace) { + _options.logger( + SentryLevel.error, + 'loadImageList failed', + exception: exception, + stackTrace: stackTrace, + ); } } return event; } + + static SentryEvent copyWithDebugImages( + SentryEvent event, List imageList) { + if (imageList.isEmpty) { + return event; + } + + final newDebugImages = []; + for (final obj in imageList) { + final jsonMap = Map.from(obj as Map); + final image = DebugImage.fromJson(jsonMap); + newDebugImages.add(image); + } + + return event.copyWith(debugMeta: DebugMeta(images: newDebugImages)); + } } diff --git a/flutter/lib/src/integrations/native_app_start_integration.dart b/flutter/lib/src/integrations/native_app_start_integration.dart index af747dbf36..d3be7b4a0f 100644 --- a/flutter/lib/src/integrations/native_app_start_integration.dart +++ b/flutter/lib/src/integrations/native_app_start_integration.dart @@ -6,7 +6,7 @@ import 'package:meta/meta.dart'; import '../../sentry_flutter.dart'; import '../frame_callback_handler.dart'; -import '../native/sentry_native_binding.dart'; +import '../native/sentry_native.dart'; import '../event_processor/native_app_start_event_processor.dart'; /// Integration which handles communication with native frameworks in order to @@ -16,28 +16,12 @@ class NativeAppStartIntegration extends Integration { {Hub? hub}) : _hub = hub ?? HubAdapter(); - final SentryNativeBinding _native; + final SentryNative _native; final FrameCallbackHandler _frameCallbackHandler; final Hub _hub; - /// This timestamp marks the end of app startup. Either set automatically when - /// [SentryFlutterOptions.autoAppStart] is true, or by calling - /// [SentryFlutter.setAppStartEnd] - @internal - static DateTime? appStartEnd; - - /// Flag indicating if app start was already fetched. - static bool _didFetchAppStart = false; - - /// Flag indicating if app start measurement was added to the first transaction. - @internal - static bool didAddAppStartMeasurement = false; - /// Timeout duration to wait for the app start info to be fetched. - static const _timeoutDuration = Duration(seconds: 10); - - @visibleForTesting - static Duration get timeoutDuration => _timeoutDuration; + static const _timeoutDuration = Duration(seconds: 30); /// We filter out App starts more than 60s static const _maxAppStartMillis = 60000; @@ -71,14 +55,6 @@ class NativeAppStartIntegration extends Integration { static void clearAppStartInfo() { _appStartInfo = null; _appStartCompleter = Completer(); - didAddAppStartMeasurement = false; - } - - /// Reset state - @visibleForTesting - static void reset() { - appStartEnd = null; - _didFetchAppStart = false; } @override @@ -97,12 +73,11 @@ class NativeAppStartIntegration extends Integration { return; } - if (_didFetchAppStart) { + if (_native.didFetchAppStart) { return; } _frameCallbackHandler.addPostFrameCallback((timeStamp) async { - _didFetchAppStart = true; final nativeAppStart = await _native.fetchNativeAppStart(); if (nativeAppStart == null) { setAppStartInfo(null); @@ -119,12 +94,14 @@ class NativeAppStartIntegration extends Integration { nativeAppStart.appStartTime.toInt()); final pluginRegistrationDateTime = DateTime.fromMillisecondsSinceEpoch( nativeAppStart.pluginRegistrationTime); + DateTime? appStartEndDateTime; if (options.autoAppStart) { // We only assign the current time if it's not already set - this is useful in tests - appStartEnd ??= options.clock(); + _native.appStartEnd ??= options.clock(); + appStartEndDateTime = _native.appStartEnd; - final duration = appStartEnd?.difference(appStartDateTime); + final duration = appStartEndDateTime?.difference(appStartDateTime); // We filter out app start more than 60s. // This could be due to many different reasons. @@ -166,7 +143,7 @@ class NativeAppStartIntegration extends Integration { final appStartInfo = AppStartInfo( nativeAppStart.isColdStart ? AppStartType.cold : AppStartType.warm, start: appStartDateTime, - end: appStartEnd, + end: appStartEndDateTime, pluginRegistration: pluginRegistrationDateTime, sentrySetupStart: sentrySetupStartDateTime, nativeSpanTimes: nativeSpanTimes); @@ -197,7 +174,7 @@ class NativeAppStartIntegration extends Integration { } }); - options.addEventProcessor(NativeAppStartEventProcessor(hub: hub)); + options.addEventProcessor(NativeAppStartEventProcessor(_native, hub: hub)); options.sdk.addIntegration('nativeAppStartIntegration'); } diff --git a/flutter/lib/src/integrations/native_sdk_integration.dart b/flutter/lib/src/integrations/native_sdk_integration.dart index 7178883d73..35181afc1e 100644 --- a/flutter/lib/src/integrations/native_sdk_integration.dart +++ b/flutter/lib/src/integrations/native_sdk_integration.dart @@ -1,7 +1,7 @@ import 'dart:async'; import 'package:sentry/sentry.dart'; -import '../native/sentry_native_binding.dart'; +import '../native/sentry_native.dart'; import '../sentry_flutter_options.dart'; /// Enables Sentry's native SDKs (Android and iOS) with options. @@ -9,7 +9,7 @@ class NativeSdkIntegration implements Integration { NativeSdkIntegration(this._native); SentryFlutterOptions? _options; - final SentryNativeBinding _native; + final SentryNative _native; @override Future call(Hub hub, SentryFlutterOptions options) async { diff --git a/flutter/lib/src/native/cocoa/binding.dart b/flutter/lib/src/native/cocoa/binding.dart index 62afabb4cf..4af31cfc57 100644 --- a/flutter/lib/src/native/cocoa/binding.dart +++ b/flutter/lib/src/native/cocoa/binding.dart @@ -30112,6 +30112,12 @@ class SentryCocoa { ffi.Pointer Function(ffi.Pointer, ffi.Pointer, ffi.Pointer)>(); + late final _sel_captureReplay1 = _registerName1("captureReplay"); + late final _sel_getReplayId1 = _registerName1("getReplayId"); + late final _sel_addReplayIgnoreClasses_1 = + _registerName1("addReplayIgnoreClasses:"); + late final _sel_addReplayRedactClasses_1 = + _registerName1("addReplayRedactClasses:"); late final _class_SentryCurrentDateProvider1 = _getClass1("SentryCurrentDateProvider"); late final _sel_timezoneOffset1 = _registerName1("timezoneOffset"); @@ -70891,6 +70897,27 @@ class PrivateSentrySDKOnly extends NSObject { return SentryBreadcrumb._(_ret, _lib, retain: true, release: true); } + static void captureReplay(SentryCocoa _lib) { + _lib._objc_msgSend_1( + _lib._class_PrivateSentrySDKOnly1, _lib._sel_captureReplay1); + } + + static NSString getReplayId(SentryCocoa _lib) { + final _ret = _lib._objc_msgSend_20( + _lib._class_PrivateSentrySDKOnly1, _lib._sel_getReplayId1); + return NSString._(_ret, _lib, retain: true, release: true); + } + + static void addReplayIgnoreClasses_(SentryCocoa _lib, NSArray? classes) { + _lib._objc_msgSend_441(_lib._class_PrivateSentrySDKOnly1, + _lib._sel_addReplayIgnoreClasses_1, classes?._id ?? ffi.nullptr); + } + + static void addReplayRedactClasses_(SentryCocoa _lib, NSArray? classes) { + _lib._objc_msgSend_441(_lib._class_PrivateSentrySDKOnly1, + _lib._sel_addReplayRedactClasses_1, classes?._id ?? ffi.nullptr); + } + @override PrivateSentrySDKOnly init() { final _ret = _lib._objc_msgSend_2(_id, _lib._sel_init1); diff --git a/flutter/lib/src/native/cocoa/sentry_native_cocoa.dart b/flutter/lib/src/native/cocoa/sentry_native_cocoa.dart index 9bb5af98b6..d6912c107c 100644 --- a/flutter/lib/src/native/cocoa/sentry_native_cocoa.dart +++ b/flutter/lib/src/native/cocoa/sentry_native_cocoa.dart @@ -10,14 +10,14 @@ import 'binding.dart' as cocoa; class SentryNativeCocoa extends SentryNativeChannel { late final _lib = cocoa.SentryCocoa(DynamicLibrary.process()); - SentryNativeCocoa(super.options, super.channel); + SentryNativeCocoa(super.channel); @override - int? startProfiler(SentryId traceId) => tryCatchSync('startProfiler', () { - final cSentryId = cocoa.SentryId1.alloc(_lib) - ..initWithUUIDString_(cocoa.NSString(_lib, traceId.toString())); - final startTime = - cocoa.PrivateSentrySDKOnly.startProfilerForTrace_(_lib, cSentryId); - return startTime; - }); + int? startProfiler(SentryId traceId) { + final cSentryId = cocoa.SentryId1.alloc(_lib) + ..initWithUUIDString_(cocoa.NSString(_lib, traceId.toString())); + final startTime = + cocoa.PrivateSentrySDKOnly.startProfilerForTrace_(_lib, cSentryId); + return startTime; + } } diff --git a/flutter/lib/src/native/factory.dart b/flutter/lib/src/native/factory.dart index c81c526594..981e1d6ead 100644 --- a/flutter/lib/src/native/factory.dart +++ b/flutter/lib/src/native/factory.dart @@ -1,3 +1 @@ -export 'factory_real.dart' - if (dart.library.html) 'factory_web.dart' - if (dart.library.js_interop) 'factory_web.dart'; +export 'factory_real.dart' if (dart.library.html) 'factory_web.dart'; diff --git a/flutter/lib/src/native/factory_real.dart b/flutter/lib/src/native/factory_real.dart index 554279a8bc..d5ee4f5cca 100644 --- a/flutter/lib/src/native/factory_real.dart +++ b/flutter/lib/src/native/factory_real.dart @@ -6,14 +6,12 @@ import 'java/sentry_native_java.dart'; import 'sentry_native_binding.dart'; import 'sentry_native_channel.dart'; -SentryNativeBinding createBinding(SentryFlutterOptions options, - {MethodChannel channel = const MethodChannel('sentry_flutter')}) { - final platform = options.platformChecker.platform; - if (platform.isIOS || platform.isMacOS) { - return SentryNativeCocoa(options, channel); - } else if (platform.isAndroid) { - return SentryNativeJava(options, channel); +SentryNativeBinding createBinding(PlatformChecker pc, MethodChannel channel) { + if (pc.platform.isIOS || pc.platform.isMacOS) { + return SentryNativeCocoa(channel); + } else if (pc.platform.isAndroid) { + return SentryNativeJava(channel); } else { - return SentryNativeChannel(options, channel); + return SentryNativeChannel(channel); } } diff --git a/flutter/lib/src/native/factory_web.dart b/flutter/lib/src/native/factory_web.dart index a928271d16..c2cd57ada7 100644 --- a/flutter/lib/src/native/factory_web.dart +++ b/flutter/lib/src/native/factory_web.dart @@ -4,7 +4,6 @@ import '../../sentry_flutter.dart'; import 'sentry_native_binding.dart'; // This isn't actually called, see SentryFlutter.init() -SentryNativeBinding createBinding(SentryFlutterOptions options, - {MethodChannel channel = const MethodChannel('sentry_flutter')}) { +SentryNativeBinding createBinding(PlatformChecker _, MethodChannel __) { throw UnsupportedError("Native binding is not supported on this platform."); } diff --git a/flutter/lib/src/native/java/sentry_native_java.dart b/flutter/lib/src/native/java/sentry_native_java.dart index 1b0ef13cc5..20774e11fa 100644 --- a/flutter/lib/src/native/java/sentry_native_java.dart +++ b/flutter/lib/src/native/java/sentry_native_java.dart @@ -6,5 +6,5 @@ import '../sentry_native_channel.dart'; // generated JNI bindings. See https://github.com/getsentry/sentry-dart/issues/1444 @internal class SentryNativeJava extends SentryNativeChannel { - SentryNativeJava(super.options, super.channel); + SentryNativeJava(super.channel); } diff --git a/flutter/lib/src/native/native_app_start.dart b/flutter/lib/src/native/native_app_start.dart deleted file mode 100644 index 7b6d53422f..0000000000 --- a/flutter/lib/src/native/native_app_start.dart +++ /dev/null @@ -1,24 +0,0 @@ -import 'package:meta/meta.dart'; - -@internal -class NativeAppStart { - NativeAppStart( - {required this.appStartTime, - required this.pluginRegistrationTime, - required this.isColdStart, - required this.nativeSpanTimes}); - - double appStartTime; - int pluginRegistrationTime; - bool isColdStart; - Map nativeSpanTimes; - - factory NativeAppStart.fromJson(Map json) { - return NativeAppStart( - appStartTime: json['appStartTime'] as double, - pluginRegistrationTime: json['pluginRegistrationTime'] as int, - isColdStart: json['isColdStart'] as bool, - nativeSpanTimes: json['nativeSpanTimes'] as Map, - ); - } -} diff --git a/flutter/lib/src/native/native_frames.dart b/flutter/lib/src/native/native_frames.dart deleted file mode 100644 index 309abccbb7..0000000000 --- a/flutter/lib/src/native/native_frames.dart +++ /dev/null @@ -1,18 +0,0 @@ -import 'package:meta/meta.dart'; - -@internal -class NativeFrames { - NativeFrames(this.totalFrames, this.slowFrames, this.frozenFrames); - - int totalFrames; - int slowFrames; - int frozenFrames; - - factory NativeFrames.fromJson(Map json) { - return NativeFrames( - json['totalFrames'] as int, - json['slowFrames'] as int, - json['frozenFrames'] as int, - ); - } -} diff --git a/flutter/lib/src/native/native_scope_observer.dart b/flutter/lib/src/native/native_scope_observer.dart index 84dc31f646..fe26a2b094 100644 --- a/flutter/lib/src/native/native_scope_observer.dart +++ b/flutter/lib/src/native/native_scope_observer.dart @@ -2,55 +2,55 @@ import 'dart:async'; import 'package:sentry/sentry.dart'; -import 'sentry_native_binding.dart'; +import 'sentry_native.dart'; class NativeScopeObserver implements ScopeObserver { - NativeScopeObserver(this._native); + NativeScopeObserver(this._sentryNative); - final SentryNativeBinding _native; + final SentryNative _sentryNative; @override Future setContexts(String key, value) async { - await _native.setContexts(key, value); + await _sentryNative.setContexts(key, value); } @override Future removeContexts(String key) async { - await _native.removeContexts(key); + await _sentryNative.removeContexts(key); } @override Future setUser(SentryUser? user) async { - await _native.setUser(user); + await _sentryNative.setUser(user); } @override Future addBreadcrumb(Breadcrumb breadcrumb) async { - await _native.addBreadcrumb(breadcrumb); + await _sentryNative.addBreadcrumb(breadcrumb); } @override Future clearBreadcrumbs() async { - await _native.clearBreadcrumbs(); + await _sentryNative.clearBreadcrumbs(); } @override Future setExtra(String key, dynamic value) async { - await _native.setExtra(key, value); + await _sentryNative.setExtra(key, value); } @override Future removeExtra(String key) async { - await _native.removeExtra(key); + await _sentryNative.removeExtra(key); } @override Future setTag(String key, String value) async { - await _native.setTag(key, value); + await _sentryNative.setTag(key, value); } @override Future removeTag(String key) async { - await _native.removeTag(key); + await _sentryNative.removeTag(key); } } diff --git a/flutter/lib/src/native/sentry_native.dart b/flutter/lib/src/native/sentry_native.dart new file mode 100644 index 0000000000..d8d9c5a964 --- /dev/null +++ b/flutter/lib/src/native/sentry_native.dart @@ -0,0 +1,172 @@ +import 'dart:async'; + +import 'package:meta/meta.dart'; + +import '../../sentry_flutter.dart'; +import 'sentry_native_binding.dart'; + +/// [SentryNative] holds state that it fetches from to the native SDKs. +/// It forwards to platform-specific implementations of [SentryNativeBinding]. +/// Any errors are logged and ignored. +@internal +class SentryNative { + final SentryOptions _options; + final SentryNativeBinding _binding; + + SentryNative(this._options, this._binding); + + // AppStart + + /// This timestamp marks the end of app startup. Either set automatically when + /// [SentryFlutterOptions.autoAppStart] is true, or by calling + /// [SentryFlutter.setAppStartEnd] + DateTime? appStartEnd; + + bool _didFetchAppStart = false; + + /// Flag indicating if app start was already fetched. + bool get didFetchAppStart => _didFetchAppStart; + + /// Flag indicating if app start measurement was added to the first transaction. + bool didAddAppStartMeasurement = false; + + Future init(SentryFlutterOptions options) async => + _invoke("init", () => _binding.init(options)); + + Future close() async => _invoke("close", _binding.close); + + /// Fetch [NativeAppStart] from native channels. Can only be called once. + Future fetchNativeAppStart() async { + _didFetchAppStart = true; + return _invoke("fetchNativeAppStart", _binding.fetchNativeAppStart); + } + + // NativeFrames + + Future beginNativeFramesCollection() => + _invoke("beginNativeFrames", _binding.beginNativeFrames); + + Future endNativeFramesCollection(SentryId traceId) => + _invoke("endNativeFrames", () => _binding.endNativeFrames(traceId)); + + // Scope + + Future setContexts(String key, dynamic value) => + _invoke("setContexts", () => _binding.setContexts(key, value)); + + Future removeContexts(String key) => + _invoke("removeContexts", () => _binding.removeContexts(key)); + + Future setUser(SentryUser? sentryUser) => + _invoke("setUser", () => _binding.setUser(sentryUser)); + + Future addBreadcrumb(Breadcrumb breadcrumb) => + _invoke("addBreadcrumb", () => _binding.addBreadcrumb(breadcrumb)); + + Future clearBreadcrumbs() => + _invoke("clearBreadcrumbs", _binding.clearBreadcrumbs); + + Future setExtra(String key, dynamic value) => + _invoke("setExtra", () => _binding.setExtra(key, value)); + + Future removeExtra(String key) => + _invoke("removeExtra", () => _binding.removeExtra(key)); + + Future setTag(String key, String value) => + _invoke("setTag", () => _binding.setTag(key, value)); + + Future removeTag(String key) => + _invoke("removeTag", () => _binding.removeTag(key)); + + int? startProfiler(SentryId traceId) => + _invokeSync("startProfiler", () => _binding.startProfiler(traceId)); + + Future discardProfiler(SentryId traceId) => + _invoke("discardProfiler", () => _binding.discardProfiler(traceId)); + + Future?> collectProfile( + SentryId traceId, int startTimeNs, int endTimeNs) => + _invoke("collectProfile", + () => _binding.collectProfile(traceId, startTimeNs, endTimeNs)); + + /// Reset state + void reset() { + appStartEnd = null; + _didFetchAppStart = false; + } + + // Helpers + Future _invoke( + String nativeMethodName, Future Function() fn) async { + try { + return await fn(); + } catch (error, stackTrace) { + _logError(nativeMethodName, error, stackTrace); + // ignore: invalid_use_of_internal_member + if (_options.automatedTestMode) { + rethrow; + } + return null; + } + } + + T? _invokeSync(String nativeMethodName, T? Function() fn) { + try { + return fn(); + } catch (error, stackTrace) { + _logError(nativeMethodName, error, stackTrace); + // ignore: invalid_use_of_internal_member + if (_options.automatedTestMode) { + rethrow; + } + return null; + } + } + + void _logError(String nativeMethodName, Object error, StackTrace stackTrace) { + _options.logger( + SentryLevel.error, + 'Native call `$nativeMethodName` failed', + exception: error, + stackTrace: stackTrace, + ); + } +} + +class NativeAppStart { + NativeAppStart( + {required this.appStartTime, + required this.pluginRegistrationTime, + required this.isColdStart, + required this.nativeSpanTimes}); + + double appStartTime; + int pluginRegistrationTime; + bool isColdStart; + Map nativeSpanTimes; + + factory NativeAppStart.fromJson(Map json) { + return NativeAppStart( + appStartTime: json['appStartTime'] as double, + pluginRegistrationTime: json['pluginRegistrationTime'] as int, + isColdStart: json['isColdStart'] as bool, + nativeSpanTimes: json['nativeSpanTimes'] as Map, + ); + } +} + +class NativeFrames { + NativeFrames(this.totalFrames, this.slowFrames, this.frozenFrames); + + int totalFrames; + int slowFrames; + int frozenFrames; + + factory NativeFrames.fromJson(Map json) { + return NativeFrames( + json['totalFrames'] as int, + json['slowFrames'] as int, + json['frozenFrames'] as int, + ); + } +} diff --git a/flutter/lib/src/native/sentry_native_binding.dart b/flutter/lib/src/native/sentry_native_binding.dart index 002790fc32..950e7f9994 100644 --- a/flutter/lib/src/native/sentry_native_binding.dart +++ b/flutter/lib/src/native/sentry_native_binding.dart @@ -1,24 +1,20 @@ import 'dart:async'; -import 'dart:typed_data'; import 'package:meta/meta.dart'; import '../../sentry_flutter.dart'; -import 'native_app_start.dart'; -import 'native_frames.dart'; +import 'sentry_native.dart'; /// Provide typed methods to access native layer. @internal abstract class SentryNativeBinding { + // TODO Move other native calls here. Future init(SentryFlutterOptions options); Future close(); Future fetchNativeAppStart(); - Future captureEnvelope( - Uint8List envelopeData, bool containsUnhandledException); - Future beginNativeFrames(); Future endNativeFrames(SentryId id); @@ -29,8 +25,6 @@ abstract class SentryNativeBinding { Future clearBreadcrumbs(); - Future?> loadContexts(); - Future setContexts(String key, dynamic value); Future removeContexts(String key); @@ -47,14 +41,6 @@ abstract class SentryNativeBinding { Future discardProfiler(SentryId traceId); - Future displayRefreshRate(); - Future?> collectProfile( SentryId traceId, int startTimeNs, int endTimeNs); - - Future?> loadDebugImages(); - - Future pauseAppHangTracking(); - - Future resumeAppHangTracking(); } diff --git a/flutter/lib/src/native/sentry_native_channel.dart b/flutter/lib/src/native/sentry_native_channel.dart index 0a3b97820d..61b361de30 100644 --- a/flutter/lib/src/native/sentry_native_channel.dart +++ b/flutter/lib/src/native/sentry_native_channel.dart @@ -1,73 +1,61 @@ import 'dart:async'; -// backcompatibility for Flutter < 3.3 -// ignore: unnecessary_import -import 'dart:typed_data'; import 'package:flutter/services.dart'; import 'package:meta/meta.dart'; import '../../sentry_flutter.dart'; -import 'native_app_start.dart'; -import 'native_frames.dart'; +import 'sentry_native.dart'; import 'method_channel_helper.dart'; import 'sentry_native_binding.dart'; -import 'sentry_native_invoker.dart'; -import 'sentry_safe_method_channel.dart'; /// Provide typed methods to access native layer via MethodChannel. @internal -class SentryNativeChannel - with SentryNativeSafeInvoker - implements SentryNativeBinding { - @override - final SentryFlutterOptions options; - - final SentrySafeMethodChannel _channel; - - SentryNativeChannel(this.options, MethodChannel channel) - : _channel = SentrySafeMethodChannel(channel, options); - - @override - Future init(SentryFlutterOptions options) async { - assert(this.options == options); - return _channel.invokeMethod('initNativeSdk', { - 'dsn': options.dsn, - 'debug': options.debug, - 'environment': options.environment, - 'release': options.release, - 'enableAutoSessionTracking': options.enableAutoSessionTracking, - 'enableNativeCrashHandling': options.enableNativeCrashHandling, - 'attachStacktrace': options.attachStacktrace, - 'attachThreads': options.attachThreads, - 'autoSessionTrackingIntervalMillis': - options.autoSessionTrackingInterval.inMilliseconds, - 'dist': options.dist, - 'integrations': options.sdk.integrations, - 'packages': - options.sdk.packages.map((e) => e.toJson()).toList(growable: false), - 'diagnosticLevel': options.diagnosticLevel.name, - 'maxBreadcrumbs': options.maxBreadcrumbs, - 'anrEnabled': options.anrEnabled, - 'anrTimeoutIntervalMillis': options.anrTimeoutInterval.inMilliseconds, - 'enableAutoNativeBreadcrumbs': options.enableAutoNativeBreadcrumbs, - 'maxCacheItems': options.maxCacheItems, - 'sendDefaultPii': options.sendDefaultPii, - 'enableWatchdogTerminationTracking': - options.enableWatchdogTerminationTracking, - 'enableNdkScopeSync': options.enableNdkScopeSync, - 'enableAutoPerformanceTracing': options.enableAutoPerformanceTracing, - 'sendClientReports': options.sendClientReports, - 'proguardUuid': options.proguardUuid, - 'maxAttachmentSize': options.maxAttachmentSize, - 'recordHttpBreadcrumbs': options.recordHttpBreadcrumbs, - 'captureFailedRequests': options.captureFailedRequests, - 'enableAppHangTracking': options.enableAppHangTracking, - 'connectionTimeoutMillis': options.connectionTimeout.inMilliseconds, - 'readTimeoutMillis': options.readTimeout.inMilliseconds, - 'appHangTimeoutIntervalMillis': - options.appHangTimeoutInterval.inMilliseconds, - }); - } +class SentryNativeChannel implements SentryNativeBinding { + SentryNativeChannel(this._channel); + + final MethodChannel _channel; + + // TODO Move other native calls here. + + @override + Future init(SentryFlutterOptions options) async => + _channel.invokeMethod('initNativeSdk', { + 'dsn': options.dsn, + 'debug': options.debug, + 'environment': options.environment, + 'release': options.release, + 'enableAutoSessionTracking': options.enableAutoSessionTracking, + 'enableNativeCrashHandling': options.enableNativeCrashHandling, + 'attachStacktrace': options.attachStacktrace, + 'attachThreads': options.attachThreads, + 'autoSessionTrackingIntervalMillis': + options.autoSessionTrackingInterval.inMilliseconds, + 'dist': options.dist, + 'integrations': options.sdk.integrations, + 'packages': + options.sdk.packages.map((e) => e.toJson()).toList(growable: false), + 'diagnosticLevel': options.diagnosticLevel.name, + 'maxBreadcrumbs': options.maxBreadcrumbs, + 'anrEnabled': options.anrEnabled, + 'anrTimeoutIntervalMillis': options.anrTimeoutInterval.inMilliseconds, + 'enableAutoNativeBreadcrumbs': options.enableAutoNativeBreadcrumbs, + 'maxCacheItems': options.maxCacheItems, + 'sendDefaultPii': options.sendDefaultPii, + 'enableWatchdogTerminationTracking': + options.enableWatchdogTerminationTracking, + 'enableNdkScopeSync': options.enableNdkScopeSync, + 'enableAutoPerformanceTracing': options.enableAutoPerformanceTracing, + 'sendClientReports': options.sendClientReports, + 'proguardUuid': options.proguardUuid, + 'maxAttachmentSize': options.maxAttachmentSize, + 'recordHttpBreadcrumbs': options.recordHttpBreadcrumbs, + 'captureFailedRequests': options.captureFailedRequests, + 'enableAppHangTracking': options.enableAppHangTracking, + 'connectionTimeoutMillis': options.connectionTimeout.inMilliseconds, + 'readTimeoutMillis': options.readTimeout.inMilliseconds, + 'appHangTimeoutIntervalMillis': + options.appHangTimeoutInterval.inMilliseconds, + }); @override Future close() async => _channel.invokeMethod('closeNativeSdk'); @@ -79,17 +67,6 @@ class SentryNativeChannel return (json != null) ? NativeAppStart.fromJson(json) : null; } - @override - Future captureEnvelope( - Uint8List envelopeData, bool containsUnhandledException) { - return _channel.invokeMethod( - 'captureEnvelope', [envelopeData, containsUnhandledException]); - } - - @override - Future?> loadContexts() => - _channel.invokeMapMethod('loadContexts'); - @override Future beginNativeFrames() => _channel.invokeMethod('beginNativeFrames'); @@ -170,27 +147,4 @@ class SentryNativeChannel 'startTime': startTimeNs, 'endTime': endTimeNs, }); - - @override - Future?> loadDebugImages() => - tryCatchAsync('loadDebugImages', () async { - final images = await _channel - .invokeListMethod>('loadImageList'); - return images - ?.map((e) => e.cast()) - .map(DebugImage.fromJson) - .toList(); - }); - - @override - Future displayRefreshRate() => - _channel.invokeMethod('displayRefreshRate'); - - @override - Future pauseAppHangTracking() => - _channel.invokeMethod('pauseAppHangTracking'); - - @override - Future resumeAppHangTracking() => - _channel.invokeMethod('resumeAppHangTracking'); } diff --git a/flutter/lib/src/native/sentry_native_invoker.dart b/flutter/lib/src/native/sentry_native_invoker.dart deleted file mode 100644 index dbda8c4513..0000000000 --- a/flutter/lib/src/native/sentry_native_invoker.dart +++ /dev/null @@ -1,47 +0,0 @@ -import 'dart:async'; - -import 'package:meta/meta.dart'; - -import '../../sentry_flutter.dart'; - -/// Helper to safely invoke native methods. Any errors are logged and ignored. -@internal -mixin SentryNativeSafeInvoker { - SentryFlutterOptions get options; - - Future tryCatchAsync( - String nativeMethodName, Future Function() fn) async { - try { - return await fn(); - } catch (error, stackTrace) { - _logError(nativeMethodName, error, stackTrace); - // ignore: invalid_use_of_internal_member - if (options.automatedTestMode) { - rethrow; - } - return null; - } - } - - T? tryCatchSync(String nativeMethodName, T? Function() fn) { - try { - return fn(); - } catch (error, stackTrace) { - _logError(nativeMethodName, error, stackTrace); - // ignore: invalid_use_of_internal_member - if (options.automatedTestMode) { - rethrow; - } - return null; - } - } - - void _logError(String nativeMethodName, Object error, StackTrace stackTrace) { - options.logger( - SentryLevel.error, - 'Native call `$nativeMethodName` failed', - exception: error, - stackTrace: stackTrace, - ); - } -} diff --git a/flutter/lib/src/native/sentry_safe_method_channel.dart b/flutter/lib/src/native/sentry_safe_method_channel.dart deleted file mode 100644 index aa44c08f44..0000000000 --- a/flutter/lib/src/native/sentry_safe_method_channel.dart +++ /dev/null @@ -1,35 +0,0 @@ -import 'dart:async'; - -import 'package:flutter/services.dart'; -import 'package:meta/meta.dart'; - -import '../../sentry_flutter.dart'; -import 'sentry_native_invoker.dart'; - -class SentrySafeMethodChannel with SentryNativeSafeInvoker { - @override - final SentryFlutterOptions options; - - final MethodChannel _channel; - - SentrySafeMethodChannel(this._channel, this.options); - - @optionalTypeArgs - Future invokeMethod(String method, [dynamic args]) => - tryCatchAsync(method, () => _channel.invokeMethod(method, args)); - - Future?> invokeListMethod(String method, [dynamic args]) => - tryCatchAsync(method, () async { - // Note, we're not using channel.invokeListMethod because it would fail in tests due to the generated mock not doing a cast. - final result = await _channel.invokeMethod>(method, args); - return result?.cast(); - }); - - Future?> invokeMapMethod(String method, [dynamic args]) => - tryCatchAsync(method, () async { - // Note, we're not using channel.invokeMapMethod because it would fail in tests due to the generated mock not doing a cast. - final result = - await _channel.invokeMethod>(method, args); - return result?.cast(); - }); -} diff --git a/flutter/lib/src/navigation/sentry_navigator_observer.dart b/flutter/lib/src/navigation/sentry_navigator_observer.dart index 1a6b156377..fbfc12b6ee 100644 --- a/flutter/lib/src/navigation/sentry_navigator_observer.dart +++ b/flutter/lib/src/navigation/sentry_navigator_observer.dart @@ -6,12 +6,11 @@ import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; import 'package:meta/meta.dart'; import '../integrations/integrations.dart'; -import '../native/native_frames.dart'; -import '../native/sentry_native_binding.dart'; import 'time_to_display_tracker.dart'; import '../../sentry_flutter.dart'; import '../event_processor/flutter_enricher_event_processor.dart'; +import '../native/sentry_native.dart'; // ignore: implementation_imports import 'package:sentry/src/sentry_tracer.dart'; @@ -112,7 +111,7 @@ class SentryNavigatorObserver extends RouteObserver> { final bool _setRouteNameAsTransaction; final RouteNameExtractor? _routeNameExtractor; final AdditionalInfoExtractor? _additionalInfoProvider; - final SentryNativeBinding? _native; + final SentryNative? _native; static TimeToDisplayTracker? _timeToDisplayTracker; @internal @@ -248,8 +247,8 @@ class SentryNavigatorObserver extends RouteObserver> { trimEnd: true, onFinish: (transaction) async { _transaction = null; - final nativeFrames = - await _native?.endNativeFrames(transaction.context.traceId); + final nativeFrames = await _native + ?.endNativeFramesCollection(transaction.context.traceId); if (nativeFrames != null) { final measurements = nativeFrames.toMeasurements(); for (final item in measurements.entries) { @@ -278,7 +277,7 @@ class SentryNavigatorObserver extends RouteObserver> { scope.span ??= _transaction; }); - await _native?.beginNativeFrames(); + await _native?.beginNativeFramesCollection(); } Future _finishTimeToDisplayTracking({bool clearAfter = false}) async { diff --git a/flutter/lib/src/profiling.dart b/flutter/lib/src/profiling.dart index 3fb22a9b75..a4332d77e7 100644 --- a/flutter/lib/src/profiling.dart +++ b/flutter/lib/src/profiling.dart @@ -8,16 +8,16 @@ import 'package:sentry/src/sentry_envelope_item_header.dart'; import 'package:sentry/src/sentry_item_type.dart'; import '../sentry_flutter.dart'; -import 'native/sentry_native_binding.dart'; +import 'native/sentry_native.dart'; // ignore: invalid_use_of_internal_member class SentryNativeProfilerFactory implements SentryProfilerFactory { - final SentryNativeBinding _native; + final SentryNative _native; final ClockProvider _clock; SentryNativeProfilerFactory(this._native, this._clock); - static void attachTo(Hub hub, SentryNativeBinding native) { + static void attachTo(Hub hub, SentryNative native) { // ignore: invalid_use_of_internal_member final options = hub.options; @@ -53,7 +53,7 @@ class SentryNativeProfilerFactory implements SentryProfilerFactory { // ignore: invalid_use_of_internal_member class SentryNativeProfiler implements SentryProfiler { - final SentryNativeBinding _native; + final SentryNative _native; final int _starTimeNs; final SentryId _traceId; bool _finished = false; diff --git a/flutter/lib/src/renderer/renderer.dart b/flutter/lib/src/renderer/renderer.dart index dc9d81276b..3e41eced70 100644 --- a/flutter/lib/src/renderer/renderer.dart +++ b/flutter/lib/src/renderer/renderer.dart @@ -2,7 +2,6 @@ import 'package:meta/meta.dart'; import 'unknown_renderer.dart' if (dart.library.html) 'html_renderer.dart' - if (dart.library.js_interop) 'web_renderer.dart' if (dart.library.io) 'io_renderer.dart' as implementation; @internal diff --git a/flutter/lib/src/renderer/web_renderer.dart b/flutter/lib/src/renderer/web_renderer.dart deleted file mode 100644 index 6baa3ca8b4..0000000000 --- a/flutter/lib/src/renderer/web_renderer.dart +++ /dev/null @@ -1,18 +0,0 @@ -import 'dart:js_interop'; - -import 'renderer.dart'; - -FlutterRenderer? getRenderer() { - return isCanvasKitRenderer ? FlutterRenderer.canvasKit : FlutterRenderer.html; -} - -bool get isCanvasKitRenderer { - return _windowFlutterCanvasKit != null; -} - -// These values are set by the engine. They are used to determine if the -// application is using canvaskit or skwasm. -// -// See https://github.com/flutter/flutter/blob/414d9238720a3cde85475f49ce0ba313f95046f7/packages/flutter/lib/src/foundation/_capabilities_web.dart#L10 -@JS('window.flutterCanvasKit') -external JSAny? get _windowFlutterCanvasKit; diff --git a/flutter/lib/src/sentry_flutter.dart b/flutter/lib/src/sentry_flutter.dart index 4b0deb8541..e0d4415de5 100644 --- a/flutter/lib/src/sentry_flutter.dart +++ b/flutter/lib/src/sentry_flutter.dart @@ -1,9 +1,9 @@ import 'dart:async'; import 'dart:ui'; +import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; import 'package:meta/meta.dart'; -import 'span_frame_metrics_collector.dart'; import '../sentry_flutter.dart'; import 'event_processor/android_platform_exception_event_processor.dart'; import 'event_processor/flutter_exception_event_processor.dart'; @@ -14,9 +14,9 @@ import 'integrations/connectivity/connectivity_integration.dart'; import 'integrations/screenshot_integration.dart'; import 'native/factory.dart'; import 'native/native_scope_observer.dart'; -import 'native/sentry_native_binding.dart'; import 'profiling.dart'; import 'renderer/renderer.dart'; +import 'native/sentry_native.dart'; import 'integrations/integrations.dart'; import 'event_processor/flutter_enricher_event_processor.dart'; @@ -32,25 +32,17 @@ typedef FlutterOptionsConfiguration = FutureOr Function( /// Sentry Flutter SDK main entry point mixin SentryFlutter { + static const _channel = MethodChannel('sentry_flutter'); + /// Represents the time when the Sentry init set up has started. @internal // ignore: invalid_use_of_internal_member static DateTime? sentrySetupStartTime; - /// Initializes the Sentry Flutter SDK. - /// - /// Unlike [Sentry.init], this method creates the Flutter default integrations. - /// - /// [optionsConfiguration] is a callback that allows you to configure the Sentry - /// options. The [SentryFlutterOptions] should not be adjusted anywhere else than - /// during [init], so that's why they're not directly exposed outside of this method. - /// - /// You can use the static members of [Sentry] from within other packages without the - /// need of initializing it in the package; as long as they have been already properly - /// initialized in the application package. static Future init( FlutterOptionsConfiguration optionsConfiguration, { AppRunner? appRunner, + @internal MethodChannel channel = _channel, @internal PlatformChecker? platformChecker, @internal RendererWrapper? rendererWrapper, }) async { @@ -67,7 +59,8 @@ mixin SentryFlutter { } if (flutterOptions.platformChecker.hasNativeIntegration) { - _native = createBinding(flutterOptions); + final binding = createBinding(flutterOptions.platformChecker, channel); + _native = SentryNative(flutterOptions, binding); } final platformDispatcher = PlatformDispatcher.instance; @@ -87,6 +80,7 @@ mixin SentryFlutter { // first step is to install the native integration and set default values, // so we are able to capture future errors. final defaultIntegrations = _createDefaultIntegrations( + channel, flutterOptions, isOnErrorSupported, ); @@ -94,13 +88,10 @@ mixin SentryFlutter { flutterOptions.addIntegration(defaultIntegration); } - await _initDefaultValues(flutterOptions); + await _initDefaultValues(flutterOptions, channel); await Sentry.init( - (options) { - assert(options == flutterOptions); - return optionsConfiguration(options as SentryFlutterOptions); - }, + (options) => optionsConfiguration(options as SentryFlutterOptions), appRunner: appRunner, // ignore: invalid_use_of_internal_member options: flutterOptions, @@ -116,12 +107,15 @@ mixin SentryFlutter { } } - static Future _initDefaultValues(SentryFlutterOptions options) async { + static Future _initDefaultValues( + SentryFlutterOptions options, + MethodChannel channel, + ) async { options.addEventProcessor(FlutterExceptionEventProcessor()); // Not all platforms have a native integration. if (_native != null) { - options.transport = FileSystemTransport(_native!, options); + options.transport = FileSystemTransport(channel, options); options.addScopeObserver(NativeScopeObserver(_native!)); } @@ -136,19 +130,19 @@ mixin SentryFlutter { options.addEventProcessor(PlatformExceptionEventProcessor()); - options.addPerformanceCollector(SpanFrameMetricsCollector(options)); - _setSdk(options); } /// Install default integrations /// https://medium.com/flutter-community/error-handling-in-flutter-98fce88a34f0 static List _createDefaultIntegrations( + MethodChannel channel, SentryFlutterOptions options, bool isOnErrorSupported, ) { final integrations = []; final platformChecker = options.platformChecker; + final platform = platformChecker.platform; // Will call WidgetsFlutterBinding.ensureInitialized() before all other integrations. integrations.add(WidgetsFlutterBindingIntegration()); @@ -167,13 +161,22 @@ mixin SentryFlutter { // The ordering here matters, as we'd like to first start the native integration. // That allow us to send events to the network and then the Flutter integrations. // Flutter Web doesn't need that, only Android and iOS. - final native = _native; - if (native != null) { - integrations.add(NativeSdkIntegration(native)); - integrations.add(LoadContextsIntegration(native)); - integrations.add(LoadImageListIntegration(native)); + if (_native != null) { + integrations.add(NativeSdkIntegration(_native!)); + } + + // Will enrich events with device context, native packages and integrations + if (platformChecker.hasNativeIntegration && + !platformChecker.isWeb && + (platform.isIOS || platform.isMacOS || platform.isAndroid)) { + integrations.add(LoadContextsIntegration(channel)); } + if (platformChecker.hasNativeIntegration && + !platformChecker.isWeb && + (platform.isAndroid || platform.isIOS || platform.isMacOS)) { + integrations.add(LoadImageListIntegration(channel)); + } final renderer = options.rendererWrapper.getRenderer(); if (!platformChecker.isWeb || renderer == FlutterRenderer.canvasKit) { integrations.add(ScreenshotIntegration()); @@ -193,9 +196,9 @@ mixin SentryFlutter { // in errors. integrations.add(LoadReleaseIntegration()); - if (native != null) { + if (_native != null) { integrations.add(NativeAppStartIntegration( - native, + _native!, DefaultFrameCallbackHandler(), )); } @@ -215,7 +218,7 @@ mixin SentryFlutter { /// Manually set when your app finished startup. Make sure to set /// [SentryFlutterOptions.autoAppStart] to false on init. static void setAppStartEnd(DateTime appStartEnd) { - NativeAppStartIntegration.appStartEnd = appStartEnd; + _native?.appStartEnd = appStartEnd; } static void _setSdk(SentryFlutterOptions options) { @@ -236,39 +239,10 @@ mixin SentryFlutter { return SentryNavigatorObserver.timeToDisplayTracker?.reportFullyDisplayed(); } - /// Pauses the app hang tracking. - /// Only for iOS and macOS. - static Future pauseAppHangTracking() { - if (_native == null) { - // ignore: invalid_use_of_internal_member - Sentry.currentHub.options.logger( - SentryLevel.debug, - 'Native integration is not available. Make sure SentryFlutter is initialized before accessing the pauseAppHangTracking API.', - ); - return Future.value(); - } - return _native!.pauseAppHangTracking(); - } - - /// Resumes the app hang tracking. - /// Only for iOS and macOS - static Future resumeAppHangTracking() { - if (_native == null) { - // ignore: invalid_use_of_internal_member - Sentry.currentHub.options.logger( - SentryLevel.debug, - 'Native integration is not available. Make sure SentryFlutter is initialized before accessing the resumeAppHangTracking API.', - ); - return Future.value(); - } - return _native!.resumeAppHangTracking(); - } - @internal - static SentryNativeBinding? get native => _native; + static SentryNative? get native => _native; @internal - static set native(SentryNativeBinding? value) => _native = value; - - static SentryNativeBinding? _native; + static set native(SentryNative? value) => _native = value; + static SentryNative? _native; } diff --git a/flutter/lib/src/sentry_flutter_options.dart b/flutter/lib/src/sentry_flutter_options.dart index 913070e9ca..ae83de611e 100644 --- a/flutter/lib/src/sentry_flutter_options.dart +++ b/flutter/lib/src/sentry_flutter_options.dart @@ -232,20 +232,6 @@ class SentryFlutterOptions extends SentryOptions { /// Read timeout. This will only be synced to the Android native SDK. Duration readTimeout = Duration(seconds: 5); - /// Enable or disable Frames Tracking, which is used to report frame information - /// for every [ISentrySpan]. - /// - /// When enabled, the following metrics are reported for each span: - /// - Slow frames: The number of frames that exceeded a specified threshold for frame duration. - /// - Frozen frames: The number of frames that took an unusually long time to render, indicating a potential freeze or hang. - /// - Total frames count: The total number of frames rendered during the span. - /// - Frames delay: The delayed frame render duration of all frames. - - /// Read more about frames tracking here: https://develop.sentry.dev/sdk/performance/frames-delay/ - /// - /// Defaults to `true` - bool enableFramesTracking = true; - /// By using this, you are disabling native [Breadcrumb] tracking and instead /// you are just tracking [Breadcrumb]s which result from events available /// in the current Flutter environment. diff --git a/flutter/lib/src/span_frame_metrics_collector.dart b/flutter/lib/src/span_frame_metrics_collector.dart deleted file mode 100644 index ecf0ca961c..0000000000 --- a/flutter/lib/src/span_frame_metrics_collector.dart +++ /dev/null @@ -1,256 +0,0 @@ -import 'dart:collection'; -import 'dart:math'; - -import 'package:flutter/cupertino.dart'; -import 'package:meta/meta.dart'; - -import '../sentry_flutter.dart'; - -import 'frame_callback_handler.dart'; -import 'native/sentry_native_binding.dart'; - -@internal -class SpanFrameMetricsCollector implements PerformanceContinuousCollector { - static const _frozenFrameThresholdMs = 700; - static const totalFramesKey = 'frames.total'; - static const framesDelayKey = 'frames.delay'; - static const slowFramesKey = 'frames.slow'; - static const frozenFramesKey = 'frames.frozen'; - - final SentryFlutterOptions options; - final FrameCallbackHandler _frameCallbackHandler; - final SentryNativeBinding? _native; - - final bool _isTestMode; - - /// Stores frame timestamps and their durations in milliseconds. - /// Keys are frame timestamps, values are frame durations. - /// The timestamps mark the end of the frame. - final frames = SplayTreeMap(); - - /// Stores the spans that are actively being tracked. - /// After the frames are calculated and stored in the span the span is removed from this list. - final activeSpans = SplayTreeSet( - (a, b) => a.startTimestamp.compareTo(b.startTimestamp)); - - bool get isTrackingPaused => _isTrackingPaused; - bool _isTrackingPaused = true; - - bool get isTrackingRegistered => _isTrackingRegistered; - bool _isTrackingRegistered = false; - - int displayRefreshRate = 60; - - final _stopwatch = Stopwatch(); - - SpanFrameMetricsCollector(this.options, - {FrameCallbackHandler? frameCallbackHandler, - SentryNativeBinding? native, - @internal bool isTestMode = false}) - : _frameCallbackHandler = - frameCallbackHandler ?? DefaultFrameCallbackHandler(), - _native = native ?? SentryFlutter.native, - _isTestMode = isTestMode; - - @override - Future onSpanStarted(ISentrySpan span) async { - if (span is NoOpSentrySpan || !options.enableFramesTracking) { - return; - } - - final fetchedDisplayRefreshRate = await _native?.displayRefreshRate(); - if (fetchedDisplayRefreshRate != null) { - options.logger(SentryLevel.debug, - 'Retrieved display refresh rate at $fetchedDisplayRefreshRate'); - displayRefreshRate = fetchedDisplayRefreshRate; - } else { - options.logger(SentryLevel.debug, - 'Could not fetch display refresh rate, keeping at 60hz by default'); - } - - activeSpans.add(span); - startFrameTracking(); - } - - @override - Future onSpanFinished(ISentrySpan span, DateTime endTimestamp) async { - if (span is NoOpSentrySpan || !activeSpans.contains(span)) return; - - final frameMetrics = - calculateFrameMetrics(span, endTimestamp, displayRefreshRate); - _applyFrameMetricsToSpan(span, frameMetrics); - - activeSpans.remove(span); - if (activeSpans.isEmpty) { - clear(); - } else { - frames.removeWhere((frameTimestamp, _) => - frameTimestamp.isBefore(activeSpans.first.startTimestamp)); - } - } - - /// Calls [WidgetsBinding.instance.addPersistentFrameCallback] which cannot be unregistered - /// and exists for the duration of the application's lifetime. - /// - /// Stopping the frame tracking means setting [isTrackingPaused] is `true` - /// to prevent actions being done when the frame callback is triggered. - void startFrameTracking() { - _isTrackingPaused = false; - - if (!_isTrackingRegistered) { - _frameCallbackHandler.addPersistentFrameCallback(measureFrameDuration); - _isTrackingRegistered = true; - } - } - - /// Records the duration of a single frame and stores it in [frames]. - /// - /// This method is called for each frame when frame tracking is active. - Future measureFrameDuration(Duration duration) async { - // Using the stopwatch to measure the frame duration is flaky in ci - if (_isTestMode) { - // ignore: invalid_use_of_internal_member - frames[options.clock().add(duration)] = duration.inMilliseconds; - return; - } - - if (_isTrackingPaused) return; - - if (!_stopwatch.isRunning) { - _stopwatch.start(); - } - - await _frameCallbackHandler.endOfFrame; - - final frameDuration = _stopwatch.elapsedMilliseconds; - // ignore: invalid_use_of_internal_member - frames[options.clock()] = frameDuration; - - _stopwatch.reset(); - - if (_frameCallbackHandler.hasScheduledFrame == true) { - _stopwatch.start(); - } - } - - void _applyFrameMetricsToSpan( - ISentrySpan span, Map frameMetrics) { - frameMetrics.forEach((key, value) { - span.setData(key, value); - }); - - // This will call the methods on the tracer, not on the span directly - if (span is SentrySpan && span.isRootSpan) { - frameMetrics.forEach((key, value) { - // ignore: invalid_use_of_internal_member - span.tracer.setData(key, value); - - // In measurements we change e.g frames.total to frames_total - // We don't do span.tracer.setMeasurement because setMeasurement in SentrySpan - // uses the tracer internally - span.setMeasurement(key.replaceAll('.', '_'), value); - }); - } - } - - @visibleForTesting - Map calculateFrameMetrics( - ISentrySpan span, DateTime spanEndTimestamp, int displayRefreshRate) { - if (frames.isEmpty) { - options.logger( - SentryLevel.info, 'No frame durations available in frame tracker.'); - return {}; - } - - final expectedFrameDuration = ((1 / displayRefreshRate) * 1000).toInt(); - - int slowFramesCount = 0; - int frozenFramesCount = 0; - int slowFramesDuration = 0; - int frozenFramesDuration = 0; - int framesDelay = 0; - - for (final entry in frames.entries) { - final frameDuration = entry.value; - final frameEndTimestamp = entry.key; - final frameStartMs = - frameEndTimestamp.millisecondsSinceEpoch - frameDuration; - final frameEndMs = frameEndTimestamp.millisecondsSinceEpoch; - final spanStartMs = span.startTimestamp.millisecondsSinceEpoch; - final spanEndMs = spanEndTimestamp.millisecondsSinceEpoch; - - final frameFullyContainedInSpan = - frameEndMs <= spanEndMs && frameStartMs >= spanStartMs; - final frameStartsBeforeSpan = - frameStartMs < spanStartMs && frameEndMs > spanStartMs; - final frameEndsAfterSpan = - frameStartMs < spanEndMs && frameEndMs > spanEndMs; - final framePartiallyContainedInSpan = - frameStartsBeforeSpan || frameEndsAfterSpan; - - int effectiveDuration = 0; - int effectiveDelay = 0; - - if (frameFullyContainedInSpan) { - effectiveDuration = frameDuration; - effectiveDelay = max(0, frameDuration - expectedFrameDuration); - } else if (framePartiallyContainedInSpan) { - final intersectionStart = max(frameStartMs, spanStartMs); - final intersectionEnd = min(frameEndMs, spanEndMs); - effectiveDuration = intersectionEnd - intersectionStart; - - final fullFrameDelay = max(0, frameDuration - expectedFrameDuration); - final intersectionRatio = effectiveDuration / frameDuration; - effectiveDelay = (fullFrameDelay * intersectionRatio).round(); - } else if (frameStartMs > spanEndMs) { - // Other frames will be newer than this span, as frames are ordered - break; - } else { - // Frame is completely outside the span, skip it - continue; - } - - if (effectiveDuration > _frozenFrameThresholdMs) { - frozenFramesCount++; - frozenFramesDuration += effectiveDuration; - } else if (effectiveDuration > expectedFrameDuration) { - slowFramesCount++; - slowFramesDuration += effectiveDuration; - } - - framesDelay += effectiveDelay; - } - - final spanDuration = - spanEndTimestamp.difference(span.startTimestamp).inMilliseconds; - final totalFramesCount = - ((spanDuration - (slowFramesDuration + frozenFramesDuration)) / - expectedFrameDuration) + - slowFramesCount + - frozenFramesCount; - - if (totalFramesCount < 0 || - framesDelay < 0 || - slowFramesCount < 0 || - frozenFramesCount < 0) { - options.logger(SentryLevel.warning, - 'Negative frame metrics calculated. Dropping frame metrics.'); - return {}; - } - - return { - SpanFrameMetricsCollector.totalFramesKey: totalFramesCount.toInt(), - SpanFrameMetricsCollector.framesDelayKey: framesDelay, - SpanFrameMetricsCollector.slowFramesKey: slowFramesCount, - SpanFrameMetricsCollector.frozenFramesKey: frozenFramesCount, - }; - } - - @override - void clear() { - _isTrackingPaused = true; - frames.clear(); - activeSpans.clear(); - displayRefreshRate = 60; - } -} diff --git a/flutter/lib/src/utils/enum_wrapper.dart b/flutter/lib/src/utils/enum_wrapper.dart deleted file mode 100644 index 6f7772af55..0000000000 --- a/flutter/lib/src/utils/enum_wrapper.dart +++ /dev/null @@ -1,12 +0,0 @@ -String pDescribeEnum(Object enumEntry) { - if (enumEntry is Enum) { - return enumEntry.name; - } - final String description = enumEntry.toString(); - final int indexOfDot = description.indexOf('.'); - assert( - indexOfDot != -1 && indexOfDot < description.length - 1, - 'The provided object "$enumEntry" is not an enum.', - ); - return description.substring(indexOfDot + 1); -} diff --git a/flutter/lib/src/version.dart b/flutter/lib/src/version.dart index c28ec2f5eb..0a431dd2de 100644 --- a/flutter/lib/src/version.dart +++ b/flutter/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.4.0-beta.1'; +const String sdkVersion = '8.3.0'; /// The default SDK name reported to Sentry.io in the submitted events. const String sdkName = 'sentry.dart.flutter'; diff --git a/flutter/pubspec.yaml b/flutter/pubspec.yaml index 5c3c03d051..d2a244f171 100644 --- a/flutter/pubspec.yaml +++ b/flutter/pubspec.yaml @@ -1,5 +1,5 @@ name: sentry_flutter -version: 8.4.0-beta.1 +version: 8.3.0 description: Sentry SDK for Flutter. This package aims to support different Flutter targets by relying on the many platforms supported by Sentry with native SDKs. homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart @@ -23,7 +23,7 @@ dependencies: sdk: flutter flutter_web_plugins: sdk: flutter - sentry: 8.4.0-beta.1 + sentry: 8.3.0 package_info_plus: '>=1.0.0' meta: ^1.3.0 ffi: ^2.0.0 diff --git a/flutter/test/fake_frame_callback_handler.dart b/flutter/test/fake_frame_callback_handler.dart index aa450a7911..0dc968f22c 100644 --- a/flutter/test/fake_frame_callback_handler.dart +++ b/flutter/test/fake_frame_callback_handler.dart @@ -1,9 +1,9 @@ import 'package:flutter/scheduler.dart'; import 'package:sentry_flutter/src/frame_callback_handler.dart'; -import 'mocks.dart'; - class FakeFrameCallbackHandler implements FrameCallbackHandler { + FrameCallback? storedCallback; + final Duration finishAfterDuration; FakeFrameCallbackHandler( @@ -15,19 +15,4 @@ class FakeFrameCallbackHandler implements FrameCallbackHandler { await Future.delayed(finishAfterDuration); callback(Duration.zero); } - - @override - Future addPersistentFrameCallback(FrameCallback callback) async { - for (final duration in fakeFrameDurations) { - // Let's wait a bit so the timestamp intervals are large enough - await Future.delayed(Duration(milliseconds: 20)); - callback(duration); - } - } - - @override - bool hasScheduledFrame = true; - - @override - Future get endOfFrame => Future.value(); } diff --git a/flutter/test/file_system_transport_test.dart b/flutter/test/file_system_transport_test.dart index 5aa0713183..aa948e56fb 100644 --- a/flutter/test/file_system_transport_test.dart +++ b/flutter/test/file_system_transport_test.dart @@ -2,29 +2,38 @@ library flutter_test; import 'dart:convert'; - // backcompatibility for Flutter < 3.3 // ignore: unnecessary_import import 'dart:typed_data'; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:mockito/mockito.dart'; import 'package:sentry/sentry.dart'; import 'package:sentry_flutter/src/file_system_transport.dart'; import 'mocks.dart'; -import 'mocks.mocks.dart'; void main() { + const _channel = MethodChannel('sentry_flutter'); + + TestWidgetsFlutterBinding.ensureInitialized(); + late Fixture fixture; setUp(() { fixture = Fixture(); }); - test("$FileSystemTransport won't throw", () async { - final transport = fixture.getSut(); + tearDown(() { + // ignore: deprecated_member_use + _channel.setMockMethodCallHandler(null); + }); + + test('FileSystemTransport wont throw', () async { + // ignore: deprecated_member_use + _channel.setMockMethodCallHandler((MethodCall methodCall) async {}); + + final transport = fixture.getSut(_channel); final event = SentryEvent(); final sdkVersion = SdkVersion(name: 'fixture-sdkName', version: 'fixture-sdkVersion'); @@ -39,10 +48,13 @@ void main() { expect(sentryId, sentryId); }); - test('$FileSystemTransport returns emptyId if channel throws', () async { - when(fixture.binding.captureEnvelope(any, false)).thenThrow(Exception()); + test('FileSystemTransport returns emptyId if channel throws', () async { + // ignore: deprecated_member_use + _channel.setMockMethodCallHandler((MethodCall methodCall) async { + throw Exception(); + }); - final transport = fixture.getSut(); + final transport = fixture.getSut(_channel); final event = SentryEvent(); final sdkVersion = SdkVersion(name: 'fixture-sdkName', version: 'fixture-sdkVersion'); @@ -57,60 +69,14 @@ void main() { expect(SentryId.empty(), sentryId); }); - test( - 'sets unhandled exception flag in captureEnvelope to true for unhandled exception', - () async { - final transport = fixture.getSut(); - - final unhandledException = SentryException( - mechanism: Mechanism(type: 'UnhandledException', handled: false), - threadId: 99, - type: 'Exception', - value: 'Unhandled exception', - ); - final event = SentryEvent(exceptions: [unhandledException]); - final sdkVersion = - SdkVersion(name: 'fixture-sdkName', version: 'fixture-sdkVersion'); - final envelope = SentryEnvelope.fromEvent( - event, - sdkVersion, - dsn: fixture.options.dsn, - ); - - await transport.send(envelope); - - verify(fixture.binding.captureEnvelope(captureAny, true)).captured.single - as Uint8List; - }); - - test( - 'sets unhandled exception flag in captureEnvelope to false for handled exception', - () async { - final transport = fixture.getSut(); - - final unhandledException = SentryException( - mechanism: Mechanism(type: 'UnhandledException', handled: true), - threadId: 99, - type: 'Exception', - value: 'Unhandled exception', - ); - final event = SentryEvent(exceptions: [unhandledException]); - final sdkVersion = - SdkVersion(name: 'fixture-sdkName', version: 'fixture-sdkVersion'); - final envelope = SentryEnvelope.fromEvent( - event, - sdkVersion, - dsn: fixture.options.dsn, - ); - - await transport.send(envelope); - - verify(fixture.binding.captureEnvelope(captureAny, false)).captured.single - as Uint8List; - }); + test('FileSystemTransport asserts the event', () async { + dynamic arguments; + // ignore: deprecated_member_use + _channel.setMockMethodCallHandler((MethodCall methodCall) async { + arguments = methodCall.arguments; + }); - test('$FileSystemTransport asserts the event', () async { - final transport = fixture.getSut(); + final transport = fixture.getSut(_channel); final event = SentryEvent(message: SentryMessage('hi I am a special char ◤')); @@ -123,10 +89,8 @@ void main() { ); await transport.send(envelope); - final envelopeData = - verify(fixture.binding.captureEnvelope(captureAny, false)) - .captured - .single as Uint8List; + final envelopeList = arguments as List; + final envelopeData = envelopeList.first as Uint8List; final envelopeString = utf8.decode(envelopeData); final lines = envelopeString.split('\n'); final envelopeHeader = lines.first; @@ -156,9 +120,8 @@ void main() { class Fixture { final options = SentryOptions(dsn: fakeDsn); - final binding = MockSentryNativeBinding(); - FileSystemTransport getSut() { - return FileSystemTransport(binding, options); + FileSystemTransport getSut(MethodChannel channel) { + return FileSystemTransport(channel, options); } } diff --git a/flutter/test/integrations/fixture.dart b/flutter/test/integrations/fixture.dart deleted file mode 100644 index 19a5ed7904..0000000000 --- a/flutter/test/integrations/fixture.dart +++ /dev/null @@ -1,26 +0,0 @@ -import 'dart:async'; - -import 'package:sentry_flutter/sentry_flutter.dart'; -import 'package:sentry_flutter/src/native/sentry_native_binding.dart'; - -import '../mocks.dart'; -import '../mocks.mocks.dart'; - -class IntegrationTestFixture { - late T sut; - late Hub hub; - final options = SentryFlutterOptions(dsn: fakeDsn); - final binding = MockSentryNativeBinding(); - - IntegrationTestFixture(T Function(SentryNativeBinding) factory) { - // ignore: invalid_use_of_internal_member - options.automatedTestMode = true; - - hub = Hub(options); - sut = factory(binding); - } - - Future registerIntegration() async { - await sut.call(hub, options); - } -} diff --git a/flutter/test/integrations/init_native_sdk_test.dart b/flutter/test/integrations/init_native_sdk_test.dart index 0dcf3af502..6d3bd57e22 100644 --- a/flutter/test/integrations/init_native_sdk_test.dart +++ b/flutter/test/integrations/init_native_sdk_test.dart @@ -25,7 +25,7 @@ void main() { }); var sut = fixture.getSut(channel); - await sut.init(fixture.options); + await sut.init(createOptions()); channel.setMethodCallHandler(null); @@ -76,7 +76,7 @@ void main() { }); var sut = fixture.getSut(channel); - fixture.options + final options = createOptions() ..debug = false ..environment = 'foo' ..release = 'foo@bar+1' @@ -106,10 +106,10 @@ void main() { ..readTimeout = Duration(milliseconds: 9002) ..appHangTimeoutInterval = Duration(milliseconds: 9003); - fixture.options.sdk.addIntegration('foo'); - fixture.options.sdk.addPackage('bar', '1'); + options.sdk.addIntegration('foo'); + options.sdk.addPackage('bar', '1'); - await sut.init(fixture.options); + await sut.init(options); channel.setMethodCallHandler(null); @@ -177,9 +177,7 @@ SentryFlutterOptions createOptions() { } class Fixture { - late SentryFlutterOptions options; SentryNativeChannel getSut(MethodChannel native) { - options = createOptions(); - return SentryNativeChannel(options, native); + return SentryNativeChannel(native); } } diff --git a/flutter/test/integrations/load_contexts_integration_test.dart b/flutter/test/integrations/load_contexts_integration_test.dart index 5acce8d264..a3bbbcbab7 100644 --- a/flutter/test/integrations/load_contexts_integration_test.dart +++ b/flutter/test/integrations/load_contexts_integration_test.dart @@ -1,23 +1,40 @@ @TestOn('vm') library flutter_test; +import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/mockito.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:sentry_flutter/src/integrations/load_contexts_integration.dart'; -import 'fixture.dart'; +import '../mocks.dart'; +import '../mocks.mocks.dart'; void main() { group(LoadContextsIntegration, () { - late IntegrationTestFixture fixture; + const _channel = MethodChannel('sentry_flutter'); - setUp(() async { - fixture = IntegrationTestFixture(LoadContextsIntegration.new); - await fixture.registerIntegration(); + TestWidgetsFlutterBinding.ensureInitialized(); + + late Fixture fixture; + + setUp(() { + fixture = Fixture(); + }); + + tearDown(() { + // ignore: deprecated_member_use + _channel.setMockMethodCallHandler(null); }); test('loadContextsIntegration adds integration', () { + // ignore: deprecated_member_use + _channel.setMockMethodCallHandler((MethodCall methodCall) async {}); + + final integration = LoadContextsIntegration(_channel); + + integration(fixture.hub, fixture.options); + expect( fixture.options.sdk.integrations.contains('loadContextsIntegration'), true); @@ -29,10 +46,19 @@ void main() { final eventBreadcrumb = Breadcrumb(message: 'event'); var event = SentryEvent(breadcrumbs: [eventBreadcrumb]); - when(fixture.binding.loadContexts()).thenAnswer((_) async => { - 'breadcrumbs': [Breadcrumb(message: 'native').toJson()] - }); + final nativeBreadcrumb = Breadcrumb(message: 'native'); + Map loadContexts = { + 'breadcrumbs': [nativeBreadcrumb.toJson()] + }; + + final future = Future.value(loadContexts); + when(fixture.methodChannel.invokeMethod('loadContexts')) + .thenAnswer((_) => future); + // ignore: deprecated_member_use + _channel.setMockMethodCallHandler((MethodCall methodCall) async {}); + final integration = LoadContextsIntegration(fixture.methodChannel); + integration.call(fixture.hub, fixture.options); event = (await fixture.options.eventProcessors.first.apply(event, Hint()))!; @@ -46,10 +72,19 @@ void main() { final eventBreadcrumb = Breadcrumb(message: 'event'); var event = SentryEvent(breadcrumbs: [eventBreadcrumb]); - when(fixture.binding.loadContexts()).thenAnswer((_) async => { - 'breadcrumbs': [Breadcrumb(message: 'native').toJson()] - }); + final nativeBreadcrumb = Breadcrumb(message: 'native'); + Map loadContexts = { + 'breadcrumbs': [nativeBreadcrumb.toJson()] + }; + + final future = Future.value(loadContexts); + when(fixture.methodChannel.invokeMethod('loadContexts')) + .thenAnswer((_) => future); + // ignore: deprecated_member_use + _channel.setMockMethodCallHandler((MethodCall methodCall) async {}); + final integration = LoadContextsIntegration(fixture.methodChannel); + integration.call(fixture.hub, fixture.options); event = (await fixture.options.eventProcessors.first.apply(event, Hint()))!; @@ -70,13 +105,23 @@ void main() { final eventBreadcrumb = Breadcrumb(message: 'event'); var event = SentryEvent(breadcrumbs: [eventBreadcrumb]); - when(fixture.binding.loadContexts()).thenAnswer((_) async => { - 'breadcrumbs': [ - Breadcrumb(message: 'native-mutated').toJson(), - Breadcrumb(message: 'native-deleted').toJson(), - ] - }); + final nativeMutatedBreadcrumb = Breadcrumb(message: 'native-mutated'); + final nativeDeletedBreadcrumb = Breadcrumb(message: 'native-deleted'); + Map loadContexts = { + 'breadcrumbs': [ + nativeMutatedBreadcrumb.toJson(), + nativeDeletedBreadcrumb.toJson(), + ] + }; + + final future = Future.value(loadContexts); + when(fixture.methodChannel.invokeMethod('loadContexts')) + .thenAnswer((_) => future); + // ignore: deprecated_member_use + _channel.setMockMethodCallHandler((MethodCall methodCall) async {}); + final integration = LoadContextsIntegration(fixture.methodChannel); + integration.call(fixture.hub, fixture.options); event = (await fixture.options.eventProcessors.first.apply(event, Hint()))!; @@ -103,8 +148,16 @@ void main() { final options = fixture.options; final user = SentryUser(id: expectedId); - when(fixture.binding.loadContexts()) - .thenAnswer((_) async => {'user': user.toJson()}); + Map loadContexts = {'user': user.toJson()}; + final future = Future.value(loadContexts); + when(fixture.methodChannel.invokeMethod('loadContexts')) + .thenAnswer((_) => future); + // ignore: deprecated_member_use + _channel.setMockMethodCallHandler((MethodCall methodCall) async {}); + + final integration = LoadContextsIntegration(fixture.methodChannel); + options.addIntegration(integration); + options.integrations.first.call(fixture.hub, options); final client = SentryClient(options); final event = SentryEvent(); @@ -116,3 +169,10 @@ void main() { }); }); } + +class Fixture { + final hub = MockHub(); + final options = SentryFlutterOptions(dsn: fakeDsn); + + final methodChannel = MockMethodChannel(); +} diff --git a/flutter/test/integrations/load_contexts_integrations_test.dart b/flutter/test/integrations/load_contexts_integrations_test.dart index a1490b8212..8c7ae456e0 100644 --- a/flutter/test/integrations/load_contexts_integrations_test.dart +++ b/flutter/test/integrations/load_contexts_integrations_test.dart @@ -1,8 +1,8 @@ @TestOn('vm') library flutter_test; +import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:mockito/mockito.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:sentry_flutter/src/integrations/load_contexts_integration.dart'; @@ -84,7 +84,7 @@ void main() { final event = await fixture.options.eventProcessors.first.apply(e, Hint()); - verify(fixture.binding.loadContexts()).called(1); + expect(fixture.called, true); expect(event?.contexts.device?.name, 'Device1'); expect(event?.contexts.app?.name, 'test-app'); expect(event?.contexts.app?.inForeground, true); @@ -124,7 +124,7 @@ void main() { final event = await fixture.options.eventProcessors.first.apply(e, Hint()); - verify(fixture.binding.loadContexts()).called(1); + expect(fixture.called, true); expect(event?.contexts.device?.name, 'eDevice'); expect(event?.contexts.app?.name, 'eApp'); expect(event?.contexts.app?.inForeground, true); @@ -236,7 +236,10 @@ void main() { ); test('should not throw on loadContextsIntegration exception', () async { - when(fixture.binding.loadContexts()).thenThrow(Exception()); + // ignore: deprecated_member_use + fixture.channel.setMockMethodCallHandler((MethodCall methodCall) async { + throw Exception(); + }); final integration = fixture.getSut(); integration(fixture.hub, fixture.options); @@ -423,9 +426,12 @@ void main() { } class Fixture { + final channel = MethodChannel('sentry_flutter'); + final hub = MockHub(); final options = SentryFlutterOptions(); - final binding = MockSentryNativeBinding(); + + var called = false; LoadContextsIntegration getSut( {Map contexts = const { @@ -460,7 +466,12 @@ class Fixture { } ] }}) { - when(binding.loadContexts()).thenAnswer((_) async => contexts); - return LoadContextsIntegration(binding); + // ignore: deprecated_member_use + channel.setMockMethodCallHandler((MethodCall methodCall) async { + called = true; + return contexts; + }); + + return LoadContextsIntegration(channel); } } diff --git a/flutter/test/integrations/load_image_list_test.dart b/flutter/test/integrations/load_image_list_test.dart index 35e59b7599..f7c72fc95e 100644 --- a/flutter/test/integrations/load_image_list_test.dart +++ b/flutter/test/integrations/load_image_list_test.dart @@ -1,62 +1,121 @@ @TestOn('vm') library flutter_test; +import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:mockito/mockito.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:sentry_flutter/src/integrations/load_image_list_integration.dart'; -import 'fixture.dart'; +import '../mocks.dart'; +import '../sentry_flutter_test.dart'; void main() { group(LoadImageListIntegration, () { - final imageList = [ - DebugImage.fromJson({ - 'code_file': '/apex/com.android.art/javalib/arm64/boot.oat', - 'code_id': '13577ce71153c228ecf0eb73fc39f45010d487f8', - 'image_addr': '0x6f80b000', - 'image_size': 3092480, - 'type': 'elf', - 'debug_id': 'e77c5713-5311-28c2-ecf0-eb73fc39f450', - 'debug_file': 'test' - }) - ]; - - late IntegrationTestFixture fixture; - - setUp(() async { - fixture = IntegrationTestFixture(LoadImageListIntegration.new); - when(fixture.binding.loadDebugImages()) - .thenAnswer((_) async => imageList); - await fixture.registerIntegration(); - }); - - test('$LoadImageListIntegration adds itself to sdk.integrations', () async { - expect( - fixture.options.sdk.integrations.contains('loadImageListIntegration'), - true, - ); - }); - - test('Native layer is not called as the event is symbolicated', () async { - expect(fixture.options.eventProcessors.length, 1); - - await fixture.hub.captureException(StateError('error'), - stackTrace: StackTrace.current); - - verifyNever(fixture.binding.loadDebugImages()); - }); - - test('Native layer is not called if the event has no stack traces', - () async { - await fixture.hub.captureException(StateError('error')); + TestWidgetsFlutterBinding.ensureInitialized(); + late Fixture fixture; - verifyNever(fixture.binding.loadDebugImages()); + tearDown(() { + // ignore: deprecated_member_use + fixture.channel.setMockMethodCallHandler(null); }); - test('Native layer is called because stack traces are not symbolicated', - () async { - await fixture.hub.captureException(StateError('error'), stackTrace: ''' + for (var platform in [ + MockPlatform.android(), + MockPlatform.iOs(), + MockPlatform.macOs() + ]) { + group(platform.operatingSystem, () { + final imageList = [ + { + 'code_file': '/apex/com.android.art/javalib/arm64/boot.oat', + 'code_id': '13577ce71153c228ecf0eb73fc39f45010d487f8', + 'image_addr': '0x6f80b000', + 'image_size': 3092480, + 'type': 'elf', + 'debug_id': 'e77c5713-5311-28c2-ecf0-eb73fc39f450', + 'debug_file': 'test' + } + ]; + + setUp(() { + fixture = Fixture(platform); + fixture.channel + // ignore: deprecated_member_use + .setMockMethodCallHandler((MethodCall methodCall) async { + return imageList; + }); + }); + + test('$LoadImageListIntegration adds itself to sdk.integrations', + () async { + final sut = fixture.getSut(); + + sut.call(fixture.hub, fixture.options); + + expect( + fixture.options.sdk.integrations + .contains('loadImageListIntegration'), + true, + ); + }); + + test('Native layer is not called as the event is symbolicated', + () async { + var called = false; + + final sut = fixture.getSut(); + fixture.channel + // ignore: deprecated_member_use + .setMockMethodCallHandler((MethodCall methodCall) async { + called = true; + return imageList; + }); + + sut.call(fixture.hub, fixture.options); + + expect(fixture.options.eventProcessors.length, 1); + + await fixture.hub.captureException(StateError('error'), + stackTrace: StackTrace.current); + + expect(called, false); + }); + + test('Native layer is not called if the event has no stack traces', + () async { + var called = false; + + final sut = fixture.getSut(); + fixture.channel + // ignore: deprecated_member_use + .setMockMethodCallHandler((MethodCall methodCall) async { + called = true; + return imageList; + }); + + sut.call(fixture.hub, fixture.options); + + await fixture.hub.captureException(StateError('error')); + + expect(called, false); + }); + + test('Native layer is called because stack traces are not symbolicated', + () async { + var called = false; + + final sut = fixture.getSut(); + fixture.channel + // ignore: deprecated_member_use + .setMockMethodCallHandler((MethodCall methodCall) async { + called = true; + return imageList; + }); + + sut.call(fixture.hub, fixture.options); + + await fixture.hub + .captureException(StateError('error'), stackTrace: ''' warning: This VM has been configured to produce stack traces that violate the Dart standard. *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** pid: 30930, tid: 30990, name 1.ui @@ -67,41 +126,62 @@ void main() { #01 abs 000000723d637527 virt 00000000001f0527 _kDartIsolateSnapshotInstructions+0x1e5527 '''); - verify(fixture.binding.loadDebugImages()).called(1); - }); + expect(called, true); + }); - test('Event processor adds image list to the event', () async { - final ep = fixture.options.eventProcessors.first; - expect( - ep.runtimeType.toString(), "_LoadImageListIntegrationEventProcessor"); - SentryEvent? event = _getEvent(); - event = await ep.apply(event, Hint()); + test('Event processor adds image list to the event', () async { + final sut = fixture.getSut(); - expect(1, event!.debugMeta!.images.length); - }); + sut.call(fixture.hub, fixture.options); - test('Event processor asserts image list', () async { - final ep = fixture.options.eventProcessors.first; - SentryEvent? event = _getEvent(); - event = await ep.apply(event, Hint()); + final ep = fixture.options.eventProcessors.first; + SentryEvent? event = _getEvent(); + event = await ep.apply(event, Hint()); - final image = event!.debugMeta!.images.first; + expect(1, event!.debugMeta!.images.length); + }); - expect('/apex/com.android.art/javalib/arm64/boot.oat', image.codeFile); - expect('13577ce71153c228ecf0eb73fc39f45010d487f8', image.codeId); - expect('0x6f80b000', image.imageAddr); - expect(3092480, image.imageSize); - expect('elf', image.type); - expect('e77c5713-5311-28c2-ecf0-eb73fc39f450', image.debugId); - expect('test', image.debugFile); - }); + test('Event processor asserts image list', () async { + final sut = fixture.getSut(); - test('Native layer is not called as there is no exceptions', () async { - expect(fixture.options.eventProcessors.length, 1); + sut.call(fixture.hub, fixture.options); + final ep = fixture.options.eventProcessors.first; + SentryEvent? event = _getEvent(); + event = await ep.apply(event, Hint()); - await fixture.hub.captureMessage('error'); - verifyNever(fixture.binding.loadDebugImages()); - }); + final image = event!.debugMeta!.images.first; + + expect( + '/apex/com.android.art/javalib/arm64/boot.oat', image.codeFile); + expect('13577ce71153c228ecf0eb73fc39f45010d487f8', image.codeId); + expect('0x6f80b000', image.imageAddr); + expect(3092480, image.imageSize); + expect('elf', image.type); + expect('e77c5713-5311-28c2-ecf0-eb73fc39f450', image.debugId); + expect('test', image.debugFile); + }); + + test('Native layer is not called as there is no exceptions', () async { + var called = false; + + final sut = fixture.getSut(); + fixture.channel + // ignore: deprecated_member_use + .setMockMethodCallHandler((MethodCall methodCall) async { + called = true; + return imageList; + }); + + sut.call(fixture.hub, fixture.options); + + expect(fixture.options.eventProcessors.length, 1); + + await fixture.hub.captureMessage('error'); + + expect(called, false); + }); + }); + } }); } @@ -110,3 +190,19 @@ SentryEvent _getEvent() { final st = SentryStackTrace(frames: [frame]); return SentryEvent(threads: [SentryThread(stacktrace: st)]); } + +class Fixture { + late final Hub hub; + late final SentryFlutterOptions options; + final channel = MethodChannel('sentry_flutter'); + + Fixture(MockPlatform platform) { + options = SentryFlutterOptions( + dsn: fakeDsn, checker: getPlatformChecker(platform: platform)); + hub = Hub(options); + } + + LoadImageListIntegration getSut() { + return LoadImageListIntegration(channel); + } +} diff --git a/flutter/test/integrations/native_app_start_integration_test.dart b/flutter/test/integrations/native_app_start_integration_test.dart index 707163c790..eb13b41a8d 100644 --- a/flutter/test/integrations/native_app_start_integration_test.dart +++ b/flutter/test/integrations/native_app_start_integration_test.dart @@ -5,14 +5,13 @@ import 'package:collection/collection.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/mockito.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; -import 'package:sentry_flutter/src/integrations/integrations.dart'; import 'package:sentry_flutter/src/integrations/native_app_start_integration.dart'; +import 'package:sentry_flutter/src/native/sentry_native.dart'; import 'package:sentry/src/sentry_tracer.dart'; -import 'package:sentry_flutter/src/native/native_app_start.dart'; import '../fake_frame_callback_handler.dart'; +import '../mocks.dart'; import '../mocks.mocks.dart'; -import 'fixture.dart'; void main() { void setupMocks(Fixture fixture) { @@ -29,22 +28,23 @@ void main() { late Fixture fixture; setUp(() { + TestWidgetsFlutterBinding.ensureInitialized(); + fixture = Fixture(); setupMocks(fixture); - when(fixture.binding.fetchNativeAppStart()).thenAnswer((_) async => - NativeAppStart( - appStartTime: 0, - pluginRegistrationTime: 10, - isColdStart: true, - nativeSpanTimes: {})); + NativeAppStartIntegration.clearAppStartInfo(); }); test('native app start measurement added to first transaction', () async { - NativeAppStartIntegration.appStartEnd = - DateTime.fromMillisecondsSinceEpoch(10); + fixture.native.appStartEnd = DateTime.fromMillisecondsSinceEpoch(10); + fixture.binding.nativeAppStart = NativeAppStart( + appStartTime: 0, + pluginRegistrationTime: 10, + isColdStart: true, + nativeSpanTimes: {}); - await fixture.registerIntegration(); + fixture.getNativeAppStartIntegration().call(fixture.hub, fixture.options); final tracer = fixture.createTracer(); final transaction = SentryTransaction(tracer); @@ -60,10 +60,14 @@ void main() { test('native app start measurement not added to following transactions', () async { - NativeAppStartIntegration.appStartEnd = - DateTime.fromMillisecondsSinceEpoch(10); + fixture.native.appStartEnd = DateTime.fromMillisecondsSinceEpoch(10); + fixture.binding.nativeAppStart = NativeAppStart( + appStartTime: 0, + pluginRegistrationTime: 10, + isColdStart: true, + nativeSpanTimes: {}); - await fixture.registerIntegration(); + fixture.getNativeAppStartIntegration().call(fixture.hub, fixture.options); final tracer = fixture.createTracer(); final transaction = SentryTransaction(tracer); @@ -79,11 +83,15 @@ void main() { }); test('measurements appended', () async { - NativeAppStartIntegration.appStartEnd = - DateTime.fromMillisecondsSinceEpoch(10); + fixture.native.appStartEnd = DateTime.fromMillisecondsSinceEpoch(10); + fixture.binding.nativeAppStart = NativeAppStart( + appStartTime: 0, + pluginRegistrationTime: 10, + isColdStart: true, + nativeSpanTimes: {}); final measurement = SentryMeasurement.warmAppStart(Duration(seconds: 1)); - await fixture.registerIntegration(); + fixture.getNativeAppStartIntegration().call(fixture.hub, fixture.options); final tracer = fixture.createTracer(); final transaction = SentryTransaction(tracer).copyWith(); @@ -101,10 +109,14 @@ void main() { }); test('native app start measurement not added if more than 60s', () async { - NativeAppStartIntegration.appStartEnd = - DateTime.fromMillisecondsSinceEpoch(60001); + fixture.native.appStartEnd = DateTime.fromMillisecondsSinceEpoch(60001); + fixture.binding.nativeAppStart = NativeAppStart( + appStartTime: 0, + pluginRegistrationTime: 10, + isColdStart: true, + nativeSpanTimes: {}); - await fixture.registerIntegration(); + fixture.getNativeAppStartIntegration().call(fixture.hub, fixture.options); final tracer = fixture.createTracer(); final transaction = SentryTransaction(tracer); @@ -118,10 +130,14 @@ void main() { test('native app start integration is called and sets app start info', () async { - NativeAppStartIntegration.appStartEnd = - DateTime.fromMillisecondsSinceEpoch(10); + fixture.native.appStartEnd = DateTime.fromMillisecondsSinceEpoch(10); + fixture.binding.nativeAppStart = NativeAppStart( + appStartTime: 0, + pluginRegistrationTime: 10, + isColdStart: true, + nativeSpanTimes: {}); - await fixture.registerIntegration(); + fixture.getNativeAppStartIntegration().call(fixture.hub, fixture.options); final appStartInfo = await NativeAppStartIntegration.getAppStartInfo(); expect(appStartInfo?.start, DateTime.fromMillisecondsSinceEpoch(0)); @@ -132,8 +148,13 @@ void main() { 'autoAppStart is false and appStartEnd is not set does not add app start measurement', () async { fixture.options.autoAppStart = false; + fixture.binding.nativeAppStart = NativeAppStart( + appStartTime: 0, + pluginRegistrationTime: 10, + isColdStart: true, + nativeSpanTimes: {}); - await fixture.registerIntegration(); + fixture.getNativeAppStartIntegration().call(fixture.hub, fixture.options); final tracer = fixture.createTracer(); final transaction = SentryTransaction(tracer); @@ -146,36 +167,18 @@ void main() { expect(enriched.spans.isEmpty, true); }); - test( - 'does not trigger timeout if autoAppStart is false and setAppStartEnd is not called', - () async { - // setting a frame callback with a bigger timeout than our app start timeout so the timeout would theoretically be triggered - fixture = Fixture( - frameCallbackTimeout: NativeAppStartIntegration.timeoutDuration + - const Duration(seconds: 5)); - fixture.options.autoAppStart = false; - - await fixture.registerIntegration(); - - final tracer = fixture.createTracer(); - final transaction = SentryTransaction(tracer); - - final processor = fixture.options.eventProcessors.first; - - final stopwatch = Stopwatch()..start(); - await processor.apply(transaction, Hint()) as SentryTransaction; - stopwatch.stop(); - - expect(stopwatch.elapsed < NativeAppStartIntegration.timeoutDuration, - isTrue); - }); - test( 'autoAppStart is false and appStartEnd is set adds app start measurement', () async { fixture.options.autoAppStart = false; + fixture.binding.nativeAppStart = NativeAppStart( + appStartTime: 0, + pluginRegistrationTime: 10, + isColdStart: true, + nativeSpanTimes: {}); + SentryFlutter.native = fixture.native; - await fixture.registerIntegration(); + fixture.getNativeAppStartIntegration().call(fixture.hub, fixture.options); SentryFlutter.setAppStartEnd(DateTime.fromMillisecondsSinceEpoch(10)); @@ -247,32 +250,29 @@ void main() { }, }; - final appStartInfoSrc = NativeAppStart( - appStartTime: 0, - pluginRegistrationTime: 10, - isColdStart: true, - nativeSpanTimes: { - ...validNativeSpanTimes, - ...invalidNativeSpanTimes, - }); + final allNativeSpanTimes = { + ...validNativeSpanTimes, + ...invalidNativeSpanTimes, + }; setUp(() async { + TestWidgetsFlutterBinding.ensureInitialized(); + fixture = Fixture(); NativeAppStartIntegration.clearAppStartInfo(); - NativeAppStartIntegration.appStartEnd = - DateTime.fromMillisecondsSinceEpoch(50); - + fixture.native.appStartEnd = DateTime.fromMillisecondsSinceEpoch(50); + fixture.binding.nativeAppStart = NativeAppStart( + appStartTime: 0, + pluginRegistrationTime: 10, + isColdStart: true, + nativeSpanTimes: allNativeSpanTimes); // dartLoadingEnd needs to be set after engine end (see MockNativeChannel) SentryFlutter.sentrySetupStartTime = DateTime.fromMillisecondsSinceEpoch(15); setupMocks(fixture); - - when(fixture.binding.fetchNativeAppStart()) - .thenAnswer((_) async => appStartInfoSrc); - - await fixture.registerIntegration(); + fixture.getNativeAppStartIntegration().call(fixture.hub, fixture.options); final processor = fixture.options.eventProcessors.first; tracer = fixture.createTracer(); @@ -380,7 +380,7 @@ void main() { test('have correct startTimestamp', () async { final appStartTime = DateTime.fromMillisecondsSinceEpoch( - appStartInfoSrc.appStartTime.toInt()) + fixture.binding.nativeAppStart!.appStartTime.toInt()) .toUtc(); expect(coldStartSpan?.startTimestamp, appStartTime); expect(pluginRegistrationSpan?.startTimestamp, appStartTime); @@ -392,10 +392,9 @@ void main() { test('have correct endTimestamp', () async { final engineReadyEndtime = DateTime.fromMillisecondsSinceEpoch( - appStartInfoSrc.pluginRegistrationTime.toInt()) + fixture.binding.nativeAppStart!.pluginRegistrationTime.toInt()) .toUtc(); - expect(coldStartSpan?.endTimestamp, - NativeAppStartIntegration.appStartEnd?.toUtc()); + expect(coldStartSpan?.endTimestamp, fixture.native.appStartEnd?.toUtc()); expect(pluginRegistrationSpan?.endTimestamp, engineReadyEndtime); expect(sentrySetupSpan?.endTimestamp, SentryFlutter.sentrySetupStartTime?.toUtc()); @@ -404,23 +403,25 @@ void main() { }); } -class Fixture extends IntegrationTestFixture { - @override - MockHub get hub => super.hub as MockHub; - - Fixture({Duration? frameCallbackTimeout}) - : super((binding) => NativeAppStartIntegration( - binding, - FakeFrameCallbackHandler( - finishAfterDuration: frameCallbackTimeout ?? - const Duration(milliseconds: 50)))) { - NativeAppStartIntegration.reset(); - hub = MockHub(); - // ignore: invalid_use_of_internal_member +class Fixture { + final hub = MockHub(); + final options = SentryFlutterOptions(dsn: fakeDsn); + final binding = MockNativeChannel(); + late final native = SentryNative(options, binding); + + Fixture() { + native.reset(); when(hub.options).thenReturn(options); SentryFlutter.sentrySetupStartTime = DateTime.now().toUtc(); } + NativeAppStartIntegration getNativeAppStartIntegration() { + return NativeAppStartIntegration( + native, + FakeFrameCallbackHandler(), + ); + } + // ignore: invalid_use_of_internal_member SentryTracer createTracer({ bool? sampled = true, diff --git a/flutter/test/integrations/native_sdk_integration_test.dart b/flutter/test/integrations/native_sdk_integration_test.dart index f94f88698c..1826bd38f2 100644 --- a/flutter/test/integrations/native_sdk_integration_test.dart +++ b/flutter/test/integrations/native_sdk_integration_test.dart @@ -1,66 +1,110 @@ @TestOn('vm') library flutter_test; +import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:mockito/mockito.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:sentry_flutter/src/integrations/native_sdk_integration.dart'; +import '../mocks.dart'; import '../mocks.mocks.dart'; -import 'fixture.dart'; void main() { group(NativeSdkIntegration, () { - late IntegrationTestFixture fixture; + const _channel = MethodChannel('sentry_flutter'); + + TestWidgetsFlutterBinding.ensureInitialized(); + + late Fixture fixture; setUp(() { - fixture = IntegrationTestFixture(NativeSdkIntegration.new); + fixture = Fixture(); + }); + + tearDown(() { + // ignore: deprecated_member_use + _channel.setMockMethodCallHandler(null); }); test('adds integration', () async { - await fixture.registerIntegration(); + // ignore: deprecated_member_use + _channel.setMockMethodCallHandler((MethodCall methodCall) async {}); + final mock = TestMockSentryNative(); + final integration = NativeSdkIntegration(mock); + + await integration(fixture.hub, fixture.options); + expect( fixture.options.sdk.integrations, contains('nativeSdkIntegration')); - verify(fixture.binding.init(any)).called(1); + expect(mock.numberOfInitCalls, 1); }); test('do not throw', () async { - fixture.sut = NativeSdkIntegration(_ThrowingMockSentryNative()); - await fixture.registerIntegration(); + final integration = NativeSdkIntegration(_ThrowingMockSentryNative()); + + await integration(fixture.hub, fixture.options); + expect(fixture.options.sdk.integrations.contains('nativeSdkIntegration'), false); }); test('closes native SDK', () async { - await fixture.registerIntegration(); - await fixture.sut.close(); - verify(fixture.binding.close()).called(1); + final mock = TestMockSentryNative(); + final integration = NativeSdkIntegration(mock); + + await integration.call(fixture.hub, fixture.options); + await integration.close(); + + expect(mock.numberOfCloseCalls, 1); }); test('does not call native sdk when auto init disabled', () async { + final mock = TestMockSentryNative(); + final integration = NativeSdkIntegration(mock); fixture.options.autoInitializeNativeSdk = false; - await fixture.registerIntegration(); - verifyNever(fixture.binding.init(any)); + + await integration.call(fixture.hub, fixture.options); + + expect(mock.numberOfInitCalls, 0); }); test('does not close native when auto init disabled', () async { + final mock = TestMockSentryNative(); + final integration = NativeSdkIntegration(mock); fixture.options.autoInitializeNativeSdk = false; - await fixture.registerIntegration(); - await fixture.sut.close(); - verifyNever(fixture.binding.close()); + + await integration(fixture.hub, fixture.options); + await integration.close(); + + expect(mock.numberOfCloseCalls, 0); + }); + + test('adds integration', () async { + final mock = TestMockSentryNative(); + final integration = NativeSdkIntegration(mock); + + await integration.call(fixture.hub, fixture.options); + + expect(fixture.options.sdk.integrations, ['nativeSdkIntegration']); }); test(' is not added in case of an exception', () async { - fixture.sut = NativeSdkIntegration(_ThrowingMockSentryNative()); - await fixture.registerIntegration(); + final integration = NativeSdkIntegration(_ThrowingMockSentryNative()); + + await integration.call(fixture.hub, fixture.options); expect(fixture.options.sdk.integrations, []); }); }); } -class _ThrowingMockSentryNative extends MockSentryNativeBinding { +class Fixture { + final hub = MockHub(); + final options = SentryFlutterOptions(dsn: fakeDsn); +} + +class _ThrowingMockSentryNative extends TestMockSentryNative { @override - Future init(SentryFlutterOptions? options) async { + Future init(SentryFlutterOptions options) async { throw Exception(); } } diff --git a/flutter/test/load_image_list_test.dart b/flutter/test/load_image_list_test.dart new file mode 100644 index 0000000000..472aac0947 --- /dev/null +++ b/flutter/test/load_image_list_test.dart @@ -0,0 +1,183 @@ +@TestOn('vm') +library flutter_test; + +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:sentry_flutter/sentry_flutter.dart'; +import 'package:sentry_flutter/src/integrations/load_image_list_integration.dart'; + +import 'mocks.dart'; +import 'sentry_flutter_test.dart'; + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + late Fixture fixture; + + tearDown(() { + // ignore: deprecated_member_use + fixture.channel.setMockMethodCallHandler(null); + }); + + for (var platform in [ + MockPlatform.android(), + MockPlatform.iOs(), + MockPlatform.macOs() + ]) { + group(platform.operatingSystem, () { + final imageList = [ + { + 'code_file': '/apex/com.android.art/javalib/arm64/boot.oat', + 'code_id': '13577ce71153c228ecf0eb73fc39f45010d487f8', + 'image_addr': '0x6f80b000', + 'image_size': 3092480, + 'type': 'elf', + 'debug_id': 'e77c5713-5311-28c2-ecf0-eb73fc39f450', + 'debug_file': 'test' + } + ]; + + setUp(() { + fixture = Fixture(platform); + // ignore: deprecated_member_use + fixture.channel.setMockMethodCallHandler((MethodCall methodCall) async { + return imageList; + }); + }); + + test('$LoadImageListIntegration adds itself to sdk.integrations', + () async { + final sut = fixture.getSut(); + + sut.call(fixture.hub, fixture.options); + + expect( + fixture.options.sdk.integrations.contains('loadImageListIntegration'), + true, + ); + }); + + test('Native layer is not called as the event is symbolicated', () async { + var called = false; + + final sut = fixture.getSut(); + // ignore: deprecated_member_use + fixture.channel.setMockMethodCallHandler((MethodCall methodCall) async { + called = true; + return imageList; + }); + + sut.call(fixture.hub, fixture.options); + + expect(fixture.options.eventProcessors.length, 1); + + await fixture.hub.captureException(StateError('error'), + stackTrace: StackTrace.current); + + expect(called, false); + }); + + test('Native layer is not called if the event has no stack traces', + () async { + var called = false; + + final sut = fixture.getSut(); + // ignore: deprecated_member_use + fixture.channel.setMockMethodCallHandler((MethodCall methodCall) async { + called = true; + return imageList; + }); + + sut.call(fixture.hub, fixture.options); + + await fixture.hub.captureException(StateError('error')); + + expect(called, false); + }); + + test('Native layer is called because stack traces are not symbolicated', + () async { + var called = false; + + final sut = fixture.getSut(); + // ignore: deprecated_member_use + fixture.channel.setMockMethodCallHandler((MethodCall methodCall) async { + called = true; + return imageList; + }); + + sut.call(fixture.hub, fixture.options); + + await fixture.hub.captureException(StateError('error'), stackTrace: ''' + warning: This VM has been configured to produce stack traces that violate the Dart standard. + *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** + pid: 30930, tid: 30990, name 1.ui + build_id: '5346e01103ffeed44e97094ff7bfcc19' + isolate_dso_base: 723d447000, vm_dso_base: 723d447000 + isolate_instructions: 723d452000, vm_instructions: 723d449000 + #00 abs 000000723d6346d7 virt 00000000001ed6d7 _kDartIsolateSnapshotInstructions+0x1e26d7 + #01 abs 000000723d637527 virt 00000000001f0527 _kDartIsolateSnapshotInstructions+0x1e5527 + '''); + + expect(called, true); + }); + + test('Event processor adds image list to the event', () async { + final sut = fixture.getSut(); + + sut.call(fixture.hub, fixture.options); + + final ep = fixture.options.eventProcessors.first; + SentryEvent? event = _getEvent(); + event = await ep.apply(event, Hint()); + + expect(1, event!.debugMeta!.images.length); + }); + + test('Event processor asserts image list', () async { + final sut = fixture.getSut(); + + sut.call(fixture.hub, fixture.options); + final ep = fixture.options.eventProcessors.first; + SentryEvent? event = _getEvent(); + event = await ep.apply(event, Hint()); + + final image = event!.debugMeta!.images.first; + + expect('/apex/com.android.art/javalib/arm64/boot.oat', image.codeFile); + expect('13577ce71153c228ecf0eb73fc39f45010d487f8', image.codeId); + expect('0x6f80b000', image.imageAddr); + expect(3092480, image.imageSize); + expect('elf', image.type); + expect('e77c5713-5311-28c2-ecf0-eb73fc39f450', image.debugId); + expect('test', image.debugFile); + }); + }); + } +} + +SentryEvent _getEvent() { + final frame = SentryStackFrame(platform: 'native'); + final st = SentryStackTrace(frames: [frame]); + final ex = SentryException( + type: 'type', + value: 'value', + stackTrace: st, + ); + return SentryEvent(exceptions: [ex]); +} + +class Fixture { + late final Hub hub; + late final SentryFlutterOptions options; + final channel = MethodChannel('sentry_flutter'); + + Fixture(MockPlatform platform) { + options = SentryFlutterOptions( + dsn: fakeDsn, checker: getPlatformChecker(platform: platform)); + hub = Hub(options); + } + + LoadImageListIntegration getSut() { + return LoadImageListIntegration(channel); + } +} diff --git a/flutter/test/mocks.dart b/flutter/test/mocks.dart index f5e5cb65ce..a373ee7511 100644 --- a/flutter/test/mocks.dart +++ b/flutter/test/mocks.dart @@ -10,6 +10,7 @@ import 'package:sentry/src/sentry_tracer.dart'; import 'package:meta/meta.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:sentry_flutter/src/renderer/renderer.dart'; +import 'package:sentry_flutter/src/native/sentry_native.dart'; import 'package:sentry_flutter/src/native/sentry_native_binding.dart'; import 'mocks.mocks.dart'; @@ -47,7 +48,6 @@ ISentrySpan startTransactionShim( SentryTransaction, SentrySpan, MethodChannel, - SentryNativeBinding ], customMocks: [ MockSpec(fallbackGenerators: {#startTransaction: startTransactionShim}) ]) @@ -162,6 +162,271 @@ class NoOpHub with NoSuchMethodProvider implements Hub { bool get isEnabled => false; } +// TODO can this be replaced with https://pub.dev/packages/mockito#verifying-exact-number-of-invocations--at-least-x--never +class TestMockSentryNative implements SentryNative { + @override + DateTime? appStartEnd; + + bool _didFetchAppStart = false; + + @override + bool get didFetchAppStart => _didFetchAppStart; + + @override + bool didAddAppStartMeasurement = false; + + Breadcrumb? breadcrumb; + var numberOfAddBreadcrumbCalls = 0; + var numberOfBeginNativeFramesCollectionCalls = 0; + var numberOfClearBreadcrumbsCalls = 0; + var numberOfEndNativeFramesCollectionCalls = 0; + var numberOfFetchNativeAppStartCalls = 0; + var removeContextsKey = ''; + var numberOfRemoveContextsCalls = 0; + var removeExtraKey = ''; + var numberOfRemoveExtraCalls = 0; + var removeTagKey = ''; + var numberOfRemoveTagCalls = 0; + var numberOfResetCalls = 0; + Map setContextData = {}; + var numberOfSetContextsCalls = 0; + Map setExtraData = {}; + var numberOfSetExtraCalls = 0; + Map setTagsData = {}; + var numberOfSetTagCalls = 0; + SentryUser? sentryUser; + var numberOfSetUserCalls = 0; + var numberOfStartProfilerCalls = 0; + var numberOfDiscardProfilerCalls = 0; + var numberOfCollectProfileCalls = 0; + var numberOfInitCalls = 0; + SentryFlutterOptions? initOptions; + var numberOfCloseCalls = 0; + + @override + Future addBreadcrumb(Breadcrumb breadcrumb) async { + this.breadcrumb = breadcrumb; + numberOfAddBreadcrumbCalls++; + } + + @override + Future beginNativeFramesCollection() async { + numberOfBeginNativeFramesCollectionCalls++; + } + + @override + Future clearBreadcrumbs() async { + numberOfClearBreadcrumbsCalls++; + } + + @override + Future endNativeFramesCollection(SentryId traceId) async { + numberOfEndNativeFramesCollectionCalls++; + return null; + } + + @override + Future fetchNativeAppStart() async { + _didFetchAppStart = true; + numberOfFetchNativeAppStartCalls++; + return null; + } + + @override + Future removeContexts(String key) async { + removeContextsKey = key; + numberOfRemoveContextsCalls++; + } + + @override + Future removeExtra(String key) async { + removeExtraKey = key; + numberOfRemoveExtraCalls++; + } + + @override + Future removeTag(String key) async { + removeTagKey = key; + numberOfRemoveTagCalls++; + } + + @override + void reset() { + numberOfResetCalls++; + } + + @override + Future setContexts(String key, value) async { + setContextData[key] = value; + numberOfSetContextsCalls++; + } + + @override + Future setExtra(String key, value) async { + setExtraData[key] = value; + numberOfSetExtraCalls++; + } + + @override + Future setTag(String key, String value) async { + setTagsData[key] = value; + numberOfSetTagCalls++; + } + + @override + Future setUser(SentryUser? sentryUser) async { + this.sentryUser = sentryUser; + numberOfSetUserCalls++; + } + + @override + Future?> collectProfile( + SentryId traceId, int startTimeNs, int endTimeNs) { + numberOfCollectProfileCalls++; + return Future.value(null); + } + + @override + int? startProfiler(SentryId traceId) { + numberOfStartProfilerCalls++; + return 42; + } + + @override + Future discardProfiler(SentryId traceId) { + numberOfDiscardProfilerCalls++; + return Future.value(null); + } + + @override + Future init(SentryFlutterOptions options) { + numberOfInitCalls++; + initOptions = options; + return Future.value(null); + } + + @override + Future close() { + numberOfCloseCalls++; + return Future.value(null); + } +} + +// TODO can this be replaced with https://pub.dev/packages/mockito#verifying-exact-number-of-invocations--at-least-x--never +class MockNativeChannel implements SentryNativeBinding { + NativeAppStart? nativeAppStart; + NativeFrames? nativeFrames; + SentryId? id; + + int numberOfBeginNativeFramesCalls = 0; + int numberOfEndNativeFramesCalls = 0; + int numberOfSetUserCalls = 0; + int numberOfAddBreadcrumbCalls = 0; + int numberOfClearBreadcrumbCalls = 0; + int numberOfRemoveContextsCalls = 0; + int numberOfRemoveExtraCalls = 0; + int numberOfRemoveTagCalls = 0; + int numberOfSetContextsCalls = 0; + int numberOfSetExtraCalls = 0; + int numberOfSetTagCalls = 0; + int numberOfStartProfilerCalls = 0; + int numberOfDiscardProfilerCalls = 0; + int numberOfCollectProfileCalls = 0; + int numberOfInitCalls = 0; + int numberOfCloseCalls = 0; + + @override + Future fetchNativeAppStart() async => nativeAppStart; + + @override + Future beginNativeFrames() async { + numberOfBeginNativeFramesCalls += 1; + } + + @override + Future endNativeFrames(SentryId id) async { + this.id = id; + numberOfEndNativeFramesCalls += 1; + return nativeFrames; + } + + @override + Future setUser(SentryUser? user) async { + numberOfSetUserCalls += 1; + } + + @override + Future addBreadcrumb(Breadcrumb breadcrumb) async { + numberOfAddBreadcrumbCalls += 1; + } + + @override + Future clearBreadcrumbs() async { + numberOfClearBreadcrumbCalls += 1; + } + + @override + Future removeContexts(String key) async { + numberOfRemoveContextsCalls += 1; + } + + @override + Future removeExtra(String key) async { + numberOfRemoveExtraCalls += 1; + } + + @override + Future removeTag(String key) async { + numberOfRemoveTagCalls += 1; + } + + @override + Future setContexts(String key, value) async { + numberOfSetContextsCalls += 1; + } + + @override + Future setExtra(String key, value) async { + numberOfSetExtraCalls += 1; + } + + @override + Future setTag(String key, value) async { + numberOfSetTagCalls += 1; + } + + @override + Future?> collectProfile( + SentryId traceId, int startTimeNs, int endTimeNs) { + numberOfCollectProfileCalls++; + return Future.value(null); + } + + @override + int? startProfiler(SentryId traceId) { + numberOfStartProfilerCalls++; + return null; + } + + @override + Future discardProfiler(SentryId traceId) { + numberOfDiscardProfilerCalls++; + return Future.value(null); + } + + @override + Future init(SentryFlutterOptions options) { + numberOfInitCalls++; + return Future.value(null); + } + + @override + Future close() { + numberOfCloseCalls++; + return Future.value(null); + } +} + class MockRendererWrapper implements RendererWrapper { MockRendererWrapper(this._renderer); @@ -191,18 +456,3 @@ class TestBindingWrapper implements BindingWrapper { } class MockSentryClient with NoSuchMethodProvider implements SentryClient {} - -// All these values are based on the fakeFrameDurations list. -// The expected total frames is also based on the span duration of 1000ms and the slow and frozen frames. -const expectedTotalFrames = 17; -const expectedFramesDelay = 722; -const expectedSlowFrames = 2; -const expectedFrozenFrames = 1; - -final fakeFrameDurations = [ - Duration(milliseconds: 0), - Duration(milliseconds: 10), - Duration(milliseconds: 20), - Duration(milliseconds: 40), - Duration(milliseconds: 710), -]; diff --git a/flutter/test/mocks.mocks.dart b/flutter/test/mocks.mocks.dart index 01d2127efe..ee81d44430 100644 --- a/flutter/test/mocks.mocks.dart +++ b/flutter/test/mocks.mocks.dart @@ -3,27 +3,20 @@ // Do not manually edit this file. // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:async' as _i8; -import 'dart:typed_data' as _i16; +import 'dart:async' as _i7; import 'package:flutter/src/services/binary_messenger.dart' as _i6; import 'package:flutter/src/services/message_codec.dart' as _i5; -import 'package:flutter/src/services/platform_channel.dart' as _i12; +import 'package:flutter/src/services/platform_channel.dart' as _i11; import 'package:mockito/mockito.dart' as _i1; -import 'package:mockito/src/dummies.dart' as _i10; +import 'package:mockito/src/dummies.dart' as _i9; import 'package:sentry/sentry.dart' as _i2; -import 'package:sentry/src/metrics/metric.dart' as _i19; -import 'package:sentry/src/metrics/metrics_api.dart' as _i7; -import 'package:sentry/src/profiling.dart' as _i11; +import 'package:sentry/src/profiling.dart' as _i10; import 'package:sentry/src/protocol.dart' as _i3; -import 'package:sentry/src/sentry_envelope.dart' as _i9; +import 'package:sentry/src/sentry_envelope.dart' as _i8; import 'package:sentry/src/sentry_tracer.dart' as _i4; -import 'package:sentry_flutter/sentry_flutter.dart' as _i14; -import 'package:sentry_flutter/src/native/native_app_start.dart' as _i15; -import 'package:sentry_flutter/src/native/native_frames.dart' as _i17; -import 'package:sentry_flutter/src/native/sentry_native_binding.dart' as _i13; -import 'mocks.dart' as _i18; +import 'mocks.dart' as _i12; // ignore_for_file: type=lint // ignore_for_file: avoid_redundant_argument_values @@ -152,8 +145,8 @@ class _FakeSentryOptions_10 extends _i1.SmartFake implements _i2.SentryOptions { ); } -class _FakeMetricsApi_11 extends _i1.SmartFake implements _i7.MetricsApi { - _FakeMetricsApi_11( +class _FakeScope_11 extends _i1.SmartFake implements _i2.Scope { + _FakeScope_11( Object parent, Invocation parentInvocation, ) : super( @@ -162,18 +155,8 @@ class _FakeMetricsApi_11 extends _i1.SmartFake implements _i7.MetricsApi { ); } -class _FakeScope_12 extends _i1.SmartFake implements _i2.Scope { - _FakeScope_12( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); -} - -class _FakeHub_13 extends _i1.SmartFake implements _i2.Hub { - _FakeHub_13( +class _FakeHub_12 extends _i1.SmartFake implements _i2.Hub { + _FakeHub_12( Object parent, Invocation parentInvocation, ) : super( @@ -191,14 +174,14 @@ class MockTransport extends _i1.Mock implements _i2.Transport { } @override - _i8.Future<_i3.SentryId?> send(_i9.SentryEnvelope? envelope) => + _i7.Future<_i3.SentryId?> send(_i8.SentryEnvelope? envelope) => (super.noSuchMethod( Invocation.method( #send, [envelope], ), - returnValue: _i8.Future<_i3.SentryId?>.value(), - ) as _i8.Future<_i3.SentryId?>); + returnValue: _i7.Future<_i3.SentryId?>.value(), + ) as _i7.Future<_i3.SentryId?>); } /// A class which mocks [SentryTracer]. @@ -212,7 +195,7 @@ class MockSentryTracer extends _i1.Mock implements _i4.SentryTracer { @override String get name => (super.noSuchMethod( Invocation.getter(#name), - returnValue: _i10.dummyValue( + returnValue: _i9.dummyValue( this, Invocation.getter(#name), ), @@ -246,7 +229,7 @@ class MockSentryTracer extends _i1.Mock implements _i4.SentryTracer { ); @override - set profiler(_i11.SentryProfiler? _profiler) => super.noSuchMethod( + set profiler(_i10.SentryProfiler? _profiler) => super.noSuchMethod( Invocation.setter( #profiler, _profiler, @@ -255,7 +238,7 @@ class MockSentryTracer extends _i1.Mock implements _i4.SentryTracer { ); @override - set profileInfo(_i11.SentryProfileInfo? _profileInfo) => super.noSuchMethod( + set profileInfo(_i10.SentryProfileInfo? _profileInfo) => super.noSuchMethod( Invocation.setter( #profileInfo, _profileInfo, @@ -339,7 +322,7 @@ class MockSentryTracer extends _i1.Mock implements _i4.SentryTracer { ) as Map); @override - _i8.Future finish({ + _i7.Future finish({ _i3.SpanStatus? status, DateTime? endTimestamp, }) => @@ -352,9 +335,9 @@ class MockSentryTracer extends _i1.Mock implements _i4.SentryTracer { #endTimestamp: endTimestamp, }, ), - returnValue: _i8.Future.value(), - returnValueForMissingStub: _i8.Future.value(), - ) as _i8.Future); + returnValue: _i7.Future.value(), + returnValueForMissingStub: _i7.Future.value(), + ) as _i7.Future); @override void removeData(String? key) => super.noSuchMethod( @@ -579,16 +562,6 @@ class MockSentryTransaction extends _i1.Mock implements _i3.SentryTransaction { returnValueForMissingStub: null, ); - @override - set metricSummaries(Map>? _metricSummaries) => - super.noSuchMethod( - Invocation.setter( - #metricSummaries, - _metricSummaries, - ), - returnValueForMissingStub: null, - ); - @override set transactionInfo(_i3.SentryTransactionInfo? _transactionInfo) => super.noSuchMethod( @@ -739,7 +712,6 @@ class MockSentryTransaction extends _i1.Mock implements _i3.SentryTransaction { #threads: threads, #type: type, #measurements: measurements, - #metricSummaries: metricSummaries, #transactionInfo: transactionInfo, }, ), @@ -755,21 +727,6 @@ class MockSentrySpan extends _i1.Mock implements _i3.SentrySpan { _i1.throwOnMissingStub(this); } - @override - bool get isRootSpan => (super.noSuchMethod( - Invocation.getter(#isRootSpan), - returnValue: false, - ) as bool); - - @override - _i4.SentryTracer get tracer => (super.noSuchMethod( - Invocation.getter(#tracer), - returnValue: _FakeSentryTracer_4( - this, - Invocation.getter(#tracer), - ), - ) as _i4.SentryTracer); - @override set status(_i3.SpanStatus? status) => super.noSuchMethod( Invocation.setter( @@ -834,7 +791,7 @@ class MockSentrySpan extends _i1.Mock implements _i3.SentrySpan { ) as Map); @override - _i8.Future finish({ + _i7.Future finish({ _i3.SpanStatus? status, DateTime? endTimestamp, }) => @@ -847,9 +804,9 @@ class MockSentrySpan extends _i1.Mock implements _i3.SentrySpan { #endTimestamp: endTimestamp, }, ), - returnValue: _i8.Future.value(), - returnValueForMissingStub: _i8.Future.value(), - ) as _i8.Future); + returnValue: _i7.Future.value(), + returnValueForMissingStub: _i7.Future.value(), + ) as _i7.Future); @override void removeData(String? key) => super.noSuchMethod( @@ -984,7 +941,7 @@ class MockSentrySpan extends _i1.Mock implements _i3.SentrySpan { /// A class which mocks [MethodChannel]. /// /// See the documentation for Mockito's code generation for more information. -class MockMethodChannel extends _i1.Mock implements _i12.MethodChannel { +class MockMethodChannel extends _i1.Mock implements _i11.MethodChannel { MockMethodChannel() { _i1.throwOnMissingStub(this); } @@ -992,7 +949,7 @@ class MockMethodChannel extends _i1.Mock implements _i12.MethodChannel { @override String get name => (super.noSuchMethod( Invocation.getter(#name), - returnValue: _i10.dummyValue( + returnValue: _i9.dummyValue( this, Invocation.getter(#name), ), @@ -1017,7 +974,7 @@ class MockMethodChannel extends _i1.Mock implements _i12.MethodChannel { ) as _i6.BinaryMessenger); @override - _i8.Future invokeMethod( + _i7.Future invokeMethod( String? method, [ dynamic arguments, ]) => @@ -1029,11 +986,11 @@ class MockMethodChannel extends _i1.Mock implements _i12.MethodChannel { arguments, ], ), - returnValue: _i8.Future.value(), - ) as _i8.Future); + returnValue: _i7.Future.value(), + ) as _i7.Future); @override - _i8.Future?> invokeListMethod( + _i7.Future?> invokeListMethod( String? method, [ dynamic arguments, ]) => @@ -1045,11 +1002,11 @@ class MockMethodChannel extends _i1.Mock implements _i12.MethodChannel { arguments, ], ), - returnValue: _i8.Future?>.value(), - ) as _i8.Future?>); + returnValue: _i7.Future?>.value(), + ) as _i7.Future?>); @override - _i8.Future?> invokeMapMethod( + _i7.Future?> invokeMapMethod( String? method, [ dynamic arguments, ]) => @@ -1061,12 +1018,12 @@ class MockMethodChannel extends _i1.Mock implements _i12.MethodChannel { arguments, ], ), - returnValue: _i8.Future?>.value(), - ) as _i8.Future?>); + returnValue: _i7.Future?>.value(), + ) as _i7.Future?>); @override void setMethodCallHandler( - _i8.Future Function(_i5.MethodCall)? handler) => + _i7.Future Function(_i5.MethodCall)? handler) => super.noSuchMethod( Invocation.method( #setMethodCallHandler, @@ -1076,278 +1033,6 @@ class MockMethodChannel extends _i1.Mock implements _i12.MethodChannel { ); } -/// A class which mocks [SentryNativeBinding]. -/// -/// See the documentation for Mockito's code generation for more information. -class MockSentryNativeBinding extends _i1.Mock - implements _i13.SentryNativeBinding { - MockSentryNativeBinding() { - _i1.throwOnMissingStub(this); - } - - @override - _i8.Future init(_i14.SentryFlutterOptions? options) => - (super.noSuchMethod( - Invocation.method( - #init, - [options], - ), - returnValue: _i8.Future.value(), - returnValueForMissingStub: _i8.Future.value(), - ) as _i8.Future); - - @override - _i8.Future close() => (super.noSuchMethod( - Invocation.method( - #close, - [], - ), - returnValue: _i8.Future.value(), - returnValueForMissingStub: _i8.Future.value(), - ) as _i8.Future); - - @override - _i8.Future<_i15.NativeAppStart?> fetchNativeAppStart() => (super.noSuchMethod( - Invocation.method( - #fetchNativeAppStart, - [], - ), - returnValue: _i8.Future<_i15.NativeAppStart?>.value(), - ) as _i8.Future<_i15.NativeAppStart?>); - - @override - _i8.Future captureEnvelope( - _i16.Uint8List? envelopeData, - bool? containsUnhandledException, - ) => - (super.noSuchMethod( - Invocation.method( - #captureEnvelope, - [ - envelopeData, - containsUnhandledException, - ], - ), - returnValue: _i8.Future.value(), - returnValueForMissingStub: _i8.Future.value(), - ) as _i8.Future); - - @override - _i8.Future beginNativeFrames() => (super.noSuchMethod( - Invocation.method( - #beginNativeFrames, - [], - ), - returnValue: _i8.Future.value(), - returnValueForMissingStub: _i8.Future.value(), - ) as _i8.Future); - - @override - _i8.Future<_i17.NativeFrames?> endNativeFrames(_i3.SentryId? id) => - (super.noSuchMethod( - Invocation.method( - #endNativeFrames, - [id], - ), - returnValue: _i8.Future<_i17.NativeFrames?>.value(), - ) as _i8.Future<_i17.NativeFrames?>); - - @override - _i8.Future setUser(_i3.SentryUser? user) => (super.noSuchMethod( - Invocation.method( - #setUser, - [user], - ), - returnValue: _i8.Future.value(), - returnValueForMissingStub: _i8.Future.value(), - ) as _i8.Future); - - @override - _i8.Future addBreadcrumb(_i3.Breadcrumb? breadcrumb) => - (super.noSuchMethod( - Invocation.method( - #addBreadcrumb, - [breadcrumb], - ), - returnValue: _i8.Future.value(), - returnValueForMissingStub: _i8.Future.value(), - ) as _i8.Future); - - @override - _i8.Future clearBreadcrumbs() => (super.noSuchMethod( - Invocation.method( - #clearBreadcrumbs, - [], - ), - returnValue: _i8.Future.value(), - returnValueForMissingStub: _i8.Future.value(), - ) as _i8.Future); - - @override - _i8.Future?> loadContexts() => (super.noSuchMethod( - Invocation.method( - #loadContexts, - [], - ), - returnValue: _i8.Future?>.value(), - ) as _i8.Future?>); - - @override - _i8.Future setContexts( - String? key, - dynamic value, - ) => - (super.noSuchMethod( - Invocation.method( - #setContexts, - [ - key, - value, - ], - ), - returnValue: _i8.Future.value(), - returnValueForMissingStub: _i8.Future.value(), - ) as _i8.Future); - - @override - _i8.Future removeContexts(String? key) => (super.noSuchMethod( - Invocation.method( - #removeContexts, - [key], - ), - returnValue: _i8.Future.value(), - returnValueForMissingStub: _i8.Future.value(), - ) as _i8.Future); - - @override - _i8.Future setExtra( - String? key, - dynamic value, - ) => - (super.noSuchMethod( - Invocation.method( - #setExtra, - [ - key, - value, - ], - ), - returnValue: _i8.Future.value(), - returnValueForMissingStub: _i8.Future.value(), - ) as _i8.Future); - - @override - _i8.Future removeExtra(String? key) => (super.noSuchMethod( - Invocation.method( - #removeExtra, - [key], - ), - returnValue: _i8.Future.value(), - returnValueForMissingStub: _i8.Future.value(), - ) as _i8.Future); - - @override - _i8.Future setTag( - String? key, - String? value, - ) => - (super.noSuchMethod( - Invocation.method( - #setTag, - [ - key, - value, - ], - ), - returnValue: _i8.Future.value(), - returnValueForMissingStub: _i8.Future.value(), - ) as _i8.Future); - - @override - _i8.Future removeTag(String? key) => (super.noSuchMethod( - Invocation.method( - #removeTag, - [key], - ), - returnValue: _i8.Future.value(), - returnValueForMissingStub: _i8.Future.value(), - ) as _i8.Future); - - @override - int? startProfiler(_i3.SentryId? traceId) => - (super.noSuchMethod(Invocation.method( - #startProfiler, - [traceId], - )) as int?); - - @override - _i8.Future discardProfiler(_i3.SentryId? traceId) => - (super.noSuchMethod( - Invocation.method( - #discardProfiler, - [traceId], - ), - returnValue: _i8.Future.value(), - returnValueForMissingStub: _i8.Future.value(), - ) as _i8.Future); - - @override - _i8.Future displayRefreshRate() => (super.noSuchMethod( - Invocation.method( - #displayRefreshRate, - [], - ), - returnValue: _i8.Future.value(), - ) as _i8.Future); - - @override - _i8.Future?> collectProfile( - _i3.SentryId? traceId, - int? startTimeNs, - int? endTimeNs, - ) => - (super.noSuchMethod( - Invocation.method( - #collectProfile, - [ - traceId, - startTimeNs, - endTimeNs, - ], - ), - returnValue: _i8.Future?>.value(), - ) as _i8.Future?>); - - @override - _i8.Future?> loadDebugImages() => (super.noSuchMethod( - Invocation.method( - #loadDebugImages, - [], - ), - returnValue: _i8.Future?>.value(), - ) as _i8.Future?>); - - @override - _i8.Future pauseAppHangTracking() => (super.noSuchMethod( - Invocation.method( - #pauseAppHangTracking, - [], - ), - returnValue: _i8.Future.value(), - returnValueForMissingStub: _i8.Future.value(), - ) as _i8.Future); - - @override - _i8.Future resumeAppHangTracking() => (super.noSuchMethod( - Invocation.method( - #resumeAppHangTracking, - [], - ), - returnValue: _i8.Future.value(), - returnValueForMissingStub: _i8.Future.value(), - ) as _i8.Future); -} - /// A class which mocks [Hub]. /// /// See the documentation for Mockito's code generation for more information. @@ -1365,15 +1050,6 @@ class MockHub extends _i1.Mock implements _i2.Hub { ), ) as _i2.SentryOptions); - @override - _i7.MetricsApi get metricsApi => (super.noSuchMethod( - Invocation.getter(#metricsApi), - returnValue: _FakeMetricsApi_11( - this, - Invocation.getter(#metricsApi), - ), - ) as _i7.MetricsApi); - @override bool get isEnabled => (super.noSuchMethod( Invocation.getter(#isEnabled), @@ -1392,14 +1068,14 @@ class MockHub extends _i1.Mock implements _i2.Hub { @override _i2.Scope get scope => (super.noSuchMethod( Invocation.getter(#scope), - returnValue: _FakeScope_12( + returnValue: _FakeScope_11( this, Invocation.getter(#scope), ), ) as _i2.Scope); @override - set profilerFactory(_i11.SentryProfilerFactory? value) => super.noSuchMethod( + set profilerFactory(_i10.SentryProfilerFactory? value) => super.noSuchMethod( Invocation.setter( #profilerFactory, value, @@ -1408,7 +1084,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { ); @override - _i8.Future<_i3.SentryId> captureEvent( + _i7.Future<_i3.SentryId> captureEvent( _i3.SentryEvent? event, { dynamic stackTrace, _i2.Hint? hint, @@ -1424,7 +1100,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { #withScope: withScope, }, ), - returnValue: _i8.Future<_i3.SentryId>.value(_FakeSentryId_5( + returnValue: _i7.Future<_i3.SentryId>.value(_FakeSentryId_5( this, Invocation.method( #captureEvent, @@ -1436,10 +1112,10 @@ class MockHub extends _i1.Mock implements _i2.Hub { }, ), )), - ) as _i8.Future<_i3.SentryId>); + ) as _i7.Future<_i3.SentryId>); @override - _i8.Future<_i3.SentryId> captureException( + _i7.Future<_i3.SentryId> captureException( dynamic throwable, { dynamic stackTrace, _i2.Hint? hint, @@ -1455,7 +1131,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { #withScope: withScope, }, ), - returnValue: _i8.Future<_i3.SentryId>.value(_FakeSentryId_5( + returnValue: _i7.Future<_i3.SentryId>.value(_FakeSentryId_5( this, Invocation.method( #captureException, @@ -1467,10 +1143,10 @@ class MockHub extends _i1.Mock implements _i2.Hub { }, ), )), - ) as _i8.Future<_i3.SentryId>); + ) as _i7.Future<_i3.SentryId>); @override - _i8.Future<_i3.SentryId> captureMessage( + _i7.Future<_i3.SentryId> captureMessage( String? message, { _i3.SentryLevel? level, String? template, @@ -1490,7 +1166,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { #withScope: withScope, }, ), - returnValue: _i8.Future<_i3.SentryId>.value(_FakeSentryId_5( + returnValue: _i7.Future<_i3.SentryId>.value(_FakeSentryId_5( this, Invocation.method( #captureMessage, @@ -1504,21 +1180,21 @@ class MockHub extends _i1.Mock implements _i2.Hub { }, ), )), - ) as _i8.Future<_i3.SentryId>); + ) as _i7.Future<_i3.SentryId>); @override - _i8.Future captureUserFeedback(_i2.SentryUserFeedback? userFeedback) => + _i7.Future captureUserFeedback(_i2.SentryUserFeedback? userFeedback) => (super.noSuchMethod( Invocation.method( #captureUserFeedback, [userFeedback], ), - returnValue: _i8.Future.value(), - returnValueForMissingStub: _i8.Future.value(), - ) as _i8.Future); + returnValue: _i7.Future.value(), + returnValueForMissingStub: _i7.Future.value(), + ) as _i7.Future); @override - _i8.Future addBreadcrumb( + _i7.Future addBreadcrumb( _i3.Breadcrumb? crumb, { _i2.Hint? hint, }) => @@ -1528,9 +1204,9 @@ class MockHub extends _i1.Mock implements _i2.Hub { [crumb], {#hint: hint}, ), - returnValue: _i8.Future.value(), - returnValueForMissingStub: _i8.Future.value(), - ) as _i8.Future); + returnValue: _i7.Future.value(), + returnValueForMissingStub: _i7.Future.value(), + ) as _i7.Future); @override void bindClient(_i2.SentryClient? client) => super.noSuchMethod( @@ -1547,7 +1223,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { #clone, [], ), - returnValue: _FakeHub_13( + returnValue: _FakeHub_12( this, Invocation.method( #clone, @@ -1557,21 +1233,21 @@ class MockHub extends _i1.Mock implements _i2.Hub { ) as _i2.Hub); @override - _i8.Future close() => (super.noSuchMethod( + _i7.Future close() => (super.noSuchMethod( Invocation.method( #close, [], ), - returnValue: _i8.Future.value(), - returnValueForMissingStub: _i8.Future.value(), - ) as _i8.Future); + returnValue: _i7.Future.value(), + returnValueForMissingStub: _i7.Future.value(), + ) as _i7.Future); @override - _i8.FutureOr configureScope(_i2.ScopeCallback? callback) => + _i7.FutureOr configureScope(_i2.ScopeCallback? callback) => (super.noSuchMethod(Invocation.method( #configureScope, [callback], - )) as _i8.FutureOr); + )) as _i7.FutureOr); @override _i2.ISentrySpan startTransaction( @@ -1604,7 +1280,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { #customSamplingContext: customSamplingContext, }, ), - returnValue: _i18.startTransactionShim( + returnValue: _i12.startTransactionShim( name, operation, description: description, @@ -1662,7 +1338,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { ) as _i2.ISentrySpan); @override - _i8.Future<_i3.SentryId> captureTransaction( + _i7.Future<_i3.SentryId> captureTransaction( _i3.SentryTransaction? transaction, { _i2.SentryTraceContextHeader? traceContext, }) => @@ -1672,7 +1348,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { [transaction], {#traceContext: traceContext}, ), - returnValue: _i8.Future<_i3.SentryId>.value(_FakeSentryId_5( + returnValue: _i7.Future<_i3.SentryId>.value(_FakeSentryId_5( this, Invocation.method( #captureTransaction, @@ -1680,24 +1356,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { {#traceContext: traceContext}, ), )), - ) as _i8.Future<_i3.SentryId>); - - @override - _i8.Future<_i3.SentryId> captureMetrics( - Map>? metricsBuckets) => - (super.noSuchMethod( - Invocation.method( - #captureMetrics, - [metricsBuckets], - ), - returnValue: _i8.Future<_i3.SentryId>.value(_FakeSentryId_5( - this, - Invocation.method( - #captureMetrics, - [metricsBuckets], - ), - )), - ) as _i8.Future<_i3.SentryId>); + ) as _i7.Future<_i3.SentryId>); @override void setSpanContext( diff --git a/flutter/test/native_scope_observer_test.dart b/flutter/test/native_scope_observer_test.dart index 9d7a8fd2a9..980449b11f 100644 --- a/flutter/test/native_scope_observer_test.dart +++ b/flutter/test/native_scope_observer_test.dart @@ -2,75 +2,98 @@ library flutter_test; import 'package:flutter_test/flutter_test.dart'; -import 'package:mockito/mockito.dart'; import 'package:sentry/sentry.dart'; import 'package:sentry_flutter/src/native/native_scope_observer.dart'; -import 'mocks.mocks.dart'; +import 'mocks.dart'; void main() { - late MockSentryNativeBinding mock; - late NativeScopeObserver sut; + late Fixture fixture; setUp(() { - mock = MockSentryNativeBinding(); - sut = NativeScopeObserver(mock); + fixture = Fixture(); }); test('addBreadcrumbCalls', () async { + final sut = fixture.getSut(); final breadcrumb = Breadcrumb(); await sut.addBreadcrumb(breadcrumb); - expect(verify(mock.addBreadcrumb(captureAny)).captured.single, breadcrumb); + expect(fixture.mock.breadcrumb, breadcrumb); + expect(fixture.mock.numberOfAddBreadcrumbCalls, 1); }); test('clearBreadcrumbsCalls', () async { + final sut = fixture.getSut(); await sut.clearBreadcrumbs(); - verify(mock.clearBreadcrumbs()).called(1); + expect(fixture.mock.numberOfClearBreadcrumbsCalls, 1); }); test('removeContextsCalls', () async { + final sut = fixture.getSut(); await sut.removeContexts('fixture-key'); - expect( - verify(mock.removeContexts(captureAny)).captured.single, 'fixture-key'); + expect(fixture.mock.removeContextsKey, 'fixture-key'); + expect(fixture.mock.numberOfRemoveContextsCalls, 1); }); test('removeExtraCalls', () async { + final sut = fixture.getSut(); await sut.removeExtra('fixture-key'); - expect(verify(mock.removeExtra(captureAny)).captured.single, 'fixture-key'); + expect(fixture.mock.removeExtraKey, 'fixture-key'); + expect(fixture.mock.numberOfRemoveExtraCalls, 1); }); test('removeTagCalls', () async { + final sut = fixture.getSut(); await sut.removeTag('fixture-key'); - expect(verify(mock.removeTag(captureAny)).captured.single, 'fixture-key'); + expect(fixture.mock.removeTagKey, 'fixture-key'); + expect(fixture.mock.numberOfRemoveTagCalls, 1); }); test('setContextsCalls', () async { + final sut = fixture.getSut(); await sut.setContexts('fixture-key', 'fixture-value'); - verify(mock.setContexts('fixture-key', 'fixture-value')).called(1); + expect(fixture.mock.setContextData['fixture-key'], 'fixture-value'); + expect(fixture.mock.numberOfSetContextsCalls, 1); }); test('setExtraCalls', () async { + final sut = fixture.getSut(); await sut.setExtra('fixture-key', 'fixture-value'); - verify(mock.setExtra('fixture-key', 'fixture-value')).called(1); + expect(fixture.mock.setExtraData['fixture-key'], 'fixture-value'); + expect(fixture.mock.numberOfSetExtraCalls, 1); }); test('setTagCalls', () async { + final sut = fixture.getSut(); await sut.setTag('fixture-key', 'fixture-value'); - verify(mock.setTag('fixture-key', 'fixture-value')).called(1); + expect(fixture.mock.setTagsData['fixture-key'], 'fixture-value'); + expect(fixture.mock.numberOfSetTagCalls, 1); }); test('setUserCalls', () async { + final sut = fixture.getSut(); + final user = SentryUser(id: 'foo bar'); await sut.setUser(user); - expect(verify(mock.setUser(captureAny)).captured.single, user); + expect(fixture.mock.sentryUser, user); + expect(fixture.mock.numberOfSetUserCalls, 1); }); } + +class Fixture { + var mock = TestMockSentryNative(); + + NativeScopeObserver getSut() { + final sut = NativeScopeObserver(mock); + return sut; + } +} diff --git a/flutter/test/navigation/sentry_display_widget_test.dart b/flutter/test/navigation/sentry_display_widget_test.dart index a0495bfe8d..2cafb706d5 100644 --- a/flutter/test/navigation/sentry_display_widget_test.dart +++ b/flutter/test/navigation/sentry_display_widget_test.dart @@ -108,6 +108,7 @@ class Fixture { final fakeFrameCallbackHandler = FakeFrameCallbackHandler(); Fixture() { + SentryFlutter.native = TestMockSentryNative(); navigatorObserver = SentryNavigatorObserver(hub: hub); } diff --git a/flutter/test/navigation/time_to_display_tracker_test.dart b/flutter/test/navigation/time_to_display_tracker_test.dart index 975adb37fd..ca9d0425a0 100644 --- a/flutter/test/navigation/time_to_display_tracker_test.dart +++ b/flutter/test/navigation/time_to_display_tracker_test.dart @@ -52,6 +52,7 @@ void main() { }); test('finishes ttid span', () async { + SentryFlutter.native = TestMockSentryNative(); final sut = fixture.getSut(); final endTimestamp = fixture.startTimestamp.add(const Duration(milliseconds: 10)); @@ -227,6 +228,7 @@ void main() { test('does not create ttfd span when not enabled', () async { fixture.options.enableTimeToFullDisplayTracing = false; + SentryFlutter.native = TestMockSentryNative(); final sut = fixture.getSut(); final transaction = fixture.getTransaction() as SentryTracer; diff --git a/flutter/test/profiling_test.dart b/flutter/test/profiling_test.dart index 04ff70d065..adf88e0f2e 100644 --- a/flutter/test/profiling_test.dart +++ b/flutter/test/profiling_test.dart @@ -10,13 +10,6 @@ import 'mocks.mocks.dart'; import 'sentry_flutter_test.dart'; void main() { - late MockSentryNativeBinding mock; - - setUp(() { - mock = MockSentryNativeBinding(); - when(mock.startProfiler(any)).thenReturn(1); - }); - group('$SentryNativeProfilerFactory', () { Hub hubWithSampleRate(double profilesSampleRate) { final o = SentryFlutterOptions(dsn: fakeDsn); @@ -30,39 +23,42 @@ void main() { test('attachTo() respects sampling rate', () async { var hub = hubWithSampleRate(0.0); - SentryNativeProfilerFactory.attachTo(hub, mock); + SentryNativeProfilerFactory.attachTo(hub, TestMockSentryNative()); // ignore: invalid_use_of_internal_member verifyNever(hub.profilerFactory = any); hub = hubWithSampleRate(0.1); - SentryNativeProfilerFactory.attachTo(hub, mock); + SentryNativeProfilerFactory.attachTo(hub, TestMockSentryNative()); // ignore: invalid_use_of_internal_member verify(hub.profilerFactory = any); }); test('creates a profiler', () async { + final nativeMock = TestMockSentryNative(); // ignore: invalid_use_of_internal_member - final sut = SentryNativeProfilerFactory(mock, getUtcDateTime); + final sut = SentryNativeProfilerFactory(nativeMock, getUtcDateTime); final profiler = sut.startProfiler(SentryTransactionContext( 'name', 'op', )); - verify(mock.startProfiler(any)).called(1); + expect(nativeMock.numberOfStartProfilerCalls, 1); expect(profiler, isNotNull); }); }); group('$SentryNativeProfiler', () { + late TestMockSentryNative nativeMock; late SentryNativeProfiler sut; setUp(() { + nativeMock = TestMockSentryNative(); // ignore: invalid_use_of_internal_member - final factory = SentryNativeProfilerFactory(mock, getUtcDateTime); + final factory = SentryNativeProfilerFactory(nativeMock, getUtcDateTime); final profiler = factory.startProfiler(SentryTransactionContext( 'name', 'op', )); - verify(mock.startProfiler(any)).called(1); + expect(nativeMock.numberOfStartProfilerCalls, 1); expect(profiler, isNotNull); sut = profiler!; }); @@ -75,15 +71,14 @@ void main() { await null; await null; - verify(mock.discardProfiler(any)).called(1); + expect(nativeMock.numberOfDiscardProfilerCalls, 1); // finishFor() mustn't work after disposing expect(await sut.finishFor(MockSentryTransaction()), isNull); - verifyNever(mock.collectProfile(any, any, any)); + expect(nativeMock.numberOfCollectProfileCalls, 0); }); test('dispose() does not call discard() after finishing', () async { - when(mock.collectProfile(any, any, any)).thenAnswer((_) async => null); final mockTransaction = MockSentryTransaction(); when(mockTransaction.startTimestamp).thenReturn(DateTime.now()); when(mockTransaction.timestamp).thenReturn(DateTime.now()); @@ -94,8 +89,8 @@ void main() { // Yield to let the .then() in .dispose() execute. await null; - verifyNever(mock.discardProfiler(any)); - verify(mock.collectProfile(any, any, any)).called(1); + expect(nativeMock.numberOfDiscardProfilerCalls, 0); + expect(nativeMock.numberOfCollectProfileCalls, 1); }); }); } diff --git a/flutter/test/sentry_flutter_test.dart b/flutter/test/sentry_flutter_test.dart index 3987cdfb7e..e06938da90 100644 --- a/flutter/test/sentry_flutter_test.dart +++ b/flutter/test/sentry_flutter_test.dart @@ -1,9 +1,7 @@ // ignore_for_file: invalid_use_of_internal_member import 'package:flutter_test/flutter_test.dart'; -import 'package:mockito/mockito.dart'; import 'package:package_info_plus/package_info_plus.dart'; -import 'package:sentry/src/platform/platform.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:sentry_flutter/src/integrations/connectivity/connectivity_integration.dart'; import 'package:sentry_flutter/src/integrations/integrations.dart'; @@ -625,40 +623,6 @@ void main() { await Sentry.close(); }); }); - - test('resumeAppHangTracking calls native method when available', () async { - SentryFlutter.native = MockSentryNativeBinding(); - when(SentryFlutter.native?.resumeAppHangTracking()) - .thenAnswer((_) => Future.value()); - - await SentryFlutter.resumeAppHangTracking(); - - verify(SentryFlutter.native?.resumeAppHangTracking()).called(1); - }); - - test('resumeAppHangTracking does nothing when native is null', () async { - SentryFlutter.native = null; - - // This should complete without throwing an error - await expectLater(SentryFlutter.resumeAppHangTracking(), completes); - }); - - test('pauseAppHangTracking calls native method when available', () async { - SentryFlutter.native = MockSentryNativeBinding(); - when(SentryFlutter.native?.pauseAppHangTracking()) - .thenAnswer((_) => Future.value()); - - await SentryFlutter.pauseAppHangTracking(); - - verify(SentryFlutter.native?.pauseAppHangTracking()).called(1); - }); - - test('pauseAppHangTracking does nothing when native is null', () async { - SentryFlutter.native = null; - - // This should complete without throwing an error - await expectLater(SentryFlutter.pauseAppHangTracking(), completes); - }); } void appRunner() {} @@ -675,7 +639,7 @@ void loadTestPackage() { } PlatformChecker getPlatformChecker({ - required Platform platform, + required MockPlatform platform, bool isWeb = false, }) { final platformChecker = PlatformChecker( diff --git a/flutter/test/sentry_native_channel_test.dart b/flutter/test/sentry_native_channel_test.dart index 5ad5eb2b3f..050693cc8a 100644 --- a/flutter/test/sentry_native_channel_test.dart +++ b/flutter/test/sentry_native_channel_test.dart @@ -3,305 +3,242 @@ @TestOn('vm') library flutter_test; -import 'dart:typed_data'; - import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/mockito.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; -import 'package:sentry_flutter/src/native/factory.dart'; import 'package:sentry_flutter/src/native/method_channel_helper.dart'; -import 'package:sentry_flutter/src/native/sentry_native_binding.dart'; -import 'package:sentry/src/platform/platform.dart' as platform; -import 'mocks.dart'; +import 'package:sentry_flutter/src/native/sentry_native.dart'; +import 'package:sentry_flutter/src/native/sentry_native_channel.dart'; import 'mocks.mocks.dart'; -import 'sentry_flutter_test.dart'; void main() { - for (var mockPlatform in [ - MockPlatform.android(), - MockPlatform.iOs(), - MockPlatform.macOs() - ]) { - group('$SentryNativeBinding', () { - late SentryNativeBinding sut; - late MockMethodChannel channel; - - setUp(() { - final options = SentryFlutterOptions( - dsn: fakeDsn, checker: getPlatformChecker(platform: mockPlatform)) - // ignore: invalid_use_of_internal_member - ..automatedTestMode = true; - channel = MockMethodChannel(); - sut = createBinding(options, channel: channel); - }); - - // TODO move other methods here, e.g. init_native_sdk_test.dart - - test('fetchNativeAppStart', () async { - when(channel.invokeMethod('fetchNativeAppStart')) - .thenAnswer((_) async => { - 'pluginRegistrationTime': 1, - 'appStartTime': 0.1, - 'isColdStart': true, - // ignore: inference_failure_on_collection_literal - 'nativeSpanTimes': {}, - }); - - final actual = await sut.fetchNativeAppStart(); - - expect(actual?.appStartTime, 0.1); - expect(actual?.isColdStart, true); - }); - - test('beginNativeFrames', () async { - when(channel.invokeMethod('beginNativeFrames')) - .thenAnswer((realInvocation) async {}); - await sut.beginNativeFrames(); - - verify(channel.invokeMethod('beginNativeFrames')); - }); - - test('endNativeFrames', () async { - final sentryId = SentryId.empty(); - - when(channel - .invokeMethod('endNativeFrames', {'id': sentryId.toString()})) - .thenAnswer((_) async => { - 'totalFrames': 3, - 'slowFrames': 2, - 'frozenFrames': 1, - }); - - final actual = await sut.endNativeFrames(sentryId); - - expect(actual?.totalFrames, 3); - expect(actual?.slowFrames, 2); - expect(actual?.frozenFrames, 1); - }); - - test('setUser', () async { - final user = SentryUser( - id: "fixture-id", - data: {'object': Object()}, - ); - final normalizedUser = user.copyWith( - data: MethodChannelHelper.normalizeMap(user.data), - ); - when(channel.invokeMethod('setUser', {'user': normalizedUser.toJson()})) - .thenAnswer((_) => Future.value()); - - await sut.setUser(user); - - verify( - channel.invokeMethod('setUser', {'user': normalizedUser.toJson()})); - }); - - test('addBreadcrumb', () async { - final breadcrumb = Breadcrumb( - data: {'object': Object()}, - ); - final normalizedBreadcrumb = breadcrumb.copyWith( - data: MethodChannelHelper.normalizeMap(breadcrumb.data)); - - when(channel.invokeMethod( - 'addBreadcrumb', {'breadcrumb': normalizedBreadcrumb.toJson()})) - .thenAnswer((_) => Future.value()); - - await sut.addBreadcrumb(breadcrumb); - - verify(channel.invokeMethod( - 'addBreadcrumb', {'breadcrumb': normalizedBreadcrumb.toJson()})); - }); - - test('clearBreadcrumbs', () async { - when(channel.invokeMethod('clearBreadcrumbs')) - .thenAnswer((_) => Future.value()); - - await sut.clearBreadcrumbs(); - - verify(channel.invokeMethod('clearBreadcrumbs')); - }); - - test('setContexts', () async { - final value = {'object': Object()}; - final normalizedValue = MethodChannelHelper.normalize(value); - when(channel.invokeMethod('setContexts', { - 'key': 'fixture-key', - 'value': normalizedValue - })).thenAnswer((_) => Future.value()); - - await sut.setContexts('fixture-key', value); - - verify(channel.invokeMethod( - 'setContexts', {'key': 'fixture-key', 'value': normalizedValue})); - }); - - test('removeContexts', () async { - when(channel.invokeMethod('removeContexts', {'key': 'fixture-key'})) - .thenAnswer((_) => Future.value()); - - await sut.removeContexts('fixture-key'); - - verify(channel.invokeMethod('removeContexts', {'key': 'fixture-key'})); - }); - - test('setExtra', () async { - final value = {'object': Object()}; - final normalizedValue = MethodChannelHelper.normalize(value); - when(channel.invokeMethod( - 'setExtra', {'key': 'fixture-key', 'value': normalizedValue})) - .thenAnswer((_) => Future.value()); - - await sut.setExtra('fixture-key', value); - - verify(channel.invokeMethod( - 'setExtra', {'key': 'fixture-key', 'value': normalizedValue})); - }); - - test('removeExtra', () async { - when(channel.invokeMethod('removeExtra', {'key': 'fixture-key'})) - .thenAnswer((_) => Future.value()); - - await sut.removeExtra('fixture-key'); - - verify(channel.invokeMethod('removeExtra', {'key': 'fixture-key'})); - }); - - test('setTag', () async { - when(channel.invokeMethod( - 'setTag', {'key': 'fixture-key', 'value': 'fixture-value'})) - .thenAnswer((_) => Future.value()); - - await sut.setTag('fixture-key', 'fixture-value'); - - verify(channel.invokeMethod( - 'setTag', {'key': 'fixture-key', 'value': 'fixture-value'})); - }); - - test('removeTag', () async { - when(channel.invokeMethod('removeTag', {'key': 'fixture-key'})) - .thenAnswer((_) => Future.value()); - - await sut.removeTag('fixture-key'); - - verify(channel.invokeMethod('removeTag', {'key': 'fixture-key'})); - }); - - test('startProfiler', () { - late Matcher matcher; - if (mockPlatform.isAndroid) { - matcher = throwsUnsupportedError; - } else if (mockPlatform.isIOS || mockPlatform.isMacOS) { - if (platform.instance.isMacOS) { - matcher = throwsA(predicate((e) => - e is Exception && - e.toString().contains('Failed to load Objective-C class'))); - } else { - matcher = throwsA(predicate((e) => - e is ArgumentError && - e.toString().contains('Failed to lookup symbol'))); - } - } - expect(() => sut.startProfiler(SentryId.newId()), matcher); - - verifyZeroInteractions(channel); - }); - - test('discardProfiler', () async { - final traceId = SentryId.newId(); - when(channel.invokeMethod('discardProfiler', traceId.toString())) - .thenAnswer((_) async {}); - - await sut.discardProfiler(traceId); - - verify(channel.invokeMethod('discardProfiler', traceId.toString())); - }); - - test('collectProfile', () async { - final traceId = SentryId.newId(); - const startTime = 42; - const endTime = 50; - when(channel.invokeMethod('collectProfile', { - 'traceId': traceId.toString(), - 'startTime': startTime, - 'endTime': endTime, - })).thenAnswer((_) async => {}); - - await sut.collectProfile(traceId, startTime, endTime); - - verify(channel.invokeMethod('collectProfile', { - 'traceId': traceId.toString(), - 'startTime': startTime, - 'endTime': endTime, - })); - }); - - test('captureEnvelope', () async { - final data = Uint8List.fromList([1, 2, 3]); - - late Uint8List captured; - when(channel.invokeMethod('captureEnvelope', any)).thenAnswer( - (invocation) async => - {captured = invocation.positionalArguments[1][0] as Uint8List}); - - await sut.captureEnvelope(data, false); - - expect(captured, data); - }); - - test('loadContexts', () async { - when(channel.invokeMethod('loadContexts')) - .thenAnswer((invocation) async => { - 'foo': [1, 2, 3], - 'bar': {'a': 'b'}, - }); - - final data = await sut.loadContexts(); - - expect(data, { - 'foo': [1, 2, 3], - 'bar': {'a': 'b'}, - }); - }); - - test('loadDebugImages', () async { - final json = [ - { - 'code_file': '/apex/com.android.art/javalib/arm64/boot.oat', - 'code_id': '13577ce71153c228ecf0eb73fc39f45010d487f8', - 'image_addr': '0x6f80b000', - 'image_size': 3092480, - 'type': 'elf', - 'debug_id': 'e77c5713-5311-28c2-ecf0-eb73fc39f450', - 'debug_file': 'test' - } - ]; - - when(channel.invokeMethod('loadImageList')) - .thenAnswer((invocation) async => json); - - final data = await sut.loadDebugImages(); - - expect(data?.map((v) => v.toJson()), json); - }); - - test('pauseAppHangTracking', () async { - when(channel.invokeMethod('pauseAppHangTracking')) - .thenAnswer((_) => Future.value()); - - await sut.pauseAppHangTracking(); - - verify(channel.invokeMethod('pauseAppHangTracking')); - }); - - test('resumeAppHangTracking', () async { - when(channel.invokeMethod('resumeAppHangTracking')) - .thenAnswer((_) => Future.value()); - - await sut.resumeAppHangTracking(); - - verify(channel.invokeMethod('resumeAppHangTracking')); - }); + group('$SentryNative', () { + late Fixture fixture; + + setUp(() { + fixture = Fixture(); + }); + + test('fetchNativeAppStart', () async { + final map = { + 'pluginRegistrationTime': 1, + 'appStartTime': 0.1, + 'isColdStart': true, + // ignore: inference_failure_on_collection_literal + 'nativeSpanTimes': {}, + }; + final future = Future.value(map); + + when(fixture.methodChannel + .invokeMapMethod('fetchNativeAppStart')) + .thenAnswer((_) => future); + + final sut = fixture.getSut(); + final actual = await sut.fetchNativeAppStart(); + + expect(actual?.appStartTime, 0.1); + expect(actual?.isColdStart, true); + }); + + test('beginNativeFrames', () async { + final sut = fixture.getSut(); + when(fixture.methodChannel.invokeMethod('beginNativeFrames')) + .thenAnswer((realInvocation) async {}); + await sut.beginNativeFrames(); + + verify(fixture.methodChannel.invokeMethod('beginNativeFrames')); + }); + + test('endNativeFrames', () async { + final sentryId = SentryId.empty(); + final map = { + 'totalFrames': 3, + 'slowFrames': 2, + 'frozenFrames': 1 + }; + final future = Future.value(map); + + when(fixture.methodChannel.invokeMapMethod( + 'endNativeFrames', {'id': sentryId.toString()})) + .thenAnswer((_) => future); + + final sut = fixture.getSut(); + final actual = await sut.endNativeFrames(sentryId); + + expect(actual?.totalFrames, 3); + expect(actual?.slowFrames, 2); + expect(actual?.frozenFrames, 1); + }); + + test('setUser', () async { + final user = SentryUser( + id: "fixture-id", + data: {'object': Object()}, + ); + final normalizedUser = user.copyWith( + data: MethodChannelHelper.normalizeMap(user.data), + ); + when(fixture.methodChannel + .invokeMethod('setUser', {'user': normalizedUser.toJson()})) + .thenAnswer((_) => Future.value()); + + final sut = fixture.getSut(); + await sut.setUser(user); + + verify(fixture.methodChannel + .invokeMethod('setUser', {'user': normalizedUser.toJson()})); + }); + + test('addBreadcrumb', () async { + final breadcrumb = Breadcrumb( + data: {'object': Object()}, + ); + final normalizedBreadcrumb = breadcrumb.copyWith( + data: MethodChannelHelper.normalizeMap(breadcrumb.data)); + + when(fixture.methodChannel.invokeMethod( + 'addBreadcrumb', {'breadcrumb': normalizedBreadcrumb.toJson()})) + .thenAnswer((_) => Future.value()); + + final sut = fixture.getSut(); + await sut.addBreadcrumb(breadcrumb); + + verify(fixture.methodChannel.invokeMethod( + 'addBreadcrumb', {'breadcrumb': normalizedBreadcrumb.toJson()})); + }); + + test('clearBreadcrumbs', () async { + when(fixture.methodChannel.invokeMethod('clearBreadcrumbs')) + .thenAnswer((_) => Future.value()); + + final sut = fixture.getSut(); + await sut.clearBreadcrumbs(); + + verify(fixture.methodChannel.invokeMethod('clearBreadcrumbs')); + }); + + test('setContexts', () async { + final value = {'object': Object()}; + final normalizedValue = MethodChannelHelper.normalize(value); + when(fixture.methodChannel.invokeMethod( + 'setContexts', {'key': 'fixture-key', 'value': normalizedValue})) + .thenAnswer((_) => Future.value()); + + final sut = fixture.getSut(); + await sut.setContexts('fixture-key', value); + + verify(fixture.methodChannel.invokeMethod( + 'setContexts', {'key': 'fixture-key', 'value': normalizedValue})); + }); + + test('removeContexts', () async { + when(fixture.methodChannel + .invokeMethod('removeContexts', {'key': 'fixture-key'})) + .thenAnswer((_) => Future.value()); + + final sut = fixture.getSut(); + await sut.removeContexts('fixture-key'); + + verify(fixture.methodChannel + .invokeMethod('removeContexts', {'key': 'fixture-key'})); }); + + test('setExtra', () async { + final value = {'object': Object()}; + final normalizedValue = MethodChannelHelper.normalize(value); + when(fixture.methodChannel.invokeMethod( + 'setExtra', {'key': 'fixture-key', 'value': normalizedValue})) + .thenAnswer((_) => Future.value()); + + final sut = fixture.getSut(); + await sut.setExtra('fixture-key', value); + + verify(fixture.methodChannel.invokeMethod( + 'setExtra', {'key': 'fixture-key', 'value': normalizedValue})); + }); + + test('removeExtra', () async { + when(fixture.methodChannel + .invokeMethod('removeExtra', {'key': 'fixture-key'})) + .thenAnswer((_) => Future.value()); + + final sut = fixture.getSut(); + await sut.removeExtra('fixture-key'); + + verify(fixture.methodChannel + .invokeMethod('removeExtra', {'key': 'fixture-key'})); + }); + + test('setTag', () async { + when(fixture.methodChannel.invokeMethod( + 'setTag', {'key': 'fixture-key', 'value': 'fixture-value'})) + .thenAnswer((_) => Future.value()); + + final sut = fixture.getSut(); + await sut.setTag('fixture-key', 'fixture-value'); + + verify(fixture.methodChannel.invokeMethod( + 'setTag', {'key': 'fixture-key', 'value': 'fixture-value'})); + }); + + test('removeTag', () async { + when(fixture.methodChannel + .invokeMethod('removeTag', {'key': 'fixture-key'})) + .thenAnswer((_) => Future.value()); + + final sut = fixture.getSut(); + await sut.removeTag('fixture-key'); + + verify(fixture.methodChannel + .invokeMethod('removeTag', {'key': 'fixture-key'})); + }); + + test('startProfiler', () { + final sut = fixture.getSut(); + expect(() => sut.startProfiler(SentryId.newId()), throwsUnsupportedError); + verifyZeroInteractions(fixture.methodChannel); + }); + + test('discardProfiler', () async { + final traceId = SentryId.newId(); + when(fixture.methodChannel + .invokeMethod('discardProfiler', traceId.toString())) + .thenAnswer((_) async {}); + + final sut = fixture.getSut(); + await sut.discardProfiler(traceId); + + verify(fixture.methodChannel + .invokeMethod('discardProfiler', traceId.toString())); + }); + + test('collectProfile', () async { + final traceId = SentryId.newId(); + const startTime = 42; + const endTime = 50; + when(fixture.methodChannel + .invokeMapMethod('collectProfile', { + 'traceId': traceId.toString(), + 'startTime': startTime, + 'endTime': endTime, + })).thenAnswer((_) => Future.value()); + + final sut = fixture.getSut(); + await sut.collectProfile(traceId, startTime, endTime); + + verify(fixture.methodChannel.invokeMapMethod('collectProfile', { + 'traceId': traceId.toString(), + 'startTime': startTime, + 'endTime': endTime, + })); + }); + }); +} + +class Fixture { + final methodChannel = MockMethodChannel(); + + SentryNativeChannel getSut() { + return SentryNativeChannel(methodChannel); } } diff --git a/flutter/test/sentry_native_test.dart b/flutter/test/sentry_native_test.dart new file mode 100644 index 0000000000..8d30312f6f --- /dev/null +++ b/flutter/test/sentry_native_test.dart @@ -0,0 +1,120 @@ +@TestOn('vm') +library flutter_test; + +import 'package:flutter_test/flutter_test.dart'; +import 'package:sentry_flutter/sentry_flutter.dart'; +import 'package:sentry_flutter/src/native/sentry_native.dart'; +import 'mocks.dart'; + +void main() { + group('$SentryNative', () { + final channel = MockNativeChannel(); + final options = SentryFlutterOptions(dsn: fakeDsn); + late final sut = SentryNative(options, channel); + + tearDown(() { + sut.reset(); + }); + + test('fetchNativeAppStart sets didFetchAppStart', () async { + final nativeAppStart = NativeAppStart( + appStartTime: 0.0, + pluginRegistrationTime: 10, + isColdStart: true, + nativeSpanTimes: {}); + channel.nativeAppStart = nativeAppStart; + + expect(sut.didFetchAppStart, false); + + final firstCall = await sut.fetchNativeAppStart(); + expect(firstCall, nativeAppStart); + + expect(sut.didFetchAppStart, true); + }); + + test('beginNativeFramesCollection', () async { + await sut.beginNativeFramesCollection(); + expect(channel.numberOfBeginNativeFramesCalls, 1); + }); + + test('endNativeFramesCollection', () async { + final nativeFrames = NativeFrames(3, 2, 1); + final traceId = SentryId.empty(); + channel.nativeFrames = nativeFrames; + + final actual = await sut.endNativeFramesCollection(traceId); + + expect(actual, nativeFrames); + expect(channel.id, traceId); + expect(channel.numberOfEndNativeFramesCalls, 1); + }); + + test('setUser', () async { + await sut.setUser(null); + expect(channel.numberOfSetUserCalls, 1); + }); + + test('addBreadcrumb', () async { + await sut.addBreadcrumb(Breadcrumb()); + expect(channel.numberOfAddBreadcrumbCalls, 1); + }); + + test('clearBreadcrumbs', () async { + await sut.clearBreadcrumbs(); + expect(channel.numberOfClearBreadcrumbCalls, 1); + }); + + test('setContexts', () async { + await sut.setContexts('fixture-key', 'fixture-value'); + expect(channel.numberOfSetContextsCalls, 1); + }); + + test('removeContexts', () async { + await sut.removeContexts('fixture-key'); + expect(channel.numberOfRemoveContextsCalls, 1); + }); + + test('setExtra', () async { + await sut.setExtra('fixture-key', 'fixture-value'); + expect(channel.numberOfSetExtraCalls, 1); + }); + + test('removeExtra', () async { + await sut.removeExtra('fixture-key'); + expect(channel.numberOfRemoveExtraCalls, 1); + }); + + test('setTag', () async { + await sut.setTag('fixture-key', 'fixture-value'); + expect(channel.numberOfSetTagCalls, 1); + }); + + test('removeTag', () async { + await sut.removeTag('fixture-key'); + expect(channel.numberOfRemoveTagCalls, 1); + }); + + test('startProfiler', () async { + sut.startProfiler(SentryId.newId()); + expect(channel.numberOfStartProfilerCalls, 1); + }); + + test('discardProfiler', () async { + await sut.discardProfiler(SentryId.newId()); + expect(channel.numberOfDiscardProfilerCalls, 1); + }); + + test('collectProfile', () async { + await sut.collectProfile(SentryId.newId(), 1, 2); + expect(channel.numberOfCollectProfileCalls, 1); + }); + + test('reset', () async { + sut.appStartEnd = DateTime.now(); + await sut.fetchNativeAppStart(); + sut.reset(); + expect(sut.appStartEnd, null); + expect(sut.didFetchAppStart, false); + }); + }); +} diff --git a/flutter/test/sentry_navigator_observer_test.dart b/flutter/test/sentry_navigator_observer_test.dart index bc9971cb9c..e2b1488cca 100644 --- a/flutter/test/sentry_navigator_observer_test.dart +++ b/flutter/test/sentry_navigator_observer_test.dart @@ -8,8 +8,8 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/mockito.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:sentry_flutter/src/integrations/integrations.dart'; +import 'package:sentry_flutter/src/native/sentry_native.dart'; import 'package:sentry/src/sentry_tracer.dart'; -import 'package:sentry_flutter/src/native/native_frames.dart'; import 'package:sentry_flutter/src/navigation/time_to_display_tracker.dart'; import 'package:sentry_flutter/src/navigation/time_to_initial_display_tracker.dart'; @@ -41,14 +41,16 @@ void main() { setUp(() { fixture = Fixture(); + WidgetsFlutterBinding.ensureInitialized(); }); group('NativeFrames', () { - late MockSentryNativeBinding mockBinding; + late MockNativeChannel mockNativeChannel; setUp(() { - mockBinding = MockSentryNativeBinding(); - SentryFlutter.native = mockBinding; + mockNativeChannel = MockNativeChannel(); + SentryFlutter.native = + SentryNative(SentryFlutterOptions(dsn: fakeDsn), mockNativeChannel); }); tearDown(() { @@ -74,8 +76,9 @@ void main() { await sut.completedDisplayTracking?.future; // Handle internal async method calls. - await Future.delayed(const Duration(milliseconds: 10), () {}); - verify(mockBinding.beginNativeFrames()).called(1); + await Future.delayed(const Duration(milliseconds: 10), () { + expect(mockNativeChannel.numberOfBeginNativeFramesCalls, 1); + }); }); test('transaction finish adds native frames to tracer', () async { @@ -85,8 +88,12 @@ void main() { options.tracesSampleRate = 1; final hub = Hub(options); - when(mockBinding.endNativeFrames(any)) - .thenAnswer((_) async => NativeFrames(3, 2, 1)); + mockNativeChannel = MockNativeChannel(); + SentryFlutter.native = + SentryNative(SentryFlutterOptions(dsn: fakeDsn), mockNativeChannel); + + final nativeFrames = NativeFrames(3, 2, 1); + mockNativeChannel.nativeFrames = nativeFrames; final sut = fixture.getSut(hub: hub); @@ -102,7 +109,7 @@ void main() { // Wait for the transaction to finish the async native frame fetching await Future.delayed(Duration(milliseconds: 1500)); - verify(mockBinding.beginNativeFrames()).called(1); + expect(mockNativeChannel.numberOfEndNativeFramesCalls, 1); final measurements = actualTransaction?.measurements ?? {}; @@ -979,6 +986,8 @@ void main() { } class Fixture { + final mockNativeChannel = MockNativeChannel(); + SentryNavigatorObserver getSut({ required Hub hub, bool enableAutoTransactions = true, diff --git a/flutter/test/span_frame_metrics_collector_test.dart b/flutter/test/span_frame_metrics_collector_test.dart deleted file mode 100644 index 70c3348070..0000000000 --- a/flutter/test/span_frame_metrics_collector_test.dart +++ /dev/null @@ -1,274 +0,0 @@ -import 'package:flutter/cupertino.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:mockito/mockito.dart'; -import 'package:sentry_flutter/sentry_flutter.dart'; -import 'package:sentry_flutter/src/span_frame_metrics_collector.dart'; - -import 'fake_frame_callback_handler.dart'; -import 'mocks.dart'; - -// ignore: implementation_imports -import 'package:sentry/src/sentry_tracer.dart'; - -import 'mocks.mocks.dart'; - -void main() { - late Fixture fixture; - - setUp(() { - fixture = Fixture(); - WidgetsFlutterBinding.ensureInitialized(); - - when(fixture.mockSentryNative.displayRefreshRate()) - .thenAnswer((_) async => 60); - }); - - test('clear() clears frames, running spans and pauses frame tracking', () { - final sut = fixture.sut; - sut.frames[DateTime.now()] = 1; - final mockSpan = MockSentrySpan(); - when(mockSpan.startTimestamp).thenReturn(DateTime.now()); - - sut.onSpanStarted(mockSpan); - sut.clear(); - - expect(sut.frames, isEmpty); - expect(sut.activeSpans, isEmpty); - expect(sut.isTrackingPaused, isTrue); - }); - - test('does not start frame tracking if frames tracking is disabled', () { - final sut = fixture.sut; - fixture.options.enableFramesTracking = false; - - final span = MockSentrySpan(); - sut.onSpanStarted(span); - - expect(sut.isTrackingRegistered, isFalse); - }); - - test( - 'captures metrics with display refresh rate of 60 if native refresh rate is null', - () async { - final sut = fixture.sut; - fixture.options.tracesSampleRate = 1.0; - fixture.options.addPerformanceCollector(sut); - final startTimestamp = DateTime.now(); - final endTimestamp = - startTimestamp.add(Duration(milliseconds: 1000)).toUtc(); - - when(fixture.mockSentryNative.displayRefreshRate()) - .thenAnswer((_) async => null); - - final tracer = SentryTracer( - SentryTransactionContext('name', 'op', description: 'tracerDesc'), - fixture.hub, - startTimestamp: startTimestamp); - - await Future.delayed(Duration(milliseconds: 500)); - await tracer.finish(endTimestamp: endTimestamp); - - expect(tracer.data['frames.slow'], expectedSlowFrames); - expect(tracer.data['frames.frozen'], expectedFrozenFrames); - expect(tracer.data['frames.delay'], expectedFramesDelay); - expect(tracer.data['frames.total'], expectedTotalFrames); - }); - - test('onSpanFinished removes frames older than span start timestamp', - () async { - // Using multiple spans to test frame removal. When the last span is finished, - // the tracker clears all data, so we need at least two spans to observe partial removal. - final sut = fixture.sut; - final span1 = MockSentrySpan(); - final span2 = MockSentrySpan(); - final spanStartTimestamp = DateTime.now(); - final spanEndTimestamp = spanStartTimestamp.add(Duration(seconds: 1)); - - when(span1.isRootSpan).thenReturn(false); - when(span1.startTimestamp).thenReturn(spanStartTimestamp); - when(span1.context).thenReturn(SentrySpanContext(operation: 'op')); - - when(span2.isRootSpan).thenReturn(false); - when(span2.startTimestamp) - .thenReturn(spanStartTimestamp.add(Duration(seconds: 2))); - when(span2.context).thenReturn(SentrySpanContext(operation: 'op')); - - sut.activeSpans.add(span1); - sut.activeSpans.add(span2); - - sut.frames[spanStartTimestamp.subtract(Duration(seconds: 5))] = 1; - sut.frames[spanStartTimestamp.subtract(Duration(seconds: 3))] = 1; - sut.frames[spanStartTimestamp.add(Duration(seconds: 4))] = 1; - - await sut.onSpanFinished(span1, spanEndTimestamp); - - expect(sut.frames, hasLength(1)); - expect(sut.frames.keys.first, spanStartTimestamp.add(Duration(seconds: 4))); - }); - - test( - 'starting and finishing a span calculates and attaches frame metrics to span', - () async { - final sut = fixture.sut; - fixture.options.tracesSampleRate = 1.0; - fixture.options.addPerformanceCollector(sut); - final startTimestamp = DateTime.now(); - final endTimestamp = startTimestamp.add(Duration(milliseconds: 1000)); - - final tracer = SentryTracer( - SentryTransactionContext('name1', 'op1'), fixture.hub, - startTimestamp: startTimestamp); - - await Future.delayed(Duration(milliseconds: 500)); - await tracer.finish(endTimestamp: endTimestamp); - - expect(tracer.data['frames.slow'], expectedSlowFrames); - expect(tracer.data['frames.frozen'], expectedFrozenFrames); - expect(tracer.data['frames.delay'], expectedFramesDelay); - expect(tracer.data['frames.total'], expectedTotalFrames); - - expect(tracer.measurements['frames_delay']!.value, expectedFramesDelay); - expect(tracer.measurements['frames_total']!.value, expectedTotalFrames); - expect(tracer.measurements['frames_slow']!.value, expectedSlowFrames); - expect(tracer.measurements['frames_frozen']!.value, expectedFrozenFrames); - }); - - test('frame fully contained in span should contribute to frame metrics', () { - final sut = fixture.sut; - final span = MockSentrySpan(); - - final now = DateTime.now(); - when(span.startTimestamp).thenReturn(now); - when(span.endTimestamp).thenReturn(now.add(Duration(milliseconds: 500))); - sut.frames[now.add(Duration(milliseconds: 200))] = 100; - - final metrics = sut.calculateFrameMetrics(span, span.endTimestamp!, 60); - - expect(metrics['frames.total'], 26); - expect(metrics['frames.slow'], 1); - expect(metrics['frames.delay'], 84); - expect(metrics['frames.frozen'], 0); - }); - - test('frame fully outside of span should not contribute to frame metrics', - () { - final sut = fixture.sut; - final span = MockSentrySpan(); - - final now = DateTime.now(); - when(span.startTimestamp).thenReturn(now); - when(span.endTimestamp).thenReturn(now.add(Duration(milliseconds: 500))); - sut.frames[now.subtract(Duration(milliseconds: 200))] = 100; - - final metrics = sut.calculateFrameMetrics(span, span.endTimestamp!, 60); - - expect(metrics['frames.total'], 31); - expect(metrics['frames.slow'], 0); - expect(metrics['frames.delay'], 0); - expect(metrics['frames.frozen'], 0); - }); - - test( - 'frame partially contained in span (starts before span and ends within span) should contribute to frame metrics', - () { - final sut = fixture.sut; - final span = MockSentrySpan(); - - final now = DateTime.now(); - when(span.startTimestamp).thenReturn(now); - when(span.endTimestamp).thenReturn(now.add(Duration(milliseconds: 500))); - // 50ms before span starts and ends 50ms after span starts - sut.frames[now.add(Duration(milliseconds: 50))] = 100; - - final metrics = sut.calculateFrameMetrics(span, span.endTimestamp!, 60); - - expect(metrics['frames.total'], 29); - expect(metrics['frames.slow'], 1); - expect(metrics['frames.delay'], 42); - expect(metrics['frames.frozen'], 0); - }); - - test( - 'frame partially contained in span (starts withing span and ends after span end) should contribute to frame metrics', - () { - final sut = fixture.sut; - final span = MockSentrySpan(); - - final now = DateTime.now(); - when(span.startTimestamp).thenReturn(now); - when(span.endTimestamp).thenReturn(now.add(Duration(milliseconds: 500))); - sut.frames[now.add(Duration(milliseconds: 550))] = 100; - - final metrics = sut.calculateFrameMetrics(span, span.endTimestamp!, 60); - - expect(metrics['frames.total'], 29); - expect(metrics['frames.slow'], 1); - expect(metrics['frames.delay'], 42); - expect(metrics['frames.frozen'], 0); - }); - - test('calculates frame metrics correctly for multiple simultaneous spans', - () async { - final sut = fixture.sut; - fixture.options.tracesSampleRate = 1.0; - fixture.options.addPerformanceCollector(sut); - final startTimestamp = DateTime.now(); - final endTimestamp = startTimestamp.add(Duration(milliseconds: 1000)); - - final tracer = SentryTracer( - SentryTransactionContext('name1', 'op1'), fixture.hub, - startTimestamp: startTimestamp); - - final child = tracer.startChild('child', - startTimestamp: startTimestamp.add(Duration(milliseconds: 1))) - as SentrySpan; - - await Future.delayed(Duration(milliseconds: 500)); - await child.finish(endTimestamp: endTimestamp); - - await Future.delayed(Duration(milliseconds: 500)); - await tracer.finish(endTimestamp: endTimestamp); - - expect(child.data['frames.slow'], expectedSlowFrames); - expect(child.data['frames.frozen'], expectedFrozenFrames); - expect(child.data['frames.delay'], expectedFramesDelay); - expect(child.data['frames.total'], expectedTotalFrames); - - // total frames is hardcoded here since it depends on span duration as well - // and we are deviating from the default 800ms to 1600ms for the whole transaction - expect(tracer.data['frames.slow'], expectedSlowFrames); - expect(tracer.data['frames.frozen'], expectedFrozenFrames); - expect(tracer.data['frames.delay'], expectedFramesDelay); - // expect(tracer.data['frames.total'], 54); - expect(tracer.measurements['frames_delay']!.value, expectedFramesDelay); - // expect(tracer.measurements['frames_total']!.value, 54); - expect(tracer.measurements['frames_slow']!.value, expectedSlowFrames); - expect(tracer.measurements['frames_frozen']!.value, expectedFrozenFrames); - }); - - test('frame tracker is paused after finishing a span', () async { - final sut = fixture.sut; - fixture.options.tracesSampleRate = 1.0; - fixture.options.addPerformanceCollector(sut); - - final tracer = - SentryTracer(SentryTransactionContext('name', 'op'), fixture.hub); - - await Future.delayed(Duration(milliseconds: 100)); - await tracer.finish(); - - expect(sut.isTrackingPaused, isTrue); - }); -} - -class Fixture { - final options = SentryFlutterOptions(dsn: fakeDsn); - late final hub = Hub(options); - final fakeFrameCallbackHandler = FakeFrameCallbackHandler(); - final mockSentryNative = MockSentryNativeBinding(); - - SpanFrameMetricsCollector get sut => SpanFrameMetricsCollector(options, - frameCallbackHandler: fakeFrameCallbackHandler, - native: mockSentryNative, - isTestMode: true); -} diff --git a/hive/lib/src/sentry_box_collection.dart b/hive/lib/src/sentry_box_collection.dart index 0dee9e9831..d4c605efe2 100644 --- a/hive/lib/src/sentry_box_collection.dart +++ b/hive/lib/src/sentry_box_collection.dart @@ -10,7 +10,6 @@ import 'package:hive/src/box_collection/box_collection_stub.dart' as stub; // ignore: implementation_imports import 'package:hive/src/box_collection/box_collection_stub.dart' if (dart.library.html) 'package:hive/src/box_collection/box_collection_indexed_db.dart' - if (dart.library.js_interop) 'package:hive/src/box_collection/box_collection_indexed_db.dart' if (dart.library.io) 'package:hive/src/box_collection/box_collection.dart' as impl; diff --git a/hive/lib/src/version.dart b/hive/lib/src/version.dart index 315e1edcf1..18932a8818 100644 --- a/hive/lib/src/version.dart +++ b/hive/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.4.0-beta.1'; +const String sdkVersion = '8.3.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_hive'; diff --git a/hive/pubspec.yaml b/hive/pubspec.yaml index 17d431741d..a065329ce4 100644 --- a/hive/pubspec.yaml +++ b/hive/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_hive description: An integration which adds support for performance tracing for the hive package. -version: 8.4.0-beta.1 +version: 8.3.0 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -17,7 +17,7 @@ platforms: web: dependencies: - sentry: 8.4.0-beta.1 + sentry: 8.3.0 hive: ^2.2.3 meta: ^1.3.0 diff --git a/hive/test/mocks/mocks.dart b/hive/test/mocks/mocks.dart index 8b6d7f4db9..9b2db0e30d 100644 --- a/hive/test/mocks/mocks.dart +++ b/hive/test/mocks/mocks.dart @@ -4,7 +4,6 @@ import 'package:sentry/sentry.dart'; import 'package:hive/src/box_collection/box_collection_stub.dart' if (dart.library.html) 'package:hive/src/box_collection/box_collection_indexed_db.dart' - if (dart.library.js_interop) 'package:hive/src/box_collection/box_collection_indexed_db.dart' if (dart.library.io) 'package:hive/src/box_collection/box_collection.dart' as impl; diff --git a/hive/test/mocks/mocks.mocks.dart b/hive/test/mocks/mocks.mocks.dart index 5cd8fc7e30..6d1bb907d7 100644 --- a/hive/test/mocks/mocks.mocks.dart +++ b/hive/test/mocks/mocks.mocks.dart @@ -18,7 +18,6 @@ import 'package:hive/src/box_collection/box_collection_stub.dart' as stub; // ignore: implementation_imports import 'package:hive/src/box_collection/box_collection_stub.dart' if (dart.library.html) 'package:hive/src/box_collection/box_collection_indexed_db.dart' - if (dart.library.js_interop) 'package:hive/src/box_collection/box_collection_indexed_db.dart' if (dart.library.io) 'package:hive/src/box_collection/box_collection.dart' as impl; diff --git a/isar/lib/src/version.dart b/isar/lib/src/version.dart index ada16a7695..c215620372 100644 --- a/isar/lib/src/version.dart +++ b/isar/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.4.0-beta.1'; +const String sdkVersion = '8.3.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_isar'; diff --git a/isar/pubspec.yaml b/isar/pubspec.yaml index dd7730269c..cbafa2af80 100644 --- a/isar/pubspec.yaml +++ b/isar/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_isar description: An integration which adds support for performance tracing for the isar package. -version: 8.4.0-beta.1 +version: 8.3.0 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -20,7 +20,7 @@ platforms: dependencies: isar: ^3.1.0 isar_flutter_libs: ^3.1.0 # contains Isar Core - sentry: 8.4.0-beta.1 + sentry: 8.3.0 meta: ^1.3.0 path: ^1.8.3 diff --git a/logging/lib/src/version.dart b/logging/lib/src/version.dart index 618089c0f9..58dbea03c7 100644 --- a/logging/lib/src/version.dart +++ b/logging/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.4.0-beta.1'; +const String sdkVersion = '8.3.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_logging'; diff --git a/logging/pubspec.yaml b/logging/pubspec.yaml index 70fd7fa71d..80b484da48 100644 --- a/logging/pubspec.yaml +++ b/logging/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_logging description: An integration which adds support for recording log from the logging package. -version: 8.4.0-beta.1 +version: 8.3.0 homepage: https://docs.sentry.io/platforms/dart/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -19,7 +19,7 @@ platforms: dependencies: logging: ^1.0.0 - sentry: 8.4.0-beta.1 + sentry: 8.3.0 dev_dependencies: lints: ^4.0.0 diff --git a/metrics/metrics-ios.yml b/metrics/metrics-ios.yml index 6c7e175b04..57177c0899 100644 --- a/metrics/metrics-ios.yml +++ b/metrics/metrics-ios.yml @@ -10,5 +10,5 @@ startupTimeTest: diffMax: 150 binarySizeTest: - diffMin: 1200 KiB - diffMax: 1500 KiB + diffMin: 900 KiB + diffMax: 1300 KiB diff --git a/min_version_test/lib/main.dart b/min_version_test/lib/main.dart index 504c706a43..72a8aea404 100644 --- a/min_version_test/lib/main.dart +++ b/min_version_test/lib/main.dart @@ -1,9 +1,8 @@ import 'package:flutter/material.dart'; -import 'package:min_version_test/transaction/transaction_stub.dart' - if (dart.library.html) 'package:min_version_test/transaction/web_transaction.dart' - if (dart.library.js_interop) 'package:min_version_test/transaction/web_transaction.dart' - if (dart.library.io) 'package:min_version_test/transaction/file_transaction.dart'; +import 'package:min_version_test/transaction/transaction_locator.dart' + if (dart.library.html) 'package:min_version_test/transaction/file_transaction.dart' + if (dart.library.io) 'package:min_version_test/transaction/web_transaction.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:sentry_logging/sentry_logging.dart'; diff --git a/min_version_test/lib/transaction/file_transaction.dart b/min_version_test/lib/transaction/file_transaction.dart index 5afa62f6ce..6f85ddc337 100644 --- a/min_version_test/lib/transaction/file_transaction.dart +++ b/min_version_test/lib/transaction/file_transaction.dart @@ -1,12 +1,12 @@ +import 'package:min_version_test/transaction/transaction.dart'; import 'dart:io'; import 'package:logging/logging.dart'; import 'package:dio/dio.dart'; + import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:sentry_dio/sentry_dio.dart'; -import 'transaction.dart'; - class FileTransaction implements Transaction { @override Future start() async { diff --git a/min_version_test/lib/transaction/transaction_stub.dart b/min_version_test/lib/transaction/transaction_locator.dart similarity index 60% rename from min_version_test/lib/transaction/transaction_stub.dart rename to min_version_test/lib/transaction/transaction_locator.dart index 1869f2ee17..7e3a3f75d5 100644 --- a/min_version_test/lib/transaction/transaction_stub.dart +++ b/min_version_test/lib/transaction/transaction_locator.dart @@ -1,4 +1,4 @@ -import 'transaction.dart'; +import 'package:min_version_test/transaction/transaction.dart'; Transaction getTransaction() => throw UnsupportedError('Cannot create sample transaction.'); diff --git a/min_version_test/lib/transaction/web_transaction.dart b/min_version_test/lib/transaction/web_transaction.dart index 03c8cdd368..99ce8f3508 100644 --- a/min_version_test/lib/transaction/web_transaction.dart +++ b/min_version_test/lib/transaction/web_transaction.dart @@ -1,10 +1,11 @@ +import 'package:min_version_test/transaction/transaction.dart'; + import 'package:logging/logging.dart'; import 'package:dio/dio.dart'; + import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:sentry_dio/sentry_dio.dart'; -import 'transaction.dart'; - class WebTransaction implements Transaction { @override Future start() async { diff --git a/min_version_test/pubspec.yaml b/min_version_test/pubspec.yaml index e8e76dc9df..8fdfe47329 100644 --- a/min_version_test/pubspec.yaml +++ b/min_version_test/pubspec.yaml @@ -91,3 +91,4 @@ flutter: # # For details regarding fonts from package dependencies, # see https://flutter.dev/custom-fonts/#from-packages + \ No newline at end of file diff --git a/sqflite/lib/src/version.dart b/sqflite/lib/src/version.dart index 4d02ffa9c3..a74f25cdbd 100644 --- a/sqflite/lib/src/version.dart +++ b/sqflite/lib/src/version.dart @@ -1,5 +1,5 @@ /// The SDK version reported to Sentry.io in the submitted events. -const String sdkVersion = '8.4.0-beta.1'; +const String sdkVersion = '8.3.0'; /// The package name reported to Sentry.io in the submitted events. const String packageName = 'pub:sentry_sqflite'; diff --git a/sqflite/pubspec.yaml b/sqflite/pubspec.yaml index b6575b0a45..b8449f13f7 100644 --- a/sqflite/pubspec.yaml +++ b/sqflite/pubspec.yaml @@ -1,6 +1,6 @@ name: sentry_sqflite description: An integration which adds support for performance tracing for the sqflite package. -version: 8.4.0-beta.1 +version: 8.3.0 homepage: https://docs.sentry.io/platforms/flutter/ repository: https://github.com/getsentry/sentry-dart issue_tracker: https://github.com/getsentry/sentry-dart/issues @@ -15,7 +15,7 @@ platforms: macos: dependencies: - sentry: 8.4.0-beta.1 + sentry: 8.3.0 sqflite: ^2.2.8 sqflite_common: ^2.0.0 meta: ^1.3.0