Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,73 @@
# Changelog

## 9.19.0

### Features

- Span-first trace lifecycle (experimental) by @buenaflor in [#3659](https://github.com/getsentry/sentry-dart/pull/3659)
- Streams spans to Sentry as each one finishes instead of buffering them into a transaction envelope at the root.
- Opt in via `options.traceLifecycle`. The classic transaction-based `SentryTraceLifecycle.static` remains the default.
- In stream mode, create spans with the new `Sentry.startSpan` / `Sentry.startSpanSync` APIs — the transaction APIs (`Sentry.startTransaction`, `ISentrySpan.startChild`) do nothing in this mode.
- Auto-instrumentations (frames, app start, TTID/TTFD, navigation, user interaction, HTTP, databases, GraphQL link) automatically switch to the streaming API when enabled.

```dart
// Opt in during SDK init.
await SentryFlutter.init((options) {
options.dsn = 'https://example@sentry.io/add-your-dsn-here';
options.tracesSampleRate = 1.0;
options.traceLifecycle = SentryTraceLifecycle.stream;
});

// Async work — the span ends and is sent when the future completes.
final order = await Sentry.startSpan('checkout', (span) async {
span.setAttribute('cart.item_count', SentryAttribute.int(cart.items.length));

// Automatically parents to 'checkout' via zones.
final payment = await Sentry.startSpan('process-payment', (span) {
return paymentService.charge(cart.total);
});

return orderService.create(cart, payment: payment);
});

// Sync variant.
final total = Sentry.startSpanSync('calculate-total', (span) {
return cart.items.fold<double>(0, (sum, item) => sum + item.price);
});
```

### Fixes

- (feedback) Show success message after feedback submission by @denrase in [#3609](https://github.com/getsentry/sentry-dart/pull/3609)

### Enhancements

- (navigator-observer) `enableNewTraceOnNavigation` is now opt-in by @buenaflor in [#3657](https://github.com/getsentry/sentry-dart/pull/3657)
- `SentryNavigatorObserver` no longer generates a fresh trace id on every push/pop/replace by default. One trace per session (the previous opt-in behavior) is now the default and preserves trace continuity across navigations.
- If you relied on the old behavior, opt back in explicitly:

```dart
SentryNavigatorObserver(
enableNewTraceOnNavigation: true,
);
```

### Dependencies

- chore(deps): update Android SDK to v8.39.1 by @github-actions in [#3646](https://github.com/getsentry/sentry-dart/pull/3646)

### Internal Changes

#### Deps

- Bump actions/create-github-app-token from 3.0.0 to 3.1.1 by @dependabot in [#3652](https://github.com/getsentry/sentry-dart/pull/3652)
- Bump getsentry/craft/.github/workflows/changelog-preview.yml from 2.25.2 to 2.25.4 by @dependabot in [#3655](https://github.com/getsentry/sentry-dart/pull/3655)
- Bump actions/cache from 5.0.4 to 5.0.5 by @dependabot in [#3656](https://github.com/getsentry/sentry-dart/pull/3656)

#### Other

- Integrate Warden for AI-powered PR code review by @buenaflor in [#3651](https://github.com/getsentry/sentry-dart/pull/3651)

## 9.18.0

### Dependencies
Expand Down
1 change: 1 addition & 0 deletions docs/sdk-versions.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ This document shows which version of the various Sentry SDKs are used in which S

| Sentry Flutter SDK | Sentry Android SDK | Sentry Cocoa SDK | Sentry JavaScript SDK | Sentry Native SDK |
| ------------------ | ------------------ | ---------------- | --------------------- | ----------------- |
| 9.19.0 | 8.39.1 | 8.58.1 | 10.38.0 | 0.13.7 |
| 9.18.0 | 8.38.0 | 8.58.1 | 10.38.0 | 0.13.7 |
| 9.17.0 | 8.38.0 | 8.58.1 | 10.38.0 | 0.13.6 |
| 9.16.1 | 8.37.1 | 8.58.0 | 10.38.0 | 0.13.3 |
Expand Down
2 changes: 1 addition & 1 deletion packages/dart/lib/src/version.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
library;

/// The SDK version reported to Sentry.io in the submitted events.
const String sdkVersion = '9.18.0';
const String sdkVersion = '9.19.0';

String sdkName(bool isWeb) => isWeb ? _browserSdkName : _ioSdkName;

Expand Down
2 changes: 1 addition & 1 deletion packages/dart/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: sentry
version: 9.18.0
version: 9.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.
Expand Down
2 changes: 1 addition & 1 deletion packages/dio/lib/src/version.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/// The SDK version reported to Sentry.io in the submitted events.
const String sdkVersion = '9.18.0';
const String sdkVersion = '9.19.0';

/// The package name reported to Sentry.io in the submitted events.
const String packageName = 'pub:sentry_dio';
4 changes: 2 additions & 2 deletions packages/dio/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: sentry_dio
description: An integration which adds support for performance tracing for the Dio package.
version: 9.18.0
version: 9.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
Expand All @@ -19,7 +19,7 @@ platforms:

dependencies:
dio: ^5.2.0
sentry: 9.18.0
sentry: 9.19.0

dev_dependencies:
_sentry_testing:
Expand Down
2 changes: 1 addition & 1 deletion packages/drift/lib/src/version.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/// The SDK version reported to Sentry.io in the submitted events.
const String sdkVersion = '9.18.0';
const String sdkVersion = '9.19.0';

/// The package name reported to Sentry.io in the submitted events.
const String packageName = 'pub:sentry_drift';
4 changes: 2 additions & 2 deletions packages/drift/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: sentry_drift
description: An integration which adds support for performance tracing for the drift package.
version: 9.18.0
version: 9.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
Expand All @@ -17,7 +17,7 @@ platforms:
web:

dependencies:
sentry: 9.18.0
sentry: 9.19.0
meta: ^1.3.0
drift: ^2.24.0

Expand Down
2 changes: 1 addition & 1 deletion packages/file/lib/src/version.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/// The SDK version reported to Sentry.io in the submitted events.
const String sdkVersion = '9.18.0';
const String sdkVersion = '9.19.0';

/// The package name reported to Sentry.io in the submitted events.
const String packageName = 'pub:sentry_file';
4 changes: 2 additions & 2 deletions packages/file/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: sentry_file
description: An integration which adds support for performance tracing for dart.io.File.
version: 9.18.0
version: 9.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
Expand All @@ -17,7 +17,7 @@ platforms:
windows:

dependencies:
sentry: 9.18.0
sentry: 9.19.0
meta: ^1.3.0

dev_dependencies:
Expand Down
4 changes: 2 additions & 2 deletions packages/firebase_remote_config/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: sentry_firebase_remote_config
description: "Sentry integration to use feature flags from Firebase Remote Config."
version: 9.18.0
version: 9.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
Expand All @@ -21,7 +21,7 @@ dependencies:
flutter:
sdk: flutter
firebase_remote_config: '>=5.4.3 <7.0.0'
sentry: 9.18.0
sentry: 9.19.0

dev_dependencies:
flutter_test:
Expand Down
107 changes: 53 additions & 54 deletions packages/flutter/example/integration_test/integration_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:http/http.dart';
import 'package:integration_test/integration_test.dart';
import 'package:jni/jni.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:sentry_flutter/sentry_flutter.dart';
import 'package:sentry_flutter_example/main.dart';
Expand Down Expand Up @@ -221,57 +222,56 @@ void main() {
});
});

final ref = jni.ScopesAdapter.getInstance()?.getOptions().reference;
expect(ref, isNotNull);
final androidOptions = jni.SentryAndroidOptions.fromReference(ref!);
final scopesAdapter = jni.ScopesAdapter.instance;
expect(scopesAdapter, isNotNull);
final androidOptions =
scopesAdapter!.options.as(jni.SentryAndroidOptions.type);

expect(androidOptions, isNotNull);
expect(androidOptions.getDsn()?.toDartString(), fakeDsn);
expect(androidOptions.isDebug(), isTrue);
final diagnostic = androidOptions.getDiagnosticLevel();
expect(androidOptions.dsn?.toDartString(), fakeDsn);
expect(androidOptions.isDebug, isTrue);
final diagnostic = androidOptions.diagnosticLevel;
expect(
diagnostic,
jni.SentryLevel.ERROR,
);
expect(androidOptions.getEnvironment()?.toDartString(), 'init-test-env');
expect(androidOptions.getRelease()?.toDartString(), '1.2.3+9');
expect(androidOptions.getDist()?.toDartString(), '42');
expect(androidOptions.isSendDefaultPii(), isTrue);
expect(androidOptions.isAttachStacktrace(), isFalse);
expect(androidOptions.isAttachThreads(), isTrue);
expect(androidOptions.getMaxBreadcrumbs(), 7);
expect(androidOptions.getMaxCacheItems(), 77);
expect(androidOptions.getMaxAttachmentSize(), 512);
expect(androidOptions.isEnableScopeSync(), isTrue);
expect(androidOptions.isAnrEnabled(), isFalse);
expect(androidOptions.getAnrTimeoutIntervalMillis(), 2000);
expect(androidOptions.isEnableActivityLifecycleBreadcrumbs(), isFalse);
expect(androidOptions.isEnableAppLifecycleBreadcrumbs(), isFalse);
expect(androidOptions.isEnableSystemEventBreadcrumbs(), isFalse);
expect(androidOptions.isEnableAppComponentBreadcrumbs(), isFalse);
expect(androidOptions.isEnableUserInteractionBreadcrumbs(), isFalse);
expect(androidOptions.getConnectionTimeoutMillis(), 1234);
expect(androidOptions.getReadTimeoutMillis(), 2345);
expect(androidOptions.isEnableSpotlight(), isTrue);
expect(androidOptions.isSendClientReports(), isFalse);
expect(androidOptions.environment?.toDartString(), 'init-test-env');
expect(androidOptions.release$1?.toDartString(), '1.2.3+9');
expect(androidOptions.dist?.toDartString(), '42');
expect(androidOptions.isSendDefaultPii, isTrue);
expect(androidOptions.isAttachStacktrace, isFalse);
expect(androidOptions.isAttachThreads, isTrue);
expect(androidOptions.maxBreadcrumbs, 7);
expect(androidOptions.maxCacheItems, 77);
expect(androidOptions.maxAttachmentSize, 512);
expect(androidOptions.isEnableScopeSync, isTrue);
expect(androidOptions.isAnrEnabled, isFalse);
expect(androidOptions.anrTimeoutIntervalMillis, 2000);
expect(androidOptions.isEnableActivityLifecycleBreadcrumbs, isFalse);
expect(androidOptions.isEnableAppLifecycleBreadcrumbs, isFalse);
expect(androidOptions.isEnableSystemEventBreadcrumbs, isFalse);
expect(androidOptions.isEnableAppComponentBreadcrumbs, isFalse);
expect(androidOptions.isEnableUserInteractionBreadcrumbs, isFalse);
expect(androidOptions.connectionTimeoutMillis, 1234);
expect(androidOptions.readTimeoutMillis, 2345);
expect(androidOptions.isEnableSpotlight, isTrue);
expect(androidOptions.isSendClientReports, isFalse);
expect(
androidOptions.getSpotlightConnectionUrl()?.toDartString(),
androidOptions.spotlightConnectionUrl?.toDartString(),
Sentry.currentHub.options.spotlight.url,
);
expect(androidOptions.getSentryClientName()?.toDartString(),
expect(androidOptions.sentryClientName?.toDartString(),
'$androidSdkName/${jni.BuildConfig.VERSION_NAME?.toDartString()}');
expect(androidOptions.getNativeSdkName()?.toDartString(), nativeSdkName);
expect(androidOptions.getSdkVersion()?.getName().toDartString(),
androidSdkName);
expect(androidOptions.getSdkVersion()?.getVersion().toDartString(),
expect(androidOptions.nativeSdkName?.toDartString(), nativeSdkName);
expect(androidOptions.sdkVersion?.name.toDartString(), androidSdkName);
expect(androidOptions.sdkVersion?.version.toDartString(),
jni.BuildConfig.VERSION_NAME?.toDartString());
final allPackages = androidOptions
.getSdkVersion()
?.getPackageSet()
final allPackages = androidOptions.sdkVersion?.packageSet
.asDart()
.map((pkg) {
if (pkg == null) return null;
return SentryPackage(
pkg.getName().toDartString(), pkg.getVersion().toDartString());
pkg.name.toDartString(), pkg.version.toDartString());
})
.nonNulls
.toList();
Expand All @@ -280,21 +280,21 @@ void main() {
(p) => p.name == package.name && p.version == package.version);
expect(findMatchingPackage, isNotNull);
}
expect(androidOptions.isEnableAutoTraceIdGeneration(), isFalse);
expect(androidOptions.isTombstoneEnabled(), isTrue);
expect(androidOptions.isEnableAutoTraceIdGeneration, isFalse);
expect(androidOptions.isTombstoneEnabled, isTrue);

final androidProxy = androidOptions.getProxy();
final androidProxy = androidOptions.proxy;
expect(androidProxy, isNotNull);
expect(androidProxy!.getHost()?.toDartString(), 'proxy.local');
expect(androidProxy.getPort()?.toDartString(), '8084');
expect(androidProxy.getUser()?.toDartString(), 'u');
expect(androidProxy.getPass()?.toDartString(), 'p');

final r = androidOptions.getSessionReplay();
expect(r.getQuality(), jni.SentryReplayOptions$SentryReplayQuality.HIGH);
expect(r.getSessionSampleRate(), isNotNull);
expect(r.getOnErrorSampleRate(), isNotNull);
expect(r.isTrackConfiguration(), isFalse);
expect(androidProxy!.host?.toDartString(), 'proxy.local');
expect(androidProxy.port?.toDartString(), '8084');
expect(androidProxy.user?.toDartString(), 'u');
expect(androidProxy.pass?.toDartString(), 'p');

final r = androidOptions.sessionReplay;
expect(r.quality, jni.SentryReplayOptions$SentryReplayQuality.HIGH);
expect(r.sessionSampleRate, isNotNull);
expect(r.onErrorSampleRate, isNotNull);
expect(r.isTrackConfiguration, isFalse);
}, skip: !Platform.isAndroid);

testWidgets('loads native contexts through loadContexts', (tester) async {
Expand Down Expand Up @@ -1079,10 +1079,10 @@ void main() {
final dartTraceId =
Sentry.currentHub.scope.propagationContext.traceId.toString();

final traceParent = jni.Sentry.getTraceparent();
final traceParent = jni.Sentry.traceparent;
expect(traceParent, isNotNull,
reason: 'Native traceparent should not be null');
final traceHeader = traceParent!.getValue().toDartString();
final traceHeader = traceParent!.value.toDartString();

final nativeTraceId = traceHeader.split('-').first;
expect(nativeTraceId, dartTraceId,
Expand All @@ -1095,8 +1095,7 @@ void main() {
// Allow the fire-and-forget dispatch to complete
await Future<void>.delayed(const Duration(milliseconds: 100));

final newTraceParent =
jni.Sentry.getTraceparent()?.getValue().toDartString();
final newTraceParent = jni.Sentry.traceparent?.value.toDartString();
final newTraceHeader = newTraceParent!.toString();

final newNativeTraceId = newTraceHeader.split('-').first;
Expand Down
Loading