User Interaction Instrumentation
(New in version 6.17.0)
Enabling UI instrumentation captures transactions and adds breadcrumbs for a set of different user interactions, which include clicks, long clicks, taps, and so on.
Instrumentation Behaviour
Before diving into the configuration, it's important to understand how user interaction instrumentation behaves:
- The instrumentation sets the transaction name specified in the
key
of theWidget
from thekey
of theWidget
, for examplelogin_button
. - The transaction operation is set to
ui.action.click
. - If the user interaction transaction has reached the idleTimeout, but didn't have any child spans added, it will be dropped.
Prerequisites
Before starting, ensure:
- The Sentry Flutter SDK is initialized. Learn more here.
- Performance Monitoring is set up. Learn more here.
Configure
1. Wrap root widget
Wrap your root widget with SentryUserInteractionWidget
:
Future<void> main2() async {
await SentryFlutter.init(
// Configure your options
(options) => options.dsn = 'https://examplePublicKey@o0.ingest.sentry.io/0',
appRunner: () => runApp(SentryUserInteractionWidget(child: MyApp())),
);
}
2. Set a unique key for your widgets
If the view doesn't have the key assigned, the transaction and the breadcrumb won't be captured because it can't be uniquely identified. The key value should be unique across the whole application because the transactions are grouped by its name.
ElevatedButton(
key: const Key('my_button_widget'),
onPressed: () {
final activeSpan = Sentry.getSpan();
final childSpan = activeSpan?.startChild('some operation', description: 'some description');
childSpan?.finish();
}, child: const Text('User Interaction Example'),
),
Verify
Tap on the button specified in step 2 of the configure section, wait for idleTimeout
seconds (default is 3s) then check the performance page for a new transaction called my_button_widget
.
Handling Successive User Interaction Events
Default Behaviour
When a new user interaction occurs while a user interaction transaction is still in progress, the SDK automatically completes the ongoing transaction. This is necessary because only one transaction can be active in the scope at a time.
Interaction with the Same View
If the same view is interacted with again (e.g. clicking an ElevatedButton
repeatedly) within the idleTimeout
period then the SDK does the following:
- Resets the idle timer for the transaction.
- Extends the transaction’s duration by the length of the
idleTimeout
.
Additional Configuration
Disabling User Interaction Tracing
User interaction
enableUserInteractionTracing
option to false
.
import 'package:flutter/widgets.dart';
import 'package:sentry_flutter/sentry_flutter.dart';
Future<void> main() async {
await SentryFlutter.init(
(options) => options.enableUserInteractionTracing = false,
appRunner: () => runApp(SentryUserInteractionWidget(child: MyApp())),
);
}
Disabling User Interaction Breadcrumbs
User interaction breadcrumbs are enabled by default.
If you wish to opt-out of this feature set the enableUserInteractionBreadcrumbs
option to false
.
import 'package:flutter/widgets.dart';
import 'package:sentry_flutter/sentry_flutter.dart';
Future<void> main() async {
await SentryFlutter.init(
(options) => options.enableUserInteractionBreadcrumbs = false,
appRunner: () => runApp(SentryUserInteractionWidget(child: MyApp())),
);
}
Breadcrumb PII
By default, breadcrumbs exclude widget labels and text to avoid capturing personally identifiable information (PII).
To include these details, set the sendDefaultPii
option to true
.
import 'package:flutter/widgets.dart';
import 'package:sentry_flutter/sentry_flutter.dart';
Future<void> main() async {
await SentryFlutter.init(
(options) => options.sendDefaultPii = true,
appRunner: () => runApp(SentryUserInteractionWidget(child: MyApp())),
);
}
Transaction Timeout
The transaction finishes automatically after it reaches the specified idleTimeout and all of its child spans are finished.
The idleTimeoout
defaults to 3000
milliseconds (3 seconds).
Disable Timeout
You can also disable the idle timeout by setting it to null
, but if you do, you must finish the transaction manually.
To finish the transaction manually, use Sentry.getSpan()
to retrieve the active transaction on the scope:
import 'package:sentry/sentry.dart';
// Finish the transaction manually
final activeTransaction = Sentry.getSpan()
await activeTransaction?.finish();
Our documentation is open source and available on GitHub. Your contributions are welcome, whether fixing a typo (drat!) or suggesting an update ("yeah, this would be better").
- Package:
- pub:sentry_flutter
- Version:
- 7.14.0
- Repository:
- https://github.com/getsentry/sentry-dart
- API Documentation:
- https://pub.dev/documentation/sentry_flutter/latest/