User Interaction Instrumentation

(New in version 6.17.0)

The UI instrumentation, once enabled, captures transactions and adds breadcrumbs for a set of different user interactions, which include clicks, long clicks, taps, and so on. The SDK composes the transaction name from the key of the Widget that captured the user interaction (for example, login_button). The transaction operation is set to

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 otherwise.

The key value should be unique across the whole application because the transactions are grouped by its name.

The UI instrumentation

tracingThe process of logging the events that took place during a request, often across multiple services.
is an opt-out feature. The following example shows how to disable it:

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())),

The UI instrumentation breadcrumbs are enabled by default, but you can disable them by setting the enableUserInteractionBreadcrumbs option to false.

Breadcrumbs don't contain the Widget labels, text, and so on, since they might include PII. However, if you want to capture them, you can enable capturing this information by setting the sendDefaultPii option to true.

The transaction finishes automatically after it reaches the specified idleTimeout and all of its child spans are finished. The idleTimeoout defaults to 3000 milliseconds (three seconds). You can also disable the idle timeout by setting it to null, but the transaction must be finished manually in this case.

To finish the transaction manually, you can:

import 'package:sentry/sentry.dart';

final span = Sentry.getSpan()
await span?.finish();

Transactions are always bound to the Scope automatically if there's none set. Because of that, you can create spans using custom instrumentation, and those spans will be automatically associated with the running UI transaction.

import 'package:sentry/sentry.dart';

Future<void> loadUserDataOnClick() async {
  final span = Sentry.getSpan();
  final innerSpan = span?.startChild('loadUserData');
  // omitted code
  await innerSpan?.finish();

When the UI transaction is not finished yet, but the user makes a new interaction, the SDK automatically finishes the previous UI transaction. This is because only one transaction can be bound to the scope at a time. However, if the same view has been interacted with (for example, an ElevatedButton was clicked again within the idleTimeout window), the idle timer will be reset and the transaction duration will be extended with the idleTimeout value.

Help improve this content
Our documentation is open source and available on GitHub. Your contributions are welcome, whether fixing a typo (drat!) to suggesting an update ("yeah, this would be better").