From 4d05ee5ccf111bf7a132f371a2f1ad0fa0373c21 Mon Sep 17 00:00:00 2001 From: Bernardo Amorim Date: Sun, 12 Nov 2023 14:52:35 +0000 Subject: [PATCH] Emit live_component update events --- lib/phoenix_live_view/diff.ex | 38 +++++++++++++++---- .../integrations/telemetry_test.exs | 38 +++++++++++++++++++ test/support/live_views/components.ex | 4 ++ 3 files changed, 72 insertions(+), 8 deletions(-) diff --git a/lib/phoenix_live_view/diff.ex b/lib/phoenix_live_view/diff.ex index 03936d41be..701b7dc335 100644 --- a/lib/phoenix_live_view/diff.ex +++ b/lib/phoenix_live_view/diff.ex @@ -659,17 +659,39 @@ defmodule Phoenix.LiveView.Diff do end) assigns_sockets = Enum.reverse(assigns_sockets) + metadata = Enum.reverse(metadata) + update_many? = function_exported?(component, :update_many, 1) + + component_data= + assigns_sockets + |> Enum.zip(metadata) + |> Enum.map(fn {{assigns, socket}, {cid, _id, new?}} -> + %{ + assigns: assigns, + socket: socket, + cid: cid, + new?: new? + } + end) + + telemetry_metadata = %{socket: socket, component: component, component_data: component_data, update_many?: update_many?} sockets = - if function_exported?(component, :update_many, 1) do - component.update_many(assigns_sockets) - else - Enum.map(assigns_sockets, fn {assigns, socket} -> - Utils.maybe_call_update!(socket, component, assigns) - end) - end + :telemetry.span([:phoenix, :live_component, :update], telemetry_metadata, fn -> + sockets = + if update_many? do + component.update_many(assigns_sockets) + else + Enum.map(assigns_sockets, fn {assigns, socket} -> + Utils.maybe_call_update!(socket, component, assigns) + end) + end + + component_data = sockets |> Enum.zip(component_data) |> Enum.map(fn {socket, data} -> %{data | socket: socket} end) + + {sockets, Map.put(telemetry_metadata, :component_data, component_data)} + end) - metadata = Enum.reverse(metadata) triplet = zip_components(sockets, metadata, component, cids, {pending, diffs, components}) {triplet, seen_ids} end) diff --git a/test/phoenix_live_view/integrations/telemetry_test.exs b/test/phoenix_live_view/integrations/telemetry_test.exs index 00a540fdff..82d1454e1e 100644 --- a/test/phoenix_live_view/integrations/telemetry_test.exs +++ b/test/phoenix_live_view/integrations/telemetry_test.exs @@ -252,6 +252,44 @@ defmodule Phoenix.LiveView.TelemtryTest do assert metadata.component == Phoenix.LiveViewTest.StatefulComponent assert metadata.params == %{"op" => "boom"} end + + test "emits telemetry events for update calls", %{conn: conn} do + attach_telemetry([:phoenix, :live_component, :update]) + + {:ok, view, _html} = live(conn, "/multi-targets") + + assert_receive {:event, [:phoenix, :live_component, :update, :start], %{system_time: _}, + metadata} + + assert metadata.socket + assert metadata.component == Phoenix.LiveViewTest.StatefulComponent + + assert [ + %{ + cid: cid, + assigns: %{id: _id, name: name}, + socket: component_socket, + new?: true + }, + _ + ] = metadata.component_data + + assert is_integer(cid) + + assert_receive {:event, [:phoenix, :live_component, :update, :stop], %{duration: _}, + metadata} + + assert metadata.socket + assert metadata.component == Phoenix.LiveViewTest.StatefulComponent + assert [%{socket: updated_component_socket}, _] = metadata.component_data + + assert updated_component_socket != component_socket + + render_click(view, "disable", %{"name" => name}) + + assert_receive {:event, [:phoenix, :live_component, :update, :start], %{system_time: _}, + %{component_data: [%{new?: false, assigns: %{name: name, disabled: true}}]}} + end end describe "logging configuration" do diff --git a/test/support/live_views/components.ex b/test/support/live_views/components.ex index cdfec8d092..830f1b6aa2 100644 --- a/test/support/live_views/components.ex +++ b/test/support/live_views/components.ex @@ -323,6 +323,10 @@ defmodule Phoenix.LiveViewTest.WithMultipleTargets do def handle_event("transform", %{"op" => _op}, socket) do {:noreply, assign(socket, :message, "Parent was updated")} end + + def handle_event("disable", %{"name" => name}, socket) do + {:noreply, assign(socket, :disabled, Enum.uniq([name | socket.assigns.disabled]))} + end end defmodule Phoenix.LiveViewTest.WithLogOverride do