Skip to content

Commit 492e32c

Browse files
authored
Backport: Fix traces filtering (#443)
1 parent b15deac commit 492e32c

File tree

5 files changed

+240
-19
lines changed

5 files changed

+240
-19
lines changed

dev/components.ex

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ defmodule LiveDebuggerDev.Components do
2626
"""
2727
end
2828

29+
attr(:id, :string, default: nil)
2930
attr(:title, :string, required: true)
3031
attr(:color, :string, default: "blue")
3132
attr(:class, :string, default: "")
@@ -34,7 +35,7 @@ defmodule LiveDebuggerDev.Components do
3435

3536
def box(assigns) do
3637
~H"""
37-
<div>
38+
<div id={@id}>
3839
<span class={"text-sm #{text_color(@color)}"}><%= @title %></span>
3940
<div class={"border-2 #{border_color(@color)} rounded-md p-8 #{@class}"}>
4041
<%= render_slot(@inner_block) %>

dev/live_components/conditional.ex

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,16 @@ defmodule LiveDebuggerDev.LiveComponents.Conditional do
55
{:ok, assign(socket, :show_child?, false)}
66
end
77

8+
attr(:id, :string, default: nil)
89
slot(:inner_block)
910

1011
def render(assigns) do
1112
~H"""
1213
<div>
13-
<.box title="Conditional [LiveComponent]" color="orange">
14+
<.box id={@id} title="Conditional [LiveComponent]" color="orange">
1415
<div class="flex flex-col gap-2">
1516
<div class="flex items-center gap-1">
16-
<.button phx-click="show_child" phx-target={@myself} color="orange">
17+
<.button id={@id <> "-button"} phx-click="show_child" phx-target={@myself} color="orange">
1718
Show
1819
</.button>
1920

lib/live_debugger/services/trace_service.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ defmodule LiveDebugger.Services.TraceService do
132132
[{{:_, %{function: :"$1"}}, to_spec(functions), [:"$_"]}]
133133
end
134134

135-
def to_spec([]), do: []
135+
def to_spec([]), do: [false]
136136

137137
def to_spec([single]), do: [{:"=:=", :"$1", single}]
138138

test/live_debugger/channel_dashboard_test.exs

Lines changed: 218 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ defmodule LiveDebugger.ChannelDashboardTest do
1313
debugger
1414
|> visit("/")
1515
|> click(first_link())
16-
|> assert_has(counter_in_assigns(text: "0"))
16+
|> assert_has(assigns_entry(key: "counter", value: "0"))
1717
|> assert_has(traces(count: 2))
1818

1919
dev_app
@@ -22,7 +22,7 @@ defmodule LiveDebugger.ChannelDashboardTest do
2222

2323
debugger
2424
|> assert_has(traces(count: 2))
25-
|> assert_has(counter_in_assigns(text: "2"))
25+
|> assert_has(assigns_entry(key: "counter", value: "2"))
2626
|> click(toggle_tracing_button())
2727

2828
dev_app
@@ -31,7 +31,7 @@ defmodule LiveDebugger.ChannelDashboardTest do
3131

3232
debugger
3333
|> assert_has(traces(count: 6))
34-
|> assert_has(counter_in_assigns(text: "4"))
34+
|> assert_has(assigns_entry(key: "counter", value: "4"))
3535
|> click(toggle_tracing_button())
3636
|> click(clear_traces_button())
3737
|> assert_has(traces(count: 0))
@@ -46,19 +46,230 @@ defmodule LiveDebugger.ChannelDashboardTest do
4646
|> assert_has(traces(count: 4))
4747
end
4848

49+
@sessions 2
50+
feature "user can change nodes using node tree and see their assigns and callback traces", %{
51+
sessions: [dev_app, debugger]
52+
} do
53+
LiveDebugger.GenServers.CallbackTracingServer.ping!()
54+
55+
dev_app
56+
|> visit(@dev_app_url)
57+
58+
debugger
59+
|> visit("/")
60+
|> click(first_link())
61+
|> click(conditional_component_4_node_button())
62+
|> find(css("#info"), fn info ->
63+
info
64+
|> assert_text("LiveComponent")
65+
|> assert_text("LiveDebuggerDev.LiveComponents.Conditional")
66+
end)
67+
|> assert_has(assigns_entry(key: "show_child?", value: "false"))
68+
|> assert_has(traces(count: 2))
69+
|> click(toggle_tracing_button())
70+
71+
dev_app
72+
|> click(button("conditional-button"))
73+
74+
debugger
75+
|> assert_has(many_assigns_14_node_button())
76+
|> assert_has(assigns_entry(key: "show_child?", value: "true"))
77+
|> assert_has(traces(count: 4))
78+
|> click(conditional_component_5_node_button())
79+
|> click(conditional_component_4_node_button())
80+
|> assert_has(assigns_entry(key: "show_child?", value: "true"))
81+
|> assert_has(traces(count: 4))
82+
end
83+
84+
@sessions 2
85+
feature "user can filter callback traces", %{sessions: [dev_app, debugger]} do
86+
LiveDebugger.GenServers.CallbackTracingServer.ping!()
87+
88+
dev_app
89+
|> visit(@dev_app_url)
90+
91+
debugger
92+
|> visit("/")
93+
|> click(first_link())
94+
|> assert_has(traces(count: 2))
95+
|> click(toggle_tracing_button())
96+
97+
dev_app
98+
|> click(button("send-button"))
99+
|> click(button("send-button"))
100+
101+
debugger
102+
|> assert_traces(6, [
103+
"render/1",
104+
"handle_info/2",
105+
"render/1",
106+
"handle_info/2",
107+
"render/1",
108+
"mount/3"
109+
])
110+
|> click(toggle_tracing_button())
111+
|> click(filters_button())
112+
|> click(checkbox("mount"))
113+
|> click(checkbox("render"))
114+
|> click(css("button", text: "Apply (7)"))
115+
|> assert_traces(2, [
116+
"handle_info/2",
117+
"handle_info/2"
118+
])
119+
120+
dev_app
121+
|> click(button("increment-button"))
122+
|> click(button("increment-button"))
123+
124+
debugger
125+
|> click(refresh_button())
126+
|> assert_traces(4, [
127+
"handle_event/3",
128+
"handle_event/3",
129+
"handle_info/2",
130+
"handle_info/2"
131+
])
132+
|> click(toggle_tracing_button())
133+
134+
dev_app
135+
|> click(button("send-button"))
136+
|> click(button("send-button"))
137+
138+
debugger
139+
|> assert_traces(6, [
140+
"handle_info/2",
141+
"handle_info/2",
142+
"handle_event/3",
143+
"handle_event/3",
144+
"handle_info/2",
145+
"handle_info/2"
146+
])
147+
|> click(toggle_tracing_button())
148+
|> click(filters_button())
149+
|> click(reset_filters_button())
150+
|> click(css("button", text: "Apply (9)"))
151+
|> assert_traces(14, [
152+
"render/1",
153+
"handle_info/2",
154+
"render/1",
155+
"handle_info/2",
156+
"render/1",
157+
"handle_event/3",
158+
"render/1",
159+
"handle_event/3",
160+
"render/1",
161+
"handle_info/2",
162+
"render/1",
163+
"handle_info/2",
164+
"render/1",
165+
"mount/3"
166+
])
167+
|> click(filters_button())
168+
|> click(checkbox("mount"))
169+
|> click(checkbox("handle_params"))
170+
|> click(checkbox("handle_info"))
171+
|> click(checkbox("handle_call"))
172+
|> click(checkbox("handle_cast"))
173+
|> click(checkbox("terminate"))
174+
|> click(checkbox("render"))
175+
|> click(checkbox("handle_event"))
176+
|> click(checkbox("handle_async"))
177+
|> click(css("button", text: "Apply"))
178+
|> assert_has(traces(count: 0))
179+
end
180+
181+
defp assert_traces(session, count, callback_names) do
182+
session
183+
|> find(traces(count: count))
184+
|> Enum.zip(callback_names)
185+
|> Enum.each(fn {trace, callback_name} ->
186+
trace |> assert_text(callback_name)
187+
end)
188+
189+
session
190+
end
191+
192+
@sessions 2
193+
feature "user can inspect arguments of executed callback", %{sessions: [dev_app, debugger]} do
194+
LiveDebugger.GenServers.CallbackTracingServer.ping!()
195+
196+
dev_app
197+
|> visit(@dev_app_url)
198+
199+
debugger
200+
|> visit("/")
201+
|> click(first_link())
202+
|> click(toggle_tracing_button())
203+
204+
dev_app
205+
|> click(button("increment-button"))
206+
|> click(button("send-button"))
207+
208+
[render3_trace, send_trace, render2_trace, increment_trace, render1_trace, _] =
209+
debugger
210+
|> find(traces(count: 6))
211+
212+
render1_trace
213+
|> click(css("summary"))
214+
|> assert_has(map_entry(key: "datetime", value: "nil"))
215+
|> assert_has(map_entry(key: "counter", value: "0"))
216+
217+
increment_trace
218+
|> click(css("summary"))
219+
|> assert_text("handle_event/3")
220+
|> assert_text("increment")
221+
222+
render2_trace
223+
|> click(css("summary"))
224+
|> assert_has(map_entry(key: "datetime", value: "nil"))
225+
|> assert_has(map_entry(key: "counter", value: "1"))
226+
227+
send_trace
228+
|> click(css("summary"))
229+
|> assert_text("handle_info/2")
230+
|> assert_text(":new_datetime")
231+
232+
render3_trace
233+
|> click(css("summary"))
234+
|> assert_has(map_entry(key: "datetime", value: "~U["))
235+
|> assert_has(map_entry(key: "counter", value: "1"))
236+
end
237+
49238
defp first_link(), do: css("#live-sessions a", count: 1)
50239

51-
defp counter_in_assigns(text: text) do
240+
defp assigns_entry(key: key, value: value) do
52241
xpath(
53-
".//*[@id=\"assigns\"]//*[contains(normalize-space(text()), \"counter:\")]/../*[contains(normalize-space(text()), \"#{text}\")]"
242+
".//*[@id=\"assigns\"]//*[contains(normalize-space(text()), \"#{key}:\")]/../*[contains(normalize-space(text()), \"#{value}\")]"
54243
)
55244
end
56245

57-
defp traces(opts), do: css("#traces-list-stream details", opts)
246+
defp map_entry(key: key, value: value) do
247+
xpath(
248+
".//*[contains(normalize-space(text()), \"#{key}:\")]/../*[contains(normalize-space(text()), \"#{value}\")]"
249+
)
250+
end
58251

59-
defp refresh_button(), do: css("button[phx-click=\"refresh-history\"]")
252+
defp traces(opts), do: css("#traces-list-stream details", opts)
60253

61254
defp toggle_tracing_button(), do: css("button[phx-click=\"switch-tracing\"]")
62255

256+
defp refresh_button(), do: css("button[phx-click=\"refresh-history\"]")
257+
63258
defp clear_traces_button(), do: css("button[phx-click=\"clear-traces\"]")
259+
260+
defp filters_button(), do: css("#filters-dropdown-button")
261+
262+
defp reset_filters_button(), do: css("button[phx-click=\"reset\"]")
263+
264+
defp conditional_component_4_node_button() do
265+
css("#tree-node-button-4-component-tree-sidebar-content")
266+
end
267+
268+
defp conditional_component_5_node_button() do
269+
css("#tree-node-button-5-component-tree-sidebar-content")
270+
end
271+
272+
defp many_assigns_14_node_button() do
273+
css("#tree-node-button-14-component-tree-sidebar-content")
274+
end
64275
end

test/services/trace_service_test.exs

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ defmodule Services.TraceServiceTest do
77
alias LiveDebugger.Services.TraceService
88
alias LiveDebugger.MockEtsTableServer
99

10+
@all_functions LiveDebugger.Utils.Callbacks.callbacks_functions()
11+
1012
setup :verify_on_exit!
1113

1214
setup_all do
@@ -56,7 +58,8 @@ defmodule Services.TraceServiceTest do
5658
MockEtsTableServer
5759
|> expect(:table!, fn ^pid -> table end)
5860

59-
assert {[^trace1, ^trace2], _} = TraceService.existing_traces(pid)
61+
assert {[^trace1, ^trace2], _} =
62+
TraceService.existing_traces(pid, functions: @all_functions)
6063
end
6164

6265
test "returns traces with limit and continuation", %{module: module, pid: pid, table: table} do
@@ -70,12 +73,13 @@ defmodule Services.TraceServiceTest do
7073
MockEtsTableServer
7174
|> expect(:table!, fn ^pid -> table end)
7275

73-
{traces1, cont} = TraceService.existing_traces(pid, limit: 2)
74-
{traces2, cont} = TraceService.existing_traces(pid, cont: cont)
76+
{traces1, cont} = TraceService.existing_traces(pid, limit: 2, functions: @all_functions)
77+
{traces2, cont} = TraceService.existing_traces(pid, cont: cont, functions: @all_functions)
7578

7679
assert [trace1, trace2] == traces1
7780
assert [trace3] == traces2
7881
assert cont == :end_of_table
82+
7983
assert :end_of_table == TraceService.existing_traces(pid, cont: :end_of_table)
8084
end
8185

@@ -113,8 +117,11 @@ defmodule Services.TraceServiceTest do
113117
MockEtsTableServer
114118
|> expect(:table!, 2, fn ^pid -> table end)
115119

116-
assert {[^trace1], _} = TraceService.existing_traces(pid, node_id: pid)
117-
assert {[^trace2, ^trace3], _} = TraceService.existing_traces(pid, node_id: cid)
120+
assert {[^trace1], _} =
121+
TraceService.existing_traces(pid, node_id: pid, functions: @all_functions)
122+
123+
assert {[^trace2, ^trace3], _} =
124+
TraceService.existing_traces(pid, node_id: cid, functions: @all_functions)
118125
end
119126

120127
test "returns :end_of_table when no traces match", %{module: module, pid: pid, table: table} do
@@ -141,15 +148,16 @@ defmodule Services.TraceServiceTest do
141148
MockEtsTableServer
142149
|> expect(:table!, 5, fn ^pid -> table end)
143150

144-
assert {[^trace1, ^trace2], _} = TraceService.existing_traces(pid)
151+
assert {[^trace1, ^trace2], _} =
152+
TraceService.existing_traces(pid, functions: @all_functions)
145153

146154
TraceService.clear_traces(pid, trace1.pid)
147155

148-
assert {[^trace2], _} = TraceService.existing_traces(pid)
156+
assert {[^trace2], _} = TraceService.existing_traces(pid, functions: @all_functions)
149157

150158
TraceService.clear_traces(pid, trace2.cid)
151159

152-
assert :end_of_table = TraceService.existing_traces(pid)
160+
assert :end_of_table = TraceService.existing_traces(pid, functions: @all_functions)
153161
end
154162
end
155163
end

0 commit comments

Comments
 (0)