Skip to content

Commit

Permalink
Merge branch 'main' into feat/dart-symbolication
Browse files Browse the repository at this point in the history
  • Loading branch information
buenaflor authored Sep 4, 2024
2 parents 22741a3 + 3a16179 commit 465b643
Show file tree
Hide file tree
Showing 73 changed files with 2,835 additions and 429 deletions.
122 changes: 100 additions & 22 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,58 @@
- This flag enables symbolication of Dart stack traces when native debug images are not available.
- Useful when using Sentry.init() instead of SentryFlutter.init() in Flutter projects for example due to size limitations.
- `true` by default but automatically set to `false` when using SentryFlutter.init() because the SentryFlutter fetches debug images from the native SDK integrations.
- Support allowUrls and denyUrls for Flutter Web ([#2227](https://github.com/getsentry/sentry-dart/pull/2227))

```dart
await SentryFlutter.init(
(options) {
...
options.allowUrls = ["^https://sentry.com.*\$", "my-custom-domain"];
options.denyUrls = ["^.*ends-with-this\$", "denied-url"];
},
appRunner: () => runApp(MyApp()),
);
```

- Session replay Alpha for Android and iOS ([#2208](https://github.com/getsentry/sentry-dart/pull/2208)).

To try out replay, you can set following options (access is limited to early access orgs on Sentry. If you're interested, [sign up for the waitlist](https://sentry.io/lp/mobile-replay-beta/)):

```dart
await SentryFlutter.init(
(options) {
...
options.experimental.replay.sessionSampleRate = 1.0;
options.experimental.replay.errorSampleRate = 1.0;
},
appRunner: () => runApp(MyApp()),
);
```

### Dependencies

- Bump Cocoa SDK from v8.35.1 to v8.36.0 ([#2252](https://github.com/getsentry/sentry-dart/pull/2252))
- [changelog](https://github.com/getsentry/sentry-cocoa/blob/main/CHANGELOG.md#8360)
- [diff](https://github.com/getsentry/sentry-cocoa/compare/8.35.1...8.36.0)

### Fixes

- Only access renderObject if `hasSize` is true ([#2263](https://github.com/getsentry/sentry-dart/pull/2263))

## 8.8.0

### Features

- Add `SentryFlutter.nativeCrash()` using MethodChannels for Android and iOS ([#2239](https://github.com/getsentry/sentry-dart/pull/2239))
- This can be used to test if native crash reporting works
- This can be used to test if native crash reporting works

- Add `ignoreRoutes` parameter to `SentryNavigatorObserver`. ([#2218](https://github.com/getsentry/sentry-dart/pull/2218))
- This will ignore the Routes and prevent the Route from being pushed to the Sentry server.
- Ignored routes will also create no TTID and TTFD spans.
```dart
SentryNavigatorObserver(ignoreRoutes: ["/ignoreThisRoute"]),
```
- This will ignore the Routes and prevent the Route from being pushed to the Sentry server.
- Ignored routes will also create no TTID and TTFD spans.

```dart
SentryNavigatorObserver(ignoreRoutes: ["/ignoreThisRoute"]),
```

### Improvements

Expand All @@ -41,12 +74,33 @@ SentryNavigatorObserver(ignoreRoutes: ["/ignoreThisRoute"]),
- [changelog](https://github.com/getsentry/sentry-java/blob/main/CHANGELOG.md#7140)
- [diff](https://github.com/getsentry/sentry-java/compare/7.13.0...7.14.0)

## 8.8.0-alpha.1

### Features

- iOS Session Replay Alpha ([#2209](https://github.com/getsentry/sentry-dart/pull/2209))
- Android replay touch tracking support ([#2228](https://github.com/getsentry/sentry-dart/pull/2228))
- Add `ignoreRoutes` parameter to `SentryNavigatorObserver`. ([#2218](https://github.com/getsentry/sentry-dart/pull/2218))
- This will ignore the Routes and prevent the Route from being pushed to the Sentry server.
- Ignored routes will also create no TTID and TTFD spans.

```dart
SentryNavigatorObserver(ignoreRoutes: ["/ignoreThisRoute"]),
```

### Dependencies

- Bump Android SDK from v7.13.0 to v7.14.0 ([#2228](https://github.com/getsentry/sentry-dart/pull/2228))
- [changelog](https://github.com/getsentry/sentry-java/blob/main/CHANGELOG.md#7140)
- [diff](https://github.com/getsentry/sentry-java/compare/7.13.0...7.14.0)

## 8.7.0

### Features

- Add support for span level measurements. ([#2214](https://github.com/getsentry/sentry-dart/pull/2214))
- Add `ignoreTransactions` and `ignoreErrors` to options ([#2207](https://github.com/getsentry/sentry-dart/pull/2207))

```dart
await SentryFlutter.init(
(options) {
Expand All @@ -58,8 +112,10 @@ SentryNavigatorObserver(ignoreRoutes: ["/ignoreThisRoute"]),
appRunner: () => runApp(MyApp()),
);
```

- Add proxy support ([#2192](https://github.com/getsentry/sentry-dart/pull/2192))
- Configure a `SentryProxy` object and set it on `SentryFlutter.init`

```dart
import 'package:flutter/widgets.dart';
import 'package:sentry_flutter/sentry_flutter.dart';
Expand Down Expand Up @@ -99,24 +155,25 @@ SentryNavigatorObserver(ignoreRoutes: ["/ignoreThisRoute"]),
- This is enabled automatically and will change grouping if you already have issues with obfuscated titles
- If you want to disable this feature, set `enableExceptionTypeIdentification` to `false` in your Sentry options
- You can add your custom exception identifier if there are exceptions that we do not identify out of the box
```dart
// How to add your own custom exception identifier
class MyCustomExceptionIdentifier implements ExceptionIdentifier {
@override
String? identifyType(Exception exception) {
if (exception is MyCustomException) {
return 'MyCustomException';
}
if (exception is MyOtherCustomException) {
return 'MyOtherCustomException';

```dart
// How to add your own custom exception identifier
class MyCustomExceptionIdentifier implements ExceptionIdentifier {
@override
String? identifyType(Exception exception) {
if (exception is MyCustomException) {
return 'MyCustomException';
}
if (exception is MyOtherCustomException) {
return 'MyOtherCustomException';
}
return null;
}
return null;
}
}
SentryFlutter.init((options) =>
options..prependExceptionTypeIdentifier(MyCustomExceptionIdentifier()));
```
SentryFlutter.init((options) =>
options..prependExceptionTypeIdentifier(MyCustomExceptionIdentifier()));
```

### Deprecated

Expand All @@ -132,6 +189,27 @@ SentryFlutter.init((options) =>
- [changelog](https://github.com/getsentry/sentry-java/blob/main/CHANGELOG.md#7130)
- [diff](https://github.com/getsentry/sentry-java/compare/7.12.0...7.13.0)

## 8.6.0-alpha.2

### Features

- Android Session Replay Alpha ([#2032](https://github.com/getsentry/sentry-dart/pull/2032))

To try out replay, you can set following options:

```dart
await SentryFlutter.init(
(options) {
...
options.experimental.replay.sessionSampleRate = 1.0;
options.experimental.replay.errorSampleRate = 1.0;
},
appRunner: () => runApp(MyApp()),
);
```

Access is limited to early access orgs on Sentry. If you're interested, [sign up for the waitlist](https://sentry.io/lp/mobile-replay-beta/)

## 8.5.0

### Features
Expand All @@ -144,7 +222,7 @@ SentryFlutter.init((options) =>
### Fixes

- Disable sff & frame delay detection on web, linux and windows ([#2182](https://github.com/getsentry/sentry-dart/pull/2182))
- Display refresh rate is locked at 60 for these platforms which can lead to inaccurate metrics
- Display refresh rate is locked at 60 for these platforms which can lead to inaccurate metrics

### Improvements

Expand Down
30 changes: 30 additions & 0 deletions dart/lib/src/protocol/breadcrumb.dart
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ class Breadcrumb {
String? httpQuery,
String? httpFragment,
}) {
// The timestamp is used as the request-end time, so we need to set it right
// now and not rely on the default constructor.
timestamp ??= getUtcDateTime();

return Breadcrumb(
type: 'http',
category: 'http',
Expand All @@ -67,6 +71,11 @@ class Breadcrumb {
if (responseBodySize != null) 'response_body_size': responseBodySize,
if (httpQuery != null) 'http.query': httpQuery,
if (httpFragment != null) 'http.fragment': httpFragment,
if (requestDuration != null)
'start_timestamp':
timestamp.millisecondsSinceEpoch - requestDuration.inMilliseconds,
if (requestDuration != null)
'end_timestamp': timestamp.millisecondsSinceEpoch,
},
);
}
Expand Down Expand Up @@ -97,11 +106,32 @@ class Breadcrumb {
String? viewClass,
}) {
final newData = data ?? {};
var path = '';

if (viewId != null) {
newData['view.id'] = viewId;
path = viewId;
}

if (newData.containsKey('label')) {
if (path.isEmpty) {
path = newData['label'];
} else {
path = "$path, label: ${newData['label']}";
}
}

if (viewClass != null) {
newData['view.class'] = viewClass;
if (path.isEmpty) {
path = viewClass;
} else {
path = "$viewClass($path)";
}
}

if (path.isNotEmpty && !newData.containsKey('path')) {
newData['path'] = path;
}

return Breadcrumb(
Expand Down
17 changes: 13 additions & 4 deletions dart/lib/src/protocol/sentry_trace_context.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ class SentryTraceContext {
/// Id of a parent span
final SpanId? parentSpanId;

/// Replay associated with this trace.
final SentryId? replayId;

/// Whether the span is sampled or not
final bool? sampled;

Expand Down Expand Up @@ -50,6 +53,9 @@ class SentryTraceContext {
? null
: SpanId.fromId(json['parent_span_id'] as String),
traceId: SentryId.fromId(json['trace_id'] as String),
replayId: json['replay_id'] == null
? null
: SentryId.fromId(json['replay_id'] as String),
description: json['description'] as String?,
status: json['status'] == null
? null
Expand All @@ -68,6 +74,7 @@ class SentryTraceContext {
'trace_id': traceId.toString(),
'op': operation,
if (parentSpanId != null) 'parent_span_id': parentSpanId!.toString(),
if (replayId != null) 'replay_id': replayId!.toString(),
if (description != null) 'description': description,
if (status != null) 'status': status!.toString(),
if (origin != null) 'origin': origin,
Expand All @@ -84,6 +91,7 @@ class SentryTraceContext {
sampled: sampled,
origin: origin,
unknown: unknown,
replayId: replayId,
);

SentryTraceContext({
Expand All @@ -96,16 +104,17 @@ class SentryTraceContext {
this.status,
this.origin,
this.unknown,
this.replayId,
}) : traceId = traceId ?? SentryId.newId(),
spanId = spanId ?? SpanId.newId();

@internal
factory SentryTraceContext.fromPropagationContext(
PropagationContext propagationContext) {
return SentryTraceContext(
traceId: propagationContext.traceId,
spanId: propagationContext.spanId,
operation: 'default',
);
traceId: propagationContext.traceId,
spanId: propagationContext.spanId,
operation: 'default',
replayId: propagationContext.baggage?.getReplayId());
}
}
11 changes: 10 additions & 1 deletion dart/lib/src/scope.dart
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,13 @@ class Scope {
/// they must be JSON-serializable.
Map<String, dynamic> get extra => Map.unmodifiable(_extra);

/// Active replay recording.
@internal
SentryId? get replayId => _replayId;
@internal
set replayId(SentryId? value) => _replayId = value;
SentryId? _replayId;

final Contexts _contexts = Contexts();

/// Unmodifiable map of the scope contexts key/value
Expand Down Expand Up @@ -237,6 +244,7 @@ class Scope {
_tags.clear();
_extra.clear();
_eventProcessors.clear();
_replayId = null;

_clearBreadcrumbsSync();
_setUserSync(null);
Expand Down Expand Up @@ -429,7 +437,8 @@ class Scope {
..fingerprint = List.from(fingerprint)
.._transaction = _transaction
..span = span
.._enableScopeSync = false;
.._enableScopeSync = false
.._replayId = _replayId;

clone._setUserSync(user);

Expand Down
10 changes: 10 additions & 0 deletions dart/lib/src/sentry_baggage.dart
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,9 @@ class SentryBaggage {
// ignore: deprecated_member_use_from_same_package
setUserSegment(scope.user!.segment!);
}
if (scope.replayId != null && scope.replayId != SentryId.empty()) {
setReplayId(scope.replayId.toString());
}
}

static Map<String, String> _extractKeyValuesFromBaggageString(
Expand Down Expand Up @@ -205,5 +208,12 @@ class SentryBaggage {
return double.tryParse(sampleRate);
}

void setReplayId(String value) => set('sentry-replay_id', value);

SentryId? getReplayId() {
final replayId = get('sentry-replay_id');
return replayId == null ? null : SentryId.fromId(replayId);
}

Map<String, String> get keyValues => Map.unmodifiable(_keyValues);
}
Loading

0 comments on commit 465b643

Please sign in to comment.