andypearson
Hey all,
I have been working on some performance improvements for the Phoenix application I work on.
As part of this, through trial and error I have discovered some very slow renders happening within assign_async in some of our dashboard screens. When the screens were implemented the performance was acceptable, but as the data behind the scenes has grown the time taken to render each part of the page has increased.
At the moment we are able to profile our performance using newrelic/elixir_agent, which uses the LiveView Telemetry events to collect transaction and span data.
However, unless I am missing something, the start and end of assign_async actually completing the work is not available to Telemetry.
My request is that the following new Telemetry events are added so that it’s possible to get visibility over assign_async:
[:phoenix, :live_view, :assign_async, :start][:phoenix, :live_view, :assign_async, :stop][:phoenix, :live_view, :assign_async, :exception]
These follow the existing naming conventions and would allow tools like the NewRelic agent to collection the associated timings.
I must admit I’m fairly new to a lot of this, so there may be a better way of doing what I want that already existing within LiveView.
There is an associated thread on GitHub where I have been talking with one of the maintainers of the NewRelic agent which may help with additional context: Problems getting metrics on LiveView async actions · Issue #550 · newrelic/elixir_agent · GitHub
Thanks for reading!
Trending in Proposals: Ideas
Other Trending Topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #library
- #deployment
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #podcasts
- #javascript
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixirconf-us
- #blog-post
- #ai
- #elixir-ls
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #hex
- #security
- #metaprogramming










Showing Posts 1 to 7- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
lessless
Hey Andy!
This looks like a very welcome addition. Is there a chance that an issue in the LV repo would get a better attention to the matter?
rhcarvalho
Hi! Something in that direction sounds like a reasonable ask!
I’m commenting to point out that depending on what you want to measure, the actual instrumentation needs to happen at different places/points in time.
The other telemetry events are centered around callbacks defined in the
Phoenix.LiveViewmodule. So they measure your callback implementations.The
assign_asyncfunction is a convenience built on top ofassign,AsyncResult,Task,start_asyncand thehandle_asynccallback.One might be interested in measuring:
Tasktook. This relates to the function you pass toassign_asyncorstart_async.handle_asynccallback took. This measures what is done after the task returns.If this doesn’t get added to LiveView, or in any case before it does, you could add your own telemetry events by implementing your own version of
assign_asyncwhich emits events at the points you care about. You could then update yourmyapp_web.exproject file to shadow LiveView’s function with yours an with this small change add instrumentation to all your LiveViews without touching their source code.rhcarvalho
This forum is the recommended venue for proposals like this. The GitHub issue tracker is used for bugs.
See
andypearson
@rhcarvalho thanks for your thoughtful reply!
I agree that it would be possible to implement my own version of
assign_asyncthat could track the time theTasktakes to run, in fact, the NewRelic agent already implementsNewRelic.Instrumented.Taskthat I think would do the trick.I was nervous about this approach because I am going to end up duplicating core framework behaviour that I would prefer to avoid, and also that I would need to make sure that everyone in the team migrates to the instrumented version.
With that in mind, you mention:
This sounds very interesting and could be a good option, as it solves the second problem.
Where can I find an example of this “shadowing” approach? My background is in Ruby so I’m used to patching open classes, I didn’t know that was possible in Elixir?
rhcarvalho
Hey, @andypearson I share a hackish starting point for you to play with:
Phoenix.LiveViewimplementation and augment it:MyAppWeb” module with the override:Relevant docs: Kernel.SpecialForms — Elixir v1.20.2
Don’t let me discourage you to pursue changes in Phoenix/LiveView. Considering
assign_asyncis a convenience on top of other primitives, I think telemetry events targeting those would be more generally applicable and solve for bothassign_asyncandstart_asyncuse cases.Of those I’d guess
Taskinstrumentation would be the most interesting. I haven’t used NewRelic with Elixir, maybe making sure your tasks are instrumented would be the biggest win?andypearson
@rhcarvalho I haven’t had a chance to play with this yet, but thanks so much for the detailed write up.
I’ve never thought about using
import except:to change what functions get pulled in from a “core” module. Really nice!steffend
I think the approach shown by @rhcarvalho is a good solution. I’m not against adding telemetry events, but I’m hesitant because the async operations we have are assign_async, start_async and stream_async, and adding separate events for all three feels a bit much? But if we’d only have them for handle_async, it would also feel incomplete, although it would fit to other events being tied to callbacks (mount, handle_event). So yeah, maybe explicitly wrapping when necessary is the best approach for now.