Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clean up code #1878

Merged
merged 9 commits into from
Mar 4, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}

Expand Down
1 change: 1 addition & 0 deletions dart/lib/src/hint.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'sentry_attachment/sentry_attachment.dart';
import 'sentry_options.dart';

/// Hints are used in [BeforeSendCallback], [BeforeBreadcrumbCallback] and
/// event processors.
Expand Down
2 changes: 1 addition & 1 deletion dart/lib/src/sentry_client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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}}';
Expand Down
18 changes: 12 additions & 6 deletions dart/lib/src/sentry_stack_trace_factory.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -21,6 +21,10 @@ class SentryStackTraceFactory {
'sentry_logging',
'sentry_dio',
'sentry_file',
'sentry_hive',
'sentry_isar',
'sentry_sqflite',
'sentry_drift',
];

SentryStackTraceFactory(this._options);
Expand Down Expand Up @@ -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;
Expand All @@ -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) {
Expand Down
6 changes: 3 additions & 3 deletions dart/lib/src/sentry_tracer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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, {
Expand Down
222 changes: 118 additions & 104 deletions flutter/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -42,52 +42,58 @@ final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();

Future<void> 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<void> 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<void> 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 {
Expand Down Expand Up @@ -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),
),
);
}
}

Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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.',
Expand Down Expand Up @@ -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.',
Expand Down Expand Up @@ -758,18 +770,20 @@ class _IntegrationTestWidgetState extends State<IntegrationTestWidget> {

@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<void> _captureException() async {
Expand Down
3 changes: 2 additions & 1 deletion flutter/lib/src/integrations/screenshot_integration.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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> {
SentryFlutterOptions? _options;
ScreenshotEventProcessor? _screenshotEventProcessor;
Expand Down
Loading
Loading