Callback graph improvements

Hi all,

The callback graph is an indispensable tool for troubleshooting, but the bigger the graphs get, the harder it becomes to get around and to use it effectively.

I wanted to share some of the improvements I am currently working on regarding the callback graph .

My main idea for this post is to:

  • discuss how people currently use it and which parts/improvements they would like to see
  • get feedback on the improvements made / proposed improvements (see further)

Currently basic search functionality and filtering of non-zero callback counts with dynamic updates are mostly working
search
hideZeroCount

Additional ideas for implementation/improvement:

  • toggle for threshold marking with a configurable thresholds (e.g. highlight > 300ms)
  • introduce absolute min / max values for call-backs stats, besides the currently average-only numbers
  • research if there is a way to implement/define a “friendly name” for pattern matching callbacks
    (currently there is only an auto-generated UUID, which doesn’t tell us much)
  • research if there is a way to have a marking/naming of callback as per the page of a multi-page app they are in/running
    (less important and not even sure if its possible at all)
  • Export to PNG / JPG (not very important, since a screen grab tool can be used to achieve the same)

Discarded / postponed ideas:

  • filter for client vs server side callbacks (some subtrees have mixed client/server callbacks which would complicate things)

Known issues and limitations:
- there is currently no sync between what is on-screen / what is searchable / layout options → planned to be fixed
- sometimes minor layout artifacts pattern matching callbacks) happen during dynamic updates
not too bad since they are resolved the next update.
- there is a 1s + processing min update delay between activity and actual updates.
multiple layout updates are optimized, but adds more time to the actual update

Thanks,
J.

7 Likes

Thank you for working on this @jcuypers . Looks like this will help a lot.

I look forward to talking to you about this next week.

1 Like

Alright. Just brainstorming here, I have thoughts on how to implement these requests. :grin:

To make this an even more useful tool:

  • pop out mode, where the graph gets displayed into a new window, obviously this helps with the app’s visibility and the graphs usability
  • ability to show the last x used callbacks, using an exclude or include of types
  • highlight on the screen the different triggers, states and outputs of the hovered / selected callbacks
  • change the callbacks to be tiered based upon their actual call, instead of all side by side
  • possibility to display the last transaction of the selected callback
2 Likes

Hi,

Thanks for the input.

Many of your points aim towards a “redux-like” audit-trail type of functionality for the callbacks. who / what / when / how much … for a longer period in time (question: as of opening the callback graph, or since the app started)?

How far in detail do you want to go? do we need / can we track the actual request data/replies?

I think it would be good to brainstorm where we can get all this information and if if isn’t currently available, how we would go about it (in a way that it would be flexible for the future).

Pardon my ignorance, but is this an enterprise feature?

No, Why? it’s just ideas for improving the debug (Debug=True) mode when you develop the app. There is a button with callback which pops up a graph representation of the callback tree. The aim is the improve it since its bare minimums now (although not badly done:)

A couple ideas I’d love to see (thrilled you have a search feature already going!)

  • Function names are attached to green nodes. I should be able to see which functions are attached to which callback, as it’s likely easier to identify a callback by its function name than by its inputs/outputs (since outputs cannot be shared, of course I can dig and get back to the unique root, but… this is hard)
  • Better performance analytics. You can currently see how long the most recent run of a callback took as part of the green node. This is incredibly useful. Why not take this further… On clicking a node, I can see a full profile of the last run of that callback, specifically which lines inside the callback took the longest. There are ways to do this manually but it’d be great as native functionality
  • Ability to split it into a different tab. Maybe out of scope here, but you can’t look at the callback graph and your app at the same time. Allow the callback graph to be viewed in a second window (or maybe even all the debug tools) so it’s easier to compare the graph to your user interactions without constantly flipping it on and off.

Amazing stuff and glad you’re taking initiative here! Looking forward to seeing what you come up with.

3 Likes

These improvements sound great! What I’d like to see is the ability to do logging in Python with e.g. app.log("hi there") or somesuch, and have those (in debug mode only!) set over to the client so I can see per-callback logging in dev tools, rather than in the console where they’re all intermingled :slight_smile:

2 Likes
  • toggle for threshold marking with a configurable thresholds (e.g. highlight > 300ms)

I really like this idea and I think it would be great if this allowed me to configure thresholds for the total/compute/network info independently

1 Like

Now I get it. This looks so nice!

Looks SO good @jcuypers ! Really excited that you are digging in here.

Some things on my wishlist :slightly_smiling_face:

  • Only display visible callbacks - By default, only show the callbacks that correspond to elements that are currently rendered. So in a multi-page app, don’t show the callbacks from the other pages. Have a radio items toggle between “Show All Callbacks” vs “Show Visible Callbacks”
  • Table view - Display the callback history in a table that’s ordered by runtime. I still find that I’ll use the browser’s network requests for advanced debugging but that’s a pain and undiscoverable for most users. Imagine if there was a table (with sortable headers!) with: columns like:
Inputs Outputs Runtime Payload Timestamp
dropdown1.value graph1.figure 3.2s 5MB 19:31:21.4312
dropdown2.value graph2.figure 3.4s 3MB 19:31:33.1285
dropdown3.value graph3.figure
graph4.figure
3.1s 6MB 19:31:38.3214

I honestly might not even use the network graph if I had a clean table view!

5 Likes

I was thinking along those lines to.

I’d be nice to replace all of those things that we’ve used debugging through the years and bring them into this tool.

I really like @nathandrezner’s idea about the ability to split into a different tab or window. :wink:

2 Likes

Another idea by a colleague:

  • Replay - Ability to replay a request with the same payload. So that you could make a change in your code (fix a bug, add a print statement, etc) and then retry the same request without needing to re-enter the UI parameters.
3 Likes

Hi thanks for all the suggestions and ideas :smiling_face: let’s see where we get with this :slight_smile:

Hi, yes I thought about the same :slight_smile: but to be able to replay after a code change is something entirely different.
I have still limited understanding of where everything is, but I see the following issues:
The callback graph is built dynamically from data pulled from the redux store. Which in it’s nature offers some form of history and playback. This information is temporary to the lifetime of the app.
There is no way to get to this information outside of that or after restarting the app.

Trying to overcome those limitations poses other problems:

  • many applications have big data requirements
    • It would be impossible to store 100,of MBs or some GBs for whenever they would like to replay
  • some apps have specific data needs
    • We are not going to have a backlog of data for uploaded pictures or documents . Would not be safe anyways…
    • Where to store this data offline, if redux dissappears.
  • structure of the app most of the time changes
    • Diminishing the overal effectiveness of this feature, since the is no match to what’s active. Building on this, the replay would mean it would need to re-appear in the actual callback graph history and would need to match something.
  • a callback event is mostly not a standalone event:
    • This means that when you tweak your app and want to run some callback / past event … Even if you even have it… You need to respect the initialization state of the modified app, since you don’t know what changed,. Then if you want to run callback 100, there might be a problem since the chain might have been started at callback 99 ,(like set output/data,) for callback 100. Even further, 100 might need to whole chain up to 1 to do anything useful including props changes.

Maybe something to try in a basic form in the future, but I think it would be hard.