Conversation
Add [:phoenix, :live_view, :handle_async] and [:phoenix, :live_component, :handle_async] spans around applying start_async, assign_async and stream_async results, mirroring the handle_event spans. Stale results that are ignored emit nothing.
Member
For start_async, that's not the case, since the result is not passed as metadata. Maybe we should add |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
LiveView emits telemetry spans for the callbacks that change a LiveView's or LiveComponent's state:
mount,handle_paramsandhandle_eventfor LiveViews,updateandhandle_eventfor LiveComponents. Async results are the exception. When astart_async/4result reacheshandle_async/3, or anassign_async/4orstream_async/4result is assigned, nothing is emitted.For LiveViews, the following
[:phoenix, :live_view, :render]span at least carries the updated socket. For LiveComponents, the only signal is that render span, whosesocketis the parent LiveView's. The component's new state can't be observed, and its change tracking is cleared by the render that follows.On
main, a single-file test that records every documented LiveView telemetry event shows the gap. A component loads data withassign_async/4andstart_async/4, and has a button:Motivation
I maintain PhoenixReplay, which records LiveView sessions and replays them by re-rendering the application's own templates with the recorded assigns. LiveComponents have no
on_mounthook, so it records component state from the documented component telemetry (update,handle_event,destroyed), with no changes to user components.A component that loads its data with
assign_async/4is recorded as loading for the rest of the session: the result is applied without telemetry, and the render that follows clears the component's__changed__. Loading data asynchronously is the recommended pattern for components, so this is common. The only workaround I found is to callPhoenix.LiveView.Debug.live_components/1from another process after each component render that no event explains. That copies every component's assigns, and it uses a debugging API for routine work.Beyond replay tools, these spans make async work observable like the other callbacks:
{:exit, reason},handle_async/3, which currently surface only as a crash.Change
Phoenix.LiveView.Async.handle_async/6is where every async result is applied, for LiveViews and LiveComponents, after stale results are discarded. It now wraps applying a result in a span:[:phoenix, :live_view, :handle_async, :start | :stop | :exception][:phoenix, :live_component, :handle_async, :start | :stop | :exception]Measurements and metadata follow the
handle_eventspans. Metadata issocket, plusname, the name given tostart_async/4orstream_async/4or the keys given toassign_async/4, andtype, which is:start,:assignor:stream. Component events also includecomponent. The:stopsocket is the socket after the result was applied.:exceptionaddskindandreason, sotypeis used rather thankindfor the async kind.Stale results, which LiveView already ignores (for example after
cancel_async/3or a newerstart_async/4with the same name), emit nothing.The telemetry guide documents the six events.
Tests
telemetry_test.exscovers LiveView and LiveComponent spans forstart_asyncandassign_asyncresults, and the:exceptionevent whenhandle_async/3raises. The last case adds one scenario toStartAsyncLive. The full Elixir suite passes.I know feature proposals usually start on the forum. I went with a small PR because the change mirrors the existing spans closely; I'm happy to move the discussion there, rename the events, or change the metadata.