-
Notifications
You must be signed in to change notification settings - Fork 0
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: UIKit instrumentation now sets the current view #26
feat: UIKit instrumentation now sets the current view #26
Conversation
c24b3dc
to
41dd09f
Compare
b1b756a
to
1f31d5e
Compare
var storyboardId: String? { | ||
return value(forKey: "storyboardIdentifier") as? String | ||
} |
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.
AFAICT, Apple doesn't actually document this, but StackOverflow to the rescue again
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.
In my experience with fields like this, it falls into a gray area. You're not really supposed to do it, but you're not really supposed to swizzle either, and it may break at any time. I don't really have a problem with us doing it, as one of several possible names, but I wouldn't want to rely on it too highly either... I'll reference this in the other comments.
} | ||
|
||
private var viewName: String { | ||
return self.view.accessibilityIdentifier ?? self.storyboardId ?? self.title |
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 think this should be:
return self.view.accessibilityIdentifier
?? self.title
?? self.storyboardId
?? NSStringFromClass(type(of: self))
From the debugger:
(lldb) po self.storyboardId
▿ Optional<String>
- some : "UIViewController-Y6W-OH-hqX"
(lldb) po self.title
▿ Optional<String>
- some : "UIKit Screen"
So I do think the title
is better than the questionable storyboardId
.
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 problem with this is that UINavigationController
acquires the title of its root stack, so you end up with this fun duplication of names:
(the first UIKit Menu
refers to the root UINavigationController
controlling the whole thing, the second refers to the view it's displaying)
whereas doing storyboardId
first gives us
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 don't know how confusing this would be for our users, or maybe I configured the storyboard incorrectly...
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 spent some time thinking about this, but didn't reach any conclusion. It seems that there are several conflicting constraints:
- Listing the
UINavigationController
in the path with the same name as the child view kinda sucks. - Listing
"UIViewController-Y6W-OH-hqX"
in the path instead of the actual title kinda sucks. - Relying too much on the undocumented, unsupported
storyboardId
field is relatively risky.
So then I think we have these options:
- Prefer
storyboardId
totitle
, and encourage use of theaccessibilityIdentifier
override. - Prefer
title
tostoryboardId
, and accept that part of the path is not useful. If we switch to using just the last thing in the path as thescreen.name
, maybe this is less of an issue? - Special-case our logic so that for
UINavigationController
, we preferstoryboardId
, while for other controllers, we prefertitle
. We'd have to investigate other common controllers to see how they behave, although we should probably do that anyway.
I think I prefer Option 3 > 2 > 1, but I'm open to discussion.
screen_attr=$(attribute_for_span_key "@honeycombio/instrumentation-uikit" "Touch Began" "screen.name" string | uniq) | ||
screen_attr=$(attributes_from_span_named "@honeycombio/instrumentation-uikit" "Touch Began" \ | ||
| jq "select (.key == \"screen.name\")" \ | ||
| jq "select (.value.stringValue == \"SwiftUI.UIKitTabBarController/UIKitNavigationRoot/UI KIT SCREEN OVERRIDE\").value.stringValue" \ |
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 think it would be better to remove the accessibilityIdentifier
from this particular view, and have a second view at the same place in the view hierarchy that does have an accessibilityidentifier
, so that we can test both flows for deriving the path. But I'm open to alternatives, if there's an easier way to test it.
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.
Well the view before this one doesn't have an accessiblityIdentifier
...ie. we're already doing this. I can add a test for the touch began for the "go to ui kit app" button on that screen.
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 think that's fine, it just seems like we'd want to catch something being named like "UIViewController-Y6W-OH-hqX" in a test. The fact that it's an unpredictable name seems like a problem to me. I guess it depends on the resolution of the precedence discussion.
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 fact that it's an unpredictable name seems like a problem to me.
It's unpredictable but it will be consistent; the id is (randomly?) generated once when we add the view controller to the storyboard but it is encoded in the storyboard file.
smoke-tests/smoke-e2e.bats
Outdated
| jq "select (.value.stringValue == \"SwiftUI.UIKitTabBarController/UIKitNavigationRoot/UI KIT SCREEN OVERRIDE\").value.stringValue" \ | ||
| uniq | ||
) | ||
assert_equal "$screen_attr" '"SwiftUI.UIKitTabBarController/UIKitNavigationRoot/UI KIT SCREEN OVERRIDE"' |
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.
Just a thought, and please feel free to push back, but do you think we should have screen.name
as a whole path like this, or do you think it would be better to have screen.path
and screen.name
as separate fields where the name is the last segment of the path? I dunno, I don't want to complicate things, so we could just do this and revisit it later. I think the main question is how the name looks in the timeline analysis UI.
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.
That sounds reasonable, would match what we get from the manual instrumentation on the SwiftUI side.
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.
done in 6dd5460
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.
Looks good to me!
Which problem is this PR solving?
UIKit Instrumentation was emitting
viewDidAppear
andviewDidDisappear
events, but wasn't persisting the "current screen" value as the SwiftUI Navigation instrumentation did in #23Short description of the changes
UIKit Instrumentation now tracks the "current screen" value
Computing "current screen" is a little complex but tldr we use the following (in order of precedence):
accessiblityIdentifier
view.title
honeycombIdentifier
is provided as an escape hatch for clients to opt out of this precedence chain and set some explicit valueThis PR also updates our smoke test app to use nested UIKit navigations as a way to exercise the "current screen" computations.
Note that we don't do anything in the
viewDidDisappear
event: I considered setting the current screen tonil
but opted against that becauseviewDidDisappear
would run after View B'sviewDidAppear
. Thus setting current screen tonil
would actually clobber the (now correct) value corresponding to whatever we get from View BHow to verify that this has the expected result