Skip to content

Commit dd80448

Browse files
authored
Merge branch 'main' into v9
2 parents 342e82b + 95ebf3f commit dd80448

File tree

5 files changed

+148
-1
lines changed

5 files changed

+148
-1
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,17 @@
4343
- [diff](https://github.com/getsentry/sentry-java/compare/7.20.1...8.1.0)
4444
## Unreleased
4545

46+
47+
### Enhancements
48+
49+
- Add Flutter runtime information ([#2742](https://github.com/getsentry/sentry-dart/pull/2742))
50+
- This works if the version of Flutter you're using includes [this code](https://github.com/flutter/flutter/pull/163761).
51+
4652
### Fixes
4753

4854
- Pass missing `captureFailedRequests` param to `FailedRequestInterceptor` ([#2744](https://github.com/getsentry/sentry-dart/pull/2744))
4955

56+
5057
## 8.14.0-beta.1
5158

5259
### Behavioral changes
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import '../../protocol/sentry_runtime.dart';
2+
3+
// The Flutter version information can be fetched via Dart defines,
4+
// see
5+
// - https://github.com/flutter/flutter/pull/140783
6+
// - https://github.com/flutter/flutter/pull/163761
7+
//
8+
// This code lives in the Dart only Sentry code, since the code
9+
// doesn't require any Flutter dependency.
10+
// Additionally, this makes it work on background isolates in
11+
// Flutter, where one may not initialize the whole Flutter Sentry
12+
// SDK.
13+
// The const-ness of the properties below ensure that the code
14+
// is tree shaken in a non-Flutter environment.
15+
16+
const _isFlutterRuntimeInformationAbsent = FlutterVersion.version == null ||
17+
FlutterVersion.channel == null ||
18+
FlutterVersion.frameworkRevision == null;
19+
20+
const SentryRuntime? flutterRuntime = _isFlutterRuntimeInformationAbsent
21+
? null
22+
: SentryRuntime(
23+
name: 'Flutter',
24+
version: '${FlutterVersion.version} (${FlutterVersion.channel})',
25+
build: FlutterVersion.frameworkRevision,
26+
rawDescription: '${FlutterVersion.version} (${FlutterVersion.channel}) '
27+
'- Git hash ${FlutterVersion.frameworkRevision} '
28+
'- Git URL ${FlutterVersion.gitUrl}',
29+
);
30+
31+
const SentryRuntime? dartFlutterRuntime = FlutterVersion.dartVersion == null
32+
? null
33+
: SentryRuntime(name: 'Dart', version: FlutterVersion.dartVersion);
34+
35+
/// Details about the Flutter version this app was compiled with,
36+
/// corresponding to the output of `flutter --version`.
37+
///
38+
/// When this Flutter version was build from a fork, or when Flutter runs in a
39+
/// custom embedder, these values might be unreliable.
40+
abstract class FlutterVersion {
41+
const FlutterVersion._();
42+
43+
/// The Flutter version used to compile the app.
44+
static const String? version = bool.hasEnvironment('FLUTTER_VERSION')
45+
? String.fromEnvironment('FLUTTER_VERSION')
46+
: null;
47+
48+
/// The Flutter channel used to compile the app.
49+
static const String? channel = bool.hasEnvironment('FLUTTER_CHANNEL')
50+
? String.fromEnvironment('FLUTTER_CHANNEL')
51+
: null;
52+
53+
/// The URL of the Git repository from which Flutter was obtained.
54+
static const String? gitUrl = bool.hasEnvironment('FLUTTER_GIT_URL')
55+
? String.fromEnvironment('FLUTTER_GIT_URL')
56+
: null;
57+
58+
/// The Flutter framework revision, as a (short) Git commit ID.
59+
static const String? frameworkRevision =
60+
bool.hasEnvironment('FLUTTER_FRAMEWORK_REVISION')
61+
? String.fromEnvironment('FLUTTER_FRAMEWORK_REVISION')
62+
: null;
63+
64+
/// The Flutter engine revision.
65+
static const String? engineRevision =
66+
bool.hasEnvironment('FLUTTER_ENGINE_REVISION')
67+
? String.fromEnvironment('FLUTTER_ENGINE_REVISION')
68+
: null;
69+
70+
// This is included since [Platform.version](https://api.dart.dev/stable/dart-io/Platform/version.html)
71+
// is not included on web platforms.
72+
/// The Dart version used to compile the app.
73+
static const String? dartVersion = bool.hasEnvironment('FLUTTER_DART_VERSION')
74+
? String.fromEnvironment('FLUTTER_DART_VERSION')
75+
: null;
76+
}

dart/lib/src/event_processor/enricher/io_enricher_event_processor.dart

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import 'package:meta/meta.dart';
44

55
import '../../../sentry.dart';
66
import 'enricher_event_processor.dart';
7+
import 'flutter_runtime.dart';
78
import 'io_platform_memory.dart';
89

910
EnricherEventProcessor enricherEventProcessor(SentryOptions options) {
@@ -63,12 +64,15 @@ class IoEnricherEventProcessor implements EnricherEventProcessor {
6364
version: _dartVersion,
6465
rawDescription: Platform.version,
6566
);
67+
final flRuntime = flutterRuntime;
68+
6669
if (runtimes == null) {
67-
return [dartRuntime];
70+
return [dartRuntime, if (flRuntime != null) flRuntime];
6871
}
6972
return [
7073
...runtimes,
7174
dartRuntime,
75+
if (flRuntime != null) flRuntime,
7276
];
7377
}
7478

dart/lib/src/event_processor/enricher/web_enricher_event_processor.dart

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import 'package:web/web.dart' as web show window, Window, Navigator;
22

33
import '../../../sentry.dart';
44
import 'enricher_event_processor.dart';
5+
import 'flutter_runtime.dart';
56

67
EnricherEventProcessor enricherEventProcessor(SentryOptions options) {
78
return WebEnricherEventProcessor(
@@ -27,6 +28,7 @@ class WebEnricherEventProcessor implements EnricherEventProcessor {
2728
final contexts = event.contexts.copyWith(
2829
device: _getDevice(event.contexts.device),
2930
culture: _getSentryCulture(event.contexts.culture),
31+
runtimes: _getRuntimes(event.contexts.runtimes),
3032
);
3133

3234
contexts['dart_context'] = _getDartContext();
@@ -98,6 +100,23 @@ class WebEnricherEventProcessor implements EnricherEventProcessor {
98100
timezone: culture?.timezone ?? DateTime.now().timeZoneName,
99101
);
100102
}
103+
104+
List<SentryRuntime> _getRuntimes(List<SentryRuntime>? runtimes) {
105+
final flRuntime = flutterRuntime;
106+
final dartFlRuntime = dartFlutterRuntime;
107+
108+
if (runtimes == null) {
109+
return [
110+
if (flRuntime != null) flRuntime,
111+
if (dartFlRuntime != null) dartFlRuntime,
112+
];
113+
}
114+
return [
115+
...runtimes,
116+
if (flRuntime != null) flRuntime,
117+
if (dartFlRuntime != null) dartFlRuntime,
118+
];
119+
}
101120
}
102121

103122
extension on web.Navigator {
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import 'package:flutter_test/flutter_test.dart';
2+
import 'package:sentry/src/event_processor/enricher/flutter_runtime.dart';
3+
4+
void main() {
5+
group(FlutterVersion, () {
6+
test('FlutterVersion.version contains the current version', () {
7+
expect(FlutterVersion.version,
8+
const String.fromEnvironment('FLUTTER_VERSION'));
9+
});
10+
11+
test('FlutterVersion.channel contains the current channel', () {
12+
expect(FlutterVersion.channel,
13+
const String.fromEnvironment('FLUTTER_CHANNEL'));
14+
});
15+
16+
test('FlutterVersion.gitUrl contains the current git URL', () {
17+
expect(FlutterVersion.gitUrl,
18+
const String.fromEnvironment('FLUTTER_GIT_URL'));
19+
});
20+
21+
test(
22+
'FlutterVersion.frameworkRevision contains the current framework revision',
23+
() {
24+
expect(
25+
FlutterVersion.frameworkRevision,
26+
const String.fromEnvironment('FLUTTER_FRAMEWORK_REVISION'),
27+
);
28+
});
29+
30+
test('FlutterVersion.engineRevision contains the current engine revision',
31+
() {
32+
expect(FlutterVersion.engineRevision,
33+
const String.fromEnvironment('FLUTTER_ENGINE_REVISION'));
34+
});
35+
36+
test('FlutterVersion.dartVersion contains the current Dart version', () {
37+
expect(FlutterVersion.dartVersion,
38+
const String.fromEnvironment('FLUTTER_DART_VERSION'));
39+
});
40+
}, skip: !(const bool.hasEnvironment('FLUTTER_VERSION')));
41+
}

0 commit comments

Comments
 (0)