Skip to content
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

Expose call group chain information #160

Merged
merged 5 commits into from
Apr 3, 2024

Conversation

elihart
Copy link
Contributor

@elihart elihart commented Apr 1, 2024

Our app relies heavily on lots of decomposition within Compose UI in order to organize UI and promote code reuse. However, this means we have lots of Compose functions which are basically wrapper functions and there can be quite a lot of functional nesting like that.

I was quite confused for a while about why these functions didn't show up in the Radiography output, or would show up sporadically. If we have a ui module that exports a compose "component" we want that component name to identify the usage of the component in the radiography output. However, currently this doesn't reliably happen and instead we mostly see more primitive elements show up in the output scan.

The code comment on computeLayoutInfos thankfully explains why this happens - only the nodes that emit layouts are represented in the final output, and they inherit the name of the top most call group wrapping them. I can see why this was done, to prevent very verbose chains, but unfortunately it doesn't always result in the best output.

This PR tries to expose more granular information about these call chains so that users can optionally get more insight into what function calls were made. I also included the source location of these function calls so that our tooling can make use of that to make more educated guesses about which functions to surface (eg, if we know its a file in our project, include the call name). To acces this, there is now a property val callChain: List<CallGroupInfo> on ComposeView which can be used to get information about all of the call groups wrapping the layout node.

Usage can be seen inside the test: https://github.com/square/radiography/pull/160/files#diff-0a37f7ae94183d0cefb9e8ba89d53a9409011f55230e69ad4300cacee413734eR161

The original behavior in terms of which display names are used is unchanged, and in general there is no impact to existing users. This can be seen in the screenshot of the compose app before and after, and all existing tests pass without changes needed. I did add a test to verify the call chain information is captured correctly.

I hope that this additional capability is welcome, but I am open to suggestions about how to modify the approach to better fit the direction of the library.

Before:
radiography before

After: (note there are no differences)
radiograpy after

@elihart elihart requested review from pyricau, jamesmosley55 and a team as code owners April 1, 2024 18:51
@rjrjr
Copy link
Contributor

rjrjr commented Apr 2, 2024

So if I'm following you, the logs should be different if @OptIn(UiToolingDataApi::class) is used? Could you add an example of that to the commit message?

@elihart
Copy link
Contributor Author

elihart commented Apr 2, 2024

@rjrjr not quite, the current logs should not change at all, and current users won't need to opt in to UiToolingDataApi::class

What is new, is that there is now a property val callChain: List<CallGroupInfo> on ComposeView which can be used to get information about all of the call groups wrapping the layout node.

Usage can be seen inside the test https://github.com/square/radiography/pull/160/files#diff-0a37f7ae94183d0cefb9e8ba89d53a9409011f55230e69ad4300cacee413734eR161

If someone does want to use the sourceLocation property they will need to opt in to UiToolingDataApi::class. I considered that we may want to create a wrapper class to avoid this, but I think directly exposing this tooling class is fine because if it does change we would need to change the wrapper anyway in potentially breaking ways, and having the user opt in makes them aware of the source of the data and that it is potentially unstable.

@jamesmosley55 jamesmosley55 removed their request for review April 2, 2024 16:11
@rjrjr
Copy link
Contributor

rjrjr commented Apr 2, 2024

LGTM (and thanks!), but could you put that explanation in the kdoc for UiToolingDataApi?

.containsExactly("Call3", "Call2", "Call1", "BasicText", "Layout", "ReusableComposeNode")
assertThat(callGroup.callChain.map { it.location?.sourceFile })
.containsExactly("ComposeViewTest.kt", "ComposeViewTest.kt", "ComposeViewTest.kt", "ComposeViewTest.kt", "BasicText.kt", "Layout.kt")
}
Copy link
Contributor

@pyricau pyricau Apr 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test seems to be testing several things (at least 2) and should be broken up to test one thing per test.

@pyricau
Copy link
Contributor

pyricau commented Apr 2, 2024

Would you mind updating the README with examples of how to get one output vs the other more detailed output? I'm a little confused.

@elihart
Copy link
Contributor Author

elihart commented Apr 2, 2024

@rjrjr UiToolingDataApi is part of the androidx compose tooling library. Is there somewhere else you want me to put the documentation? I can update the readme as Py requested.

@rjrjr
Copy link
Contributor

rjrjr commented Apr 2, 2024

@rjrjr UiToolingDataApi is part of the androidx compose tooling library. Is there somewhere else you want me to put the documentation? I can update the readme as Py requested.

Nope, nevermind, I was being an idiot. I could have sworn I saw you introducing it in this PR.

@elihart
Copy link
Contributor Author

elihart commented Apr 3, 2024

@pyricau I've split the test and updated the readme with explanations and examples

@elihart elihart force-pushed the eli-add_call_chain_info branch from 09ee1ea to c92245b Compare April 3, 2024 16:25
Copy link
Contributor

@rjrjr rjrjr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is marvelous, thank you so much.

@elihart
Copy link
Contributor Author

elihart commented Apr 3, 2024

@rjrjr The instrumented tests for API 30 seem to be failing, but I believe it is unrelated to my changes. It looks like the last commit to main also failed like this

image

I ran the tests with an api 30 emulator locally and can't reproduce

@rjrjr
Copy link
Contributor

rjrjr commented Apr 3, 2024

@rjrjr The instrumented tests for API 30 seem to be failing, but I believe it is unrelated to my changes. It looks like the last commit to main also failed like this

I ran the tests with an api 30 emulator locally and can't reproduce

Welcome to our espresso hell. We'll figure it out.

@rjrjr
Copy link
Contributor

rjrjr commented Apr 3, 2024

I too can't reproduce this problem locally, on main or on Eli's branch. And I just had a green run of the test on another PR branch.

I do notice that the tests are taking a very long time to run, especially including AVD startup; and that (30) takes the longest. @RBusarow I'm inclined to try putting Radiography on the same paid testing set up that Workflow is on. The rate of change here is so low it's hard to imagine that being an issue. WDYT?

@rjrjr
Copy link
Contributor

rjrjr commented Apr 3, 2024

I too can't reproduce this problem locally, on main or on Eli's branch. And I just had a green run of the test on another PR branch.

I do notice that the tests are taking a very long time to run, especially including AVD startup; and that (30) takes the longest. @RBusarow I'm inclined to try putting Radiography on the same paid testing set up that Workflow is on. The rate of change here is so low it's hard to imagine that being an issue. WDYT?

Experimenting here: #161

@rjrjr
Copy link
Contributor

rjrjr commented Apr 3, 2024

It's very clearly a flake predating this work. I'm going to go ahead and merge it. And then we can play the "how do we release this thing again?" game!

@rjrjr rjrjr merged commit a32b0a8 into block:main Apr 3, 2024
6 of 7 checks passed
@RBusarow
Copy link
Contributor

RBusarow commented Apr 4, 2024

@RBusarow I'm inclined to try putting Radiography on the same paid testing set up that Workflow is on. The rate of change here is so low it's hard to imagine that being an issue. WDYT?

I completely agree. Good idea!

@rjrjr
Copy link
Contributor

rjrjr commented Apr 23, 2024

Hey @elihart, I think I finally fixed our CI. How would you like a release at long last?

@elihart elihart deleted the eli-add_call_chain_info branch April 24, 2024 04:41
@elihart
Copy link
Contributor Author

elihart commented Apr 24, 2024

A release would be great @rjrjr ! Thanks for following up :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants