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

Feature request: for debugging, would be very useful to know which reactive caused invalidation #1846

Open
daattali opened this issue Sep 8, 2017 · 8 comments

Comments

@daattali
Copy link
Contributor

daattali commented Sep 8, 2017

I'm not sure if this is possible, but if it is it could help tremendously when debugging larger apps. Sometimes a render or reactive code block gets called and you have no idea why--what reactive exactly caused it to execute. There isn't an easy way to do that kind of debugging in non trivial apps right now. The closest thing is the react graph log, which is awesome, but gets impossible to use for larger apps

@jcheng5
Copy link
Member

jcheng5 commented Sep 13, 2017

That's really interesting. Are you thinking a function which would return some kind of string or list based description, that you could do your own println-debugging with?

@daattali
Copy link
Contributor Author

Yes, I'm not sure or really care about the exact syntax, but something like this

foo <- reactive({
  cat("I'm here because", getInvalidatedReactive(), "was invalidated\n")
  x1()
  x2()
  x3()
  input$x1
  input$x2
})

Sometimes I see people's code where a large reactive is called multiple times (instead of once) and this sort of thing could really help speed up finding out the cause

@jcheng5
Copy link
Member

jcheng5 commented Sep 14, 2017

Note to self. Not which reactive, but the call stack that caused a dependency on the reactive. We care about the call site of taking the dependency, not the dependency itself. This should be collected only behind a flag because of the performance hit (collecting and formatting a stack on every reactive read).

@jcheng5
Copy link
Member

jcheng5 commented Sep 14, 2017

Call stack that is causing the invalidation may be good too, actually. In cases where an input is being updated due to a message being received by the client, not so helpful. But for stacks where observers set reactive values, it would be useful.

@Ploulackk2
Copy link

@daattali

Sometimes I see people's code where a large reactive is called multiple times (instead of once) and this sort of thing could really help speed up finding out the cause

That's exactly how i arrived here via Rstudio's community then StackOverflow...it literally this usage that today would have saved me so much time :)

@lisovyk
Copy link

lisovyk commented Jan 11, 2018

++
Would this kind of thing be possible in near future? Would be very handy.

@glin
Copy link

glin commented Jan 31, 2018

I've been experimenting with ways to do this without having to change Shiny. My first idea was based on @jcheng5's notes above - print the current call stack in the relevant upstream reactives, or in the observer onInvalidate callback. Example: https://gist.github.com/glin/aad1349f03e6c3f6e6af78e598f853f4

It kinda worked, but the stack trace lacked key info like inputs being set, or labels for the invalidated contexts. Maybe these are possible to get but I hit a dead end.

Second idea was to run a profiler and collect/parse the call stacks. This also worked in some cases, but wasn't reliable because of the sampling.

Last idea was to just parse it out of the reactive log. Similar to what @yonicd did, build the dependency graph in R, then follow the invalidated dependencies to figure out what caused invalidation. I used shiny:::getCurrentContext() to find the graph node for the current reactive and its most recently invalidated context.

https://github.com/glin/reactlog

options(shiny.reactlog = TRUE)

foo <- reactive({
  reactlog::traceInvalidation()
  x1()
})

This package also includes a way to list reactive dependencies in a tree view, since multiple dependencies can change, not just the one that caused invalidation.

And initial attempts at hacking some of @daattali and Joe's ideas from #1532 into the reactive log visualizer - filtering on graph nodes and jumping to the next flush cycle. But even with filtering, I think I still prefer to just look at a stack trace when working on larger apps.

Demos if you want to see how this looks:

@daattali
Copy link
Contributor Author

I know this isn't a sexy or fun feature, but I wanted to ping here to re-grab attention. I think this may not be as low priority as many of my other requests because this could immensely help debugging in large apps and save hours for many developers. I'm sure there are lots of apps out there that get invalidated way more than they need to, causing bad experiences for the users, but the developers simply could not figure out why and left it. I work with many clients and see this a lot :)

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

No branches or pull requests

5 participants