Skip to content

Commit 824df58

Browse files
authored
Add flag to disable reporting of view hierarchy identifiers (#2158)
* Add report view hierarchy identifier option * Update docs * Update CHANGELOG * Fix test * Formatting * Update CHANGELOG.md
1 parent 2d9f4e8 commit 824df58

6 files changed

+54
-10
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
### Features
66

7+
- Add flag to disable reporting of view hierarchy identifiers ([#2158](https://github.com/getsentry/sentry-dart/pull/2158))
8+
- Use `reportViewHierarchyIdentifiers` to enable or disable the option
79
- Record dropped spans in client reports ([#2154](https://github.com/getsentry/sentry-dart/pull/2154))
810
- Add memory usage to contexts ([#2133](https://github.com/getsentry/sentry-dart/pull/2133))
911
- Only for Linux/Windows applications, as iOS/Android/macOS use native SDKs

flutter/lib/src/sentry_flutter_options.dart

+8
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,14 @@ class SentryFlutterOptions extends SentryOptions {
213213
@experimental
214214
bool attachViewHierarchy = false;
215215

216+
/// Enables collection of view hierarchy element identifiers.
217+
///
218+
/// Identifiers are extracted from widget keys.
219+
/// Disable this flag if your widget keys contain sensitive data.
220+
///
221+
/// Default: `true`
222+
bool reportViewHierarchyIdentifiers = true;
223+
216224
/// When enabled, the SDK tracks when the application stops responding for a
217225
/// specific amount of time, See [appHangTimeoutInterval].
218226
/// Only available on iOS and macOS.

flutter/lib/src/view_hierarchy/sentry_tree_walker.dart

+11-4
Original file line numberDiff line numberDiff line change
@@ -209,9 +209,10 @@ import '../widget_utils.dart';
209209
class _TreeWalker {
210210
static const _privateDelimiter = '_';
211211

212-
_TreeWalker(this.rootElement);
212+
_TreeWalker(this.rootElement, this.options);
213213

214214
final Element rootElement;
215+
final SentryFlutterOptions options;
215216

216217
ValueChanged<Element> _visitor(
217218
SentryViewHierarchyElement parentSentryElement) {
@@ -278,10 +279,15 @@ class _TreeWalker {
278279
alpha = widget.opacity;
279280
}
280281

282+
String? identifier;
283+
if (options.reportViewHierarchyIdentifiers) {
284+
identifier = WidgetUtils.toStringValue(widget.key);
285+
}
286+
281287
return SentryViewHierarchyElement(
282288
element.widget.runtimeType.toString(),
283289
depth: element.depth,
284-
identifier: WidgetUtils.toStringValue(element.widget.key),
290+
identifier: identifier,
285291
width: width,
286292
height: height,
287293
x: x,
@@ -292,15 +298,16 @@ class _TreeWalker {
292298
}
293299
}
294300

295-
SentryViewHierarchy? walkWidgetTree(WidgetsBinding instance) {
301+
SentryViewHierarchy? walkWidgetTree(
302+
WidgetsBinding instance, SentryFlutterOptions options) {
296303
// to keep compatibility with older versions
297304
// ignore: deprecated_member_use
298305
final rootElement = instance.renderViewElement;
299306
if (rootElement == null) {
300307
return null;
301308
}
302309

303-
final walker = _TreeWalker(rootElement);
310+
final walker = _TreeWalker(rootElement, options);
304311

305312
return walker.toSentryViewHierarchy();
306313
}

flutter/lib/src/view_hierarchy/view_hierarchy_event_processor.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ class SentryViewHierarchyEventProcessor implements EventProcessor {
2323
if (instance == null) {
2424
return event;
2525
}
26-
final sentryViewHierarchy = walkWidgetTree(instance);
26+
final sentryViewHierarchy = walkWidgetTree(instance, _options);
2727

2828
if (sentryViewHierarchy == null) {
2929
return event;

flutter/test/view_hierarchy/sentry_tree_walker_test.dart

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import 'package:flutter/material.dart';
22
import 'package:flutter_test/flutter_test.dart';
3-
import 'package:sentry/sentry.dart';
3+
import 'package:sentry_flutter/sentry_flutter.dart';
44
import 'package:sentry_flutter/src/view_hierarchy/sentry_tree_walker.dart';
55

66
void main() {
@@ -16,7 +16,8 @@ void main() {
1616
await tester.runAsync(() async {
1717
await tester.pumpWidget(MyApp());
1818

19-
final sentryViewHierarchy = walkWidgetTree(instance);
19+
final sentryViewHierarchy =
20+
walkWidgetTree(instance, SentryFlutterOptions());
2021

2122
expect(sentryViewHierarchy!.renderingSystem, 'flutter');
2223
});
@@ -147,7 +148,8 @@ void main() {
147148

148149
SentryViewHierarchyElement _getFirstSentryViewHierarchy(
149150
WidgetsBinding instance) {
150-
final sentryViewHierarchy = walkWidgetTree(instance);
151+
final options = SentryFlutterOptions();
152+
final sentryViewHierarchy = walkWidgetTree(instance, options);
151153

152154
return sentryViewHierarchy!.windows.first;
153155
}

flutter/test/view_hierarchy/view_hierarchy_event_processor_test.dart

+27-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import 'dart:convert';
2+
13
import 'package:flutter/material.dart';
24
import 'package:flutter_test/flutter_test.dart';
35
import 'package:sentry/sentry.dart';
@@ -79,6 +81,27 @@ void main() {
7981
expect(hint.viewHierarchy, isNull);
8082
});
8183
});
84+
85+
testWidgets('does not add view hierarchy identifiers if opt out in options',
86+
(tester) async {
87+
await tester.runAsync(() async {
88+
final sut =
89+
fixture.getSut(instance, reportViewHierarchyIdentifiers: false);
90+
91+
await tester.pumpWidget(MyApp());
92+
93+
final event = SentryEvent(
94+
exceptions: [SentryException(type: 'type', value: 'value')]);
95+
final hint = Hint();
96+
97+
sut.apply(event, hint);
98+
99+
expect(hint.viewHierarchy, isNotNull);
100+
final bytes = await hint.viewHierarchy!.bytes;
101+
final jsonString = utf8.decode(bytes);
102+
expect(jsonString, isNot(contains('identifier')));
103+
});
104+
});
82105
});
83106
}
84107

@@ -99,9 +122,11 @@ class TestBindingWrapper implements BindingWrapper {
99122
}
100123

101124
class Fixture {
102-
SentryViewHierarchyEventProcessor getSut(WidgetsBinding instance) {
125+
SentryViewHierarchyEventProcessor getSut(WidgetsBinding instance,
126+
{bool reportViewHierarchyIdentifiers = true}) {
103127
final options = SentryFlutterOptions()
104-
..bindingUtils = TestBindingWrapper(instance);
128+
..bindingUtils = TestBindingWrapper(instance)
129+
..reportViewHierarchyIdentifiers = reportViewHierarchyIdentifiers;
105130
return SentryViewHierarchyEventProcessor(options);
106131
}
107132
}

0 commit comments

Comments
 (0)