-
-
Notifications
You must be signed in to change notification settings - Fork 239
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
Feat View hierarchy #1189
Feat View hierarchy #1189
Conversation
Instructions and example for changelogPlease add an entry to Example: ## Unreleased
- Feat View hierarchy ([#1189](https://github.com/getsentry/sentry-dart/pull/1189)) If none of the above apply, you can opt out of this check by adding |
Codecov Report
Additional details and impacted files@@ Coverage Diff @@
## v7.0.0 #1189 +/- ##
=========================================
Coverage ? 88.02%
=========================================
Files ? 122
Lines ? 3816
Branches ? 0
=========================================
Hits ? 3359
Misses ? 457
Partials ? 0 Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here. ☔ View full report at Codecov. |
|
||
SentryViewHierarchy? toSentryViewHierarchy() { | ||
final rootNode = _toSentryViewHierarchyElement(rootElement); | ||
rootElement.visitChildElements(_visitor(rootNode)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ueman so the result of this for simple screens is quite deep in-depth, and it looks way more deeper in depth than the view hierarchy of the dev tooling, have you noticed that, or did I mess up something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately yes. See getsentry/team-mobile#64 (comment) for some ideas on how to tackle that.
Edit: Copied it over:
The view hierarchy in Flutter is way deeper than those of Android and iOS. Classes of views (views are called widgets in Flutter) prefixed with a
_
are private (that's how it works in Dart). It might be worth to ignore private classes since you most probably can't look them up in docs and so on. Public children of private classes should be shown again, though. Private classes are often used to improve the structuring of a widget, so they are kinda an implementation detail. Classes not prefixed with an underscore are public and one should be able to look them up in docs. Ignoring private classes is currently not done in my code. Also, you don't know whether a class is from user code, 3-party code or framework code, since there's no reflection/introspection in Dart. When enabling obfuscation in Flutter, the class names are of course not really human readable, but I guess that's similar for Android/iOS.In addition to the names of the widgets, you could also add the content of well known widgets like Text and *Buttons, as well as the on screen size and coordinates.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh indeed, missed that, thank you for sharing your thoughts, let me try this out.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if the _
check for private classes also works in obfuscated code
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will check, also found this https://docs.flutter.dev/development/tools/devtools/inspector#track-widget-creation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are also a few methods that print the tree, but only on debug mode https://docs.flutter.dev/testing/code-debugging#debug-flags-performance
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ueman That does not work when obfuscated is enabled because everything is renamed at compile time.
Still worth keeping this quick workaround; it improves at least when it's disabled.
@markushi @brustolin @krystofwoldrich early feedback is welcomed since it's a working solution already. |
if (instance == null) { | ||
return event; | ||
} | ||
final sentryViewHierarchy = walkWidgetTree(instance); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Being not too familiar with Flutter, it would be interesting to know:
- how fast walking the tree is
- if there are any multi-threading concerns (e.g. walking the tree whilst it get's modified)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dart is single-threaded, so no multi-threading concern, its also a sync call.
Running on debug mode (Profile mode isn't supported on iOS simulator, Debug is much slower) takes ~30ms
, for our sample app/main screen, this is dynamic because it depends on the app's view, so hard to measure.
Final JSON around ~50-60kb
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if there are any multi-threading concerns (e.g. walking the tree whilst it get's modified)
I actually think that's a valid concern because that's also a common problem when creating screenshots. Sometime you'll get an error which says it's not possible to create a screenshot because the current on screen content was already invalidated. But I also think it's something not a lot of people will run into, since it should be fast enough.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The feature is best effort, if for some reason you can't read the tree or take the screenshot, that's fine, there will be always a state that the framework won't allow you to do it, and we don't have control over that.
Looks good to me, nice one! Regarding the deep nesting: I'm wondering if it could make sense to aggregate certain "known" widgets. {
"opacity": 0.5,
"children": [{
"visible": true,
"children": [{
"identifier": "button_login"
}]
}]
} turns into {
"identifier": "button_login",
"opacity": 0.5,
"visible": true,
} |
I believe this should be an optimization for the FE, where we can fix/improve over time rather than changing on the SDK level and waiting for people to upgrade their SDKs before getting a meaningful view, but I agree whenever possible, the super nested view should be improved when debugging issues, but the SDK should report as it is. |
@krystofwoldrich its a Draft because there's a bug on Relay, but its ready to review, test are failing locally, working on them. |
I agree, that's something which could be done on FE! Looping in @narsaynorath |
flutter/lib/src/view_hierarchy/view_hierarchy_event_processor.dart
Outdated
Show resolved
Hide resolved
The CI is failing but otherwise looks good to me. |
CI should fail, that's expected (just the analyze) step. |
Is the event from your sample screenshot available in prod? I'd be interested in seeing how deep it actually ends up being. Seeing it would also help me understand the aggregated optimization mentioned above. When this example was provided:
is this form the result of ignoring the private views? And the idea to aggregate the children is because the private views will show up in the data as nodes, but without anything meaningful since we're ignoring them? Is there a chance that a private view contains two (or more) children or is it always a 1:1 relationship in those cases? |
Shared the JSON in the channel a few weeks ago. |
@krystofwoldrich @brustolin this is ready for final review. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM 🎉🚀🚀
I know I asked about the failing analyzer before, but why does it fail/why is it expected?
You can ignore this, it will be automatically solved once it's published. |
double? alpha; | ||
|
||
// Widget has to be RenderBox to have a size | ||
if (widget is RenderBox) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @marandaneto, is it possible that this should be
if (element.renderObject is RenderBox) {
instead?
@narsaynorath is seeing elements in the View Hierarchy which have a x/y
coordinate but no width/height
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right, #1258
📜 Description
View hierarchy as an attachment
💡 Motivation and Context
getsentry/team-mobile#64
💚 How did you test it?
📝 Checklist
🔮 Next steps