Skip to content

Commit 24758d0

Browse files
NSHkrNSHkr
authored andcommitted
progress on phoenix scope player
1 parent 8a215eb commit 24758d0

5 files changed

Lines changed: 272 additions & 98 deletions

File tree

test_apps/lib/phoenix_scope_player/data_provider.ex

Lines changed: 59 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,24 +11,24 @@ defmodule PhoenixScopePlayer.DataProvider do
1111
Lists all available debug sessions.
1212
"""
1313
def list_sessions do
14-
IO.puts("\n=== Listing Sessions ===")
14+
Logger.info("\n=== Listing Sessions ===")
1515
case File.ls(@sessions_dir) do
1616
{:ok, session_dirs} ->
17-
IO.puts("Found #{length(session_dirs)} session directories")
17+
Logger.info("Found #{length(session_dirs)} session directories")
1818
sessions = session_dirs
1919
|> Enum.map(&load_session_metadata/1)
2020
|> Enum.reject(&is_nil/1)
2121
|> Enum.sort_by(& &1["date"], :desc)
2222

23-
IO.puts("Processed #{length(sessions)} valid sessions:")
23+
Logger.info("Processed #{length(sessions)} valid sessions:")
2424
Enum.each(sessions, fn session ->
25-
IO.puts(" - #{session["id"]}: #{session["event_count"]} events")
25+
Logger.info(" - #{session["id"]}: #{session["event_count"]} events")
2626
end)
2727

2828
sessions
2929

3030
{:error, reason} ->
31-
IO.puts("Error listing sessions: #{inspect(reason)}")
31+
Logger.error("Error listing sessions: #{inspect(reason)}")
3232
[]
3333
end
3434
end
@@ -37,32 +37,70 @@ defmodule PhoenixScopePlayer.DataProvider do
3737
Gets the complete data for a specific session.
3838
"""
3939
def get_session_data(session_id) do
40-
IO.puts("\n=== Getting Session Data: #{session_id} ===")
40+
Logger.info("\n=== Getting Session Data: #{session_id} ===")
4141
session_dir = Path.join(@sessions_dir, session_id)
4242

4343
with {:ok, metadata} <- read_json_file(session_dir, "metadata.json"),
4444
{:ok, events} <- read_json_file(session_dir, "events.json"),
4545
{:ok, source_code} <- read_json_file(session_dir, "source_code.json") do
4646

47-
IO.puts("Metadata: #{inspect(metadata)}")
48-
IO.puts("Events count: #{length(events || [])}")
47+
# Transform events into the expected format
48+
transformed_events = Enum.map(events, fn event ->
49+
%{
50+
"type" => event["type"],
51+
"module" => get_in(event, ["data", "module"]),
52+
"function" => get_in(event, ["data", "function"]),
53+
"args" => format_args(get_in(event, ["data", "args"])),
54+
"return_value" => format_return_value(get_in(event, ["data", "return_value"])),
55+
"pid" => event["id"],
56+
"timestamp" => event["timestamp_ns"],
57+
"variables" => get_in(event, ["data", "variables"])
58+
}
59+
end)
60+
61+
# Transform source code into the expected format
62+
transformed_source_code = %{
63+
"files" => Map.new(source_code, fn {module, content} ->
64+
{module, %{
65+
"content" => content,
66+
"type" => "elixir"
67+
}}
68+
end)
69+
}
70+
71+
Logger.info("Metadata: #{inspect(metadata)}")
72+
Logger.info("Events count: #{length(transformed_events)}")
73+
Logger.info("Source code files: #{inspect(Map.keys(transformed_source_code["files"]))}")
4974

5075
{:ok, %{
51-
metadata: metadata,
52-
events: events, # The events are directly in the root of events.json
53-
source_code: source_code
76+
"metadata" => metadata,
77+
"events" => transformed_events,
78+
"source_code" => transformed_source_code
5479
}}
5580
else
5681
error ->
57-
IO.puts("Error reading session data: #{inspect(error)}")
82+
Logger.error("Error reading session data: #{inspect(error)}")
5883
{:error, :not_found}
5984
end
6085
end
6186

6287
# Private helpers
6388

89+
defp format_args(nil), do: nil
90+
defp format_args(args) when is_list(args) do
91+
Enum.map(args, &format_value/1)
92+
end
93+
94+
defp format_return_value(nil), do: nil
95+
defp format_return_value(value), do: format_value(value)
96+
97+
defp format_value(%{"type" => type, "value" => value}) do
98+
"#{type}: #{value}"
99+
end
100+
defp format_value(value), do: inspect(value)
101+
64102
defp load_session_metadata(session_dir) do
65-
IO.puts("\nLoading metadata for session: #{session_dir}")
103+
Logger.info("\nLoading metadata for session: #{session_dir}")
66104
case read_json_file(Path.join(@sessions_dir, session_dir), "metadata.json") do
67105
{:ok, metadata} ->
68106
# Read events file to get actual event count
@@ -78,36 +116,36 @@ defmodule PhoenixScopePlayer.DataProvider do
78116

79117
session = Map.merge(metadata, %{
80118
"id" => session_dir,
81-
"name" => session_dir |> String.replace("_", " ") |> String.capitalize(),
119+
"name" => metadata["name"] || session_dir |> String.replace("_", " ") |> String.capitalize(),
82120
"date" => metadata["timestamp"] || "Unknown",
83-
"description" => "Debug session with #{actual_event_count} events"
121+
"description" => metadata["description"] || "Debug session with #{actual_event_count} events"
84122
})
85123

86-
IO.puts(" Loaded session: #{inspect(session, pretty: true)}")
124+
Logger.info(" Loaded session: #{inspect(session, pretty: true)}")
87125
session
88126

89127
error ->
90-
IO.puts(" Error loading metadata: #{inspect(error)}")
128+
Logger.error(" Error loading metadata: #{inspect(error)}")
91129
nil
92130
end
93131
end
94132

95133
defp read_json_file(dir, filename) do
96134
path = Path.join(dir, filename)
97-
IO.puts("Reading JSON file: #{path}")
135+
Logger.info("Reading JSON file: #{path}")
98136

99137
case File.read(path) do
100138
{:ok, content} ->
101139
case Jason.decode(content) do
102140
{:ok, data} ->
103-
IO.puts(" Successfully decoded JSON")
141+
Logger.info(" Successfully decoded JSON: #{inspect(String.slice(content, 0..100))}...")
104142
{:ok, data}
105143
error ->
106-
IO.puts(" Error decoding JSON: #{inspect(error)}")
144+
Logger.error(" Error decoding JSON: #{inspect(error)}")
107145
error
108146
end
109147
{:error, reason} ->
110-
IO.puts(" Error reading file: #{inspect(reason)}")
148+
Logger.error(" Error reading file: #{inspect(reason)}")
111149
{:error, :not_found}
112150
end
113151
end

test_apps/lib/phoenix_scope_player_web/live/playback_live.ex

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,19 @@
11
defmodule PhoenixScopePlayerWeb.PlaybackLive do
22
use PhoenixScopePlayerWeb, :live_view
33
alias PhoenixScopePlayer.DataProvider
4+
require Logger
45

56
def mount(%{"id" => session_id}, _session, socket) do
7+
Logger.info("Mounting PlaybackLive with session_id: #{session_id}")
8+
69
case DataProvider.get_session_data(session_id) do
710
{:ok, session_data} ->
8-
events = session_data.events
11+
Logger.info("Got session data: #{inspect(session_data, pretty: true)}")
12+
events = session_data["events"] || []
913
current_event = List.first(events)
14+
15+
Logger.info("Events count: #{length(events)}")
16+
Logger.info("First event: #{inspect(current_event)}")
1017

1118
{:ok, assign(socket,
1219
session_id: session_id,
@@ -20,6 +27,7 @@ defmodule PhoenixScopePlayerWeb.PlaybackLive do
2027
)}
2128

2229
{:error, :not_found} ->
30+
Logger.error("Session not found: #{session_id}")
2331
{:ok, socket
2432
|> put_flash(:error, "Session not found")
2533
|> redirect(to: ~p"/")}
@@ -28,9 +36,11 @@ defmodule PhoenixScopePlayerWeb.PlaybackLive do
2836

2937
def handle_event("next_event", _, socket) do
3038
%{current_event_index: index, session_data: data} = socket.assigns
31-
events = data.events
39+
events = data["events"] || []
3240
next_index = min(index + 1, length(events) - 1)
3341

42+
Logger.info("Moving to next event: #{next_index} of #{length(events)}")
43+
3444
{:noreply, assign(socket,
3545
current_event_index: next_index,
3646
current_event: Enum.at(events, next_index)
@@ -39,9 +49,11 @@ defmodule PhoenixScopePlayerWeb.PlaybackLive do
3949

4050
def handle_event("prev_event", _, socket) do
4151
%{current_event_index: index, session_data: data} = socket.assigns
42-
events = data.events
52+
events = data["events"] || []
4353
prev_index = max(index - 1, 0)
4454

55+
Logger.info("Moving to previous event: #{prev_index} of #{length(events)}")
56+
4557
{:noreply, assign(socket,
4658
current_event_index: prev_index,
4759
current_event: Enum.at(events, prev_index)
@@ -53,7 +65,9 @@ defmodule PhoenixScopePlayerWeb.PlaybackLive do
5365
end
5466

5567
def handle_event("select_file", %{"file" => file}, socket) do
56-
content = get_in(socket.assigns.session_data.source_code, [file, "content"])
68+
Logger.info("Selecting file: #{file}")
69+
content = get_in(socket.assigns.session_data, ["source_code", "files", file, "content"])
70+
Logger.info("Got content: #{inspect(String.slice(content || "", 0..100))}...")
5771

5872
{:noreply, assign(socket,
5973
current_file: file,
@@ -68,7 +82,7 @@ defmodule PhoenixScopePlayerWeb.PlaybackLive do
6882
<div class="sm:flex-auto">
6983
<h1 class="text-base font-semibold leading-6 text-gray-900">Session Playback</h1>
7084
<p class="mt-2 text-sm text-gray-700">
71-
<%= @session_data.metadata["name"] %>
85+
<%= @session_data["metadata"]["name"] %>
7286
</p>
7387
</div>
7488
<div class="mt-4 sm:ml-16 sm:mt-0">
@@ -117,7 +131,7 @@ defmodule PhoenixScopePlayerWeb.PlaybackLive do
117131
<h3 class="text-base font-semibold leading-6 text-gray-900">Source Code</h3>
118132
<div class="mt-2">
119133
<div class="flex space-x-2 mb-2">
120-
<%= for {file, _} <- @session_data.source_code do %>
134+
<%= for {file, _} <- get_in(@session_data, ["source_code", "files"]) || %{} do %>
121135
<button
122136
type="button"
123137
class={"px-2 py-1 text-sm rounded #{if @current_file == file, do: "bg-indigo-600 text-white", else: "bg-gray-100 text-gray-700 hover:bg-gray-200"}"}
@@ -146,28 +160,30 @@ defmodule PhoenixScopePlayerWeb.PlaybackLive do
146160
</div>
147161
<div class="mb-4">
148162
<div class="font-medium text-gray-700">Function</div>
149-
<div class="text-sm text-gray-900"><%= get_in(@current_event, ["data", "module"]) %>.<%= get_in(@current_event, ["data", "function"]) %></div>
163+
<div class="text-sm text-gray-900"><%= @current_event["module"] %>.<%= @current_event["function"] %></div>
150164
</div>
151-
<%= if get_in(@current_event, ["data", "args"]) do %>
165+
<%= if @current_event["args"] do %>
152166
<div class="mb-4">
153167
<div class="font-medium text-gray-700">Arguments</div>
154-
<div class="text-sm text-gray-900"><%= inspect(get_in(@current_event, ["data", "args"])) %></div>
168+
<div class="text-sm text-gray-900"><%= inspect(@current_event["args"]) %></div>
155169
</div>
156170
<% end %>
157-
<%= if get_in(@current_event, ["data", "return_value"]) do %>
171+
<%= if @current_event["return_value"] do %>
158172
<div class="mb-4">
159173
<div class="font-medium text-gray-700">Return Value</div>
160-
<div class="text-sm text-gray-900"><%= inspect(get_in(@current_event, ["data", "return_value"])) %></div>
174+
<div class="text-sm text-gray-900"><%= @current_event["return_value"] %></div>
175+
</div>
176+
<% end %>
177+
<%= if @current_event["pid"] do %>
178+
<div class="mb-4">
179+
<div class="font-medium text-gray-700">Process ID</div>
180+
<div class="text-sm text-gray-900"><%= @current_event["pid"] %></div>
161181
</div>
162182
<% end %>
163-
<%= if get_in(@current_event, ["data", "variables"]) do %>
183+
<%= if @current_event["timestamp"] do %>
164184
<div class="mb-4">
165-
<div class="font-medium text-gray-700">Variables</div>
166-
<div class="text-sm text-gray-900">
167-
<%= for {var, value} <- get_in(@current_event, ["data", "variables"]) do %>
168-
<div><span class="font-mono"><%= var %></span>: <%= inspect(value) %></div>
169-
<% end %>
170-
</div>
185+
<div class="font-medium text-gray-700">Timestamp</div>
186+
<div class="text-sm text-gray-900"><%= @current_event["timestamp"] %></div>
171187
</div>
172188
<% end %>
173189
<% else %>
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
defmodule Mix.Tasks.Clean.Sessions do
2+
@moduledoc """
3+
Mix task to clean out all debug sessions.
4+
5+
## Examples
6+
7+
mix clean.sessions # Cleans all sessions
8+
mix clean.sessions --keep-sample # Keeps sample_session_1
9+
"""
10+
11+
use Mix.Task
12+
require Logger
13+
14+
@impl Mix.Task
15+
def run(args) do
16+
keep_sample = "--keep-sample" in args
17+
18+
captured_data_dir = Path.join([
19+
:code.priv_dir(:phoenix_scope_player),
20+
"captured_data"
21+
])
22+
23+
Logger.info("\n=== Cleaning debug sessions ===")
24+
25+
# Ensure directory exists
26+
File.mkdir_p!(captured_data_dir)
27+
28+
case File.ls(captured_data_dir) do
29+
{:ok, files} ->
30+
files
31+
|> Enum.filter(fn file ->
32+
if keep_sample do
33+
file != "sample_session_1"
34+
else
35+
true
36+
end
37+
end)
38+
|> Enum.each(fn file ->
39+
path = Path.join(captured_data_dir, file)
40+
case File.rm_rf(path) do
41+
{:ok, _} ->
42+
Logger.info("✓ Removed #{file}")
43+
{:error, posix, reason} ->
44+
Logger.error("✗ Failed to remove #{file}: #{inspect(posix)} - #{inspect(reason)}")
45+
end
46+
end)
47+
48+
Logger.info("\n=== Session cleanup complete ===")
49+
50+
{:error, reason} ->
51+
Logger.error("Error listing sessions: #{inspect(reason)}")
52+
end
53+
end
54+
end

0 commit comments

Comments
 (0)