Skip to content

Commit 681d2d7

Browse files
committed
wip - e2e tests for distributed tracing
1 parent bbdc484 commit 681d2d7

File tree

29 files changed

+1798
-2
lines changed

29 files changed

+1798
-2
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,4 @@ test_integrations/phoenix_app/db
1717

1818
test_integrations/*/_build
1919
test_integrations/*/deps
20+
test_integrations/*/test-results/
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
defmodule Mix.Tasks.Sentry.Tracing.Phoenix do
2+
@shortdoc "Starts the Phoenix test app for distributed tracing testing"
3+
4+
@moduledoc """
5+
Starts the Phoenix test application for distributed tracing testing.
6+
7+
This task is useful for:
8+
- Running the Phoenix backend for end-to-end tracing tests
9+
- Manual testing of distributed tracing with a real Sentry DSN
10+
- Development and debugging of tracing features
11+
12+
## Usage
13+
14+
mix sentry.tracing.phoenix [options]
15+
16+
## Options
17+
18+
* `--dsn DSN` - Set the Sentry DSN to use (defaults to test DSN)
19+
* `--port PORT` - Set the port for the Phoenix app (default: 4000)
20+
* `--test-mode` - Enable test mode (logs events to file instead of sending to Sentry)
21+
22+
## Examples
23+
24+
# Start with test mode (logs to file)
25+
mix sentry.tracing.phoenix --test-mode
26+
27+
# Start with a real DSN for manual testing
28+
mix sentry.tracing.phoenix --dsn https://[email protected]/project
29+
30+
# Start on a different port
31+
mix sentry.tracing.phoenix --port 4001
32+
33+
"""
34+
35+
@moduledoc since: "11.1.0"
36+
37+
use Mix.Task
38+
39+
@switches [
40+
dsn: :string,
41+
port: :string,
42+
test_mode: :boolean
43+
]
44+
45+
@impl true
46+
def run(args) do
47+
{opts, _args} = OptionParser.parse!(args, strict: @switches)
48+
49+
phoenix_app_path =
50+
Path.join([Mix.Project.project_file(), "..", "test_integrations", "phoenix_app"])
51+
52+
phoenix_app_path = Path.expand(phoenix_app_path)
53+
54+
unless File.dir?(phoenix_app_path) do
55+
Mix.raise("Phoenix app not found at: #{phoenix_app_path}")
56+
end
57+
58+
# Set environment variables
59+
port = Keyword.get(opts, :port, "4000")
60+
test_mode = Keyword.get(opts, :test_mode, false)
61+
62+
dsn = Keyword.get(opts, :dsn, "https://user:[email protected]/42")
63+
64+
env = %{
65+
"SENTRY_DSN" => dsn,
66+
"SENTRY_E2E_PHOENIX_APP_PORT" => port,
67+
"SENTRY_E2E_TEST_MODE" => if(test_mode, do: "true", else: "false"),
68+
"MIX_ENV" => "dev"
69+
}
70+
71+
Mix.shell().info([:green, "Starting Phoenix app on port #{port}...", :reset])
72+
73+
if test_mode do
74+
Mix.shell().info([
75+
:yellow,
76+
"Test mode enabled - events will be logged to tmp/sentry_debug_events.log",
77+
:reset
78+
])
79+
else
80+
Mix.shell().info([:cyan, "Using DSN: #{dsn}", :reset])
81+
end
82+
83+
# Clean up old log file if in test mode
84+
if test_mode do
85+
log_file = Path.join([phoenix_app_path, "tmp", "sentry_debug_events.log"])
86+
File.rm(log_file)
87+
end
88+
89+
# Install dependencies
90+
Mix.shell().info("Installing dependencies...")
91+
92+
{_, 0} =
93+
System.cmd("mix", ["deps.get"],
94+
cd: phoenix_app_path,
95+
env: env,
96+
into: IO.stream(:stdio, :line)
97+
)
98+
99+
# Start the Phoenix server
100+
Mix.shell().info([:green, "Starting Phoenix server...", :reset])
101+
Mix.shell().info("Visit http://localhost:#{port}/health to verify it's running")
102+
Mix.shell().info("Press Ctrl+C to stop")
103+
104+
System.cmd("mix", ["phx.server"],
105+
cd: phoenix_app_path,
106+
env: env,
107+
into: IO.stream(:stdio, :line)
108+
)
109+
end
110+
end
Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
defmodule Mix.Tasks.Sentry.Tracing.Start do
2+
@shortdoc "Starts both Phoenix and Svelte apps for distributed tracing testing"
3+
4+
@moduledoc """
5+
Prepares the environment and generates instructions for running distributed tracing tests.
6+
7+
This task sets up environment variables and provides commands to start the Phoenix backend
8+
and Svelte frontend for manual testing of distributed tracing features.
9+
10+
## Usage
11+
12+
mix sentry.tracing.start [options]
13+
14+
## Options
15+
16+
* `--dsn DSN` - Set the Sentry DSN to use (defaults to test DSN)
17+
* `--phoenix-port PORT` - Set the port for the Phoenix app (default: 4000)
18+
* `--svelte-port PORT` - Set the port for the Svelte app (default: 4001)
19+
* `--test-mode` - Enable test mode (logs events to file instead of sending to Sentry)
20+
21+
## Examples
22+
23+
# Start with test mode (logs to file)
24+
mix sentry.tracing.start --test-mode
25+
26+
# Start with a real DSN for manual testing
27+
mix sentry.tracing.start --dsn https://[email protected]/project
28+
29+
# Start on different ports
30+
mix sentry.tracing.start --phoenix-port 4001 --svelte-port 4002
31+
32+
## Testing
33+
34+
Once both apps are running:
35+
1. Visit http://localhost:4001 (or your custom Svelte port) in your browser
36+
2. Click "Trigger Error" to send a request to the Phoenix backend
37+
3. Check your Sentry dashboard or the log file (if in test mode) to see events
38+
39+
In test mode, events are logged to:
40+
`test_integrations/phoenix_app/tmp/sentry_debug_events.log`
41+
42+
## Stopping
43+
44+
Simply press Ctrl+C once in the terminal where you started the processes.
45+
46+
"""
47+
48+
@moduledoc since: "11.1.0"
49+
50+
use Mix.Task
51+
52+
@switches [
53+
dsn: :string,
54+
phoenix_port: :string,
55+
svelte_port: :string,
56+
test_mode: :boolean
57+
]
58+
59+
@impl true
60+
def run(args) do
61+
{opts, _args} = OptionParser.parse!(args, strict: @switches)
62+
63+
tracing_path = Path.join([Mix.Project.project_file(), "..", "test_integrations", "tracing"])
64+
tracing_path = Path.expand(tracing_path)
65+
66+
phoenix_app_path = Path.join([tracing_path, "..", "phoenix_app"])
67+
phoenix_app_path = Path.expand(phoenix_app_path)
68+
69+
svelte_app_path = Path.join([tracing_path, "svelte_mini"])
70+
71+
unless File.dir?(tracing_path) do
72+
Mix.raise("Tracing test directory not found at: #{tracing_path}")
73+
end
74+
75+
# Check if npm is available
76+
case System.cmd("npm", ["--version"], stderr_to_stdout: true) do
77+
{_, 0} -> :ok
78+
_ -> Mix.raise("npm is not installed. Please install Node.js and npm first.")
79+
end
80+
81+
# Set environment variables
82+
phoenix_port_number = Keyword.get(opts, :phoenix_port, "4000")
83+
svelte_port_number = Keyword.get(opts, :svelte_port, "4001")
84+
test_mode = Keyword.get(opts, :test_mode, false)
85+
dsn = Keyword.get(opts, :dsn, "https://user:[email protected]/42")
86+
87+
env_vars = %{
88+
"SENTRY_DSN" => dsn,
89+
"SENTRY_E2E_PHOENIX_APP_PORT" => phoenix_port_number,
90+
"SENTRY_E2E_SVELTE_APP_PORT" => svelte_port_number,
91+
"SENTRY_E2E_TEST_MODE" => if(test_mode, do: "true", else: "false"),
92+
"MIX_ENV" => "dev",
93+
"VITE_BACKEND_URL" => "http://localhost:#{phoenix_port_number}",
94+
"PORT" => svelte_port_number,
95+
"OVERMIND_NO_PORT" => "1"
96+
}
97+
98+
Mix.shell().info([
99+
:green,
100+
:bright,
101+
"Preparing distributed tracing test environment...",
102+
:reset
103+
])
104+
105+
Mix.shell().info("")
106+
107+
Mix.shell().info([
108+
:cyan,
109+
"Phoenix backend: ",
110+
:reset,
111+
"http://localhost:#{phoenix_port_number}"
112+
])
113+
114+
Mix.shell().info([
115+
:cyan,
116+
"Svelte frontend: ",
117+
:reset,
118+
"http://localhost:#{svelte_port_number}"
119+
])
120+
121+
if test_mode do
122+
Mix.shell().info([:yellow, "Test mode enabled - events will be logged to:", :reset])
123+
Mix.shell().info(" test_integrations/phoenix_app/tmp/sentry_debug_events.log")
124+
else
125+
Mix.shell().info([:cyan, "Using Sentry DSN: ", :reset, dsn])
126+
end
127+
128+
Mix.shell().info("")
129+
130+
# Clean up old log file if in test mode
131+
if test_mode do
132+
log_file = Path.join([phoenix_app_path, "tmp", "sentry_debug_events.log"])
133+
File.rm(log_file)
134+
end
135+
136+
# Install dependencies
137+
Mix.shell().info([:yellow, "Installing dependencies...", :reset])
138+
System.cmd("mix", ["deps.get"], cd: phoenix_app_path, stderr_to_stdout: true)
139+
140+
node_modules = Path.join(svelte_app_path, "node_modules")
141+
142+
unless File.dir?(node_modules) do
143+
System.cmd("npm", ["install"], cd: svelte_app_path, stderr_to_stdout: true)
144+
end
145+
146+
# Write environment file for overmind/manual start
147+
env_file_path = Path.join(tracing_path, ".env")
148+
env_file_content = Enum.map_join(env_vars, "\n", fn {k, v} -> "#{k}=#{v}" end)
149+
File.write!(env_file_path, env_file_content)
150+
151+
Mix.shell().info("")
152+
Mix.shell().info([:green, :bright, "✓ Environment ready!", :reset])
153+
Mix.shell().info("")
154+
Mix.shell().info([:bright, "To start the servers, run:", :reset])
155+
Mix.shell().info("")
156+
Mix.shell().info([" ", :cyan, "cd test_integrations/tracing && overmind start", :reset])
157+
Mix.shell().info("")
158+
Mix.shell().info([:bright, "Then:", :reset])
159+
160+
Mix.shell().info([
161+
" • Visit ",
162+
:cyan,
163+
"http://localhost:#{svelte_port_number}",
164+
:reset,
165+
" to test"
166+
])
167+
168+
Mix.shell().info([" • Press ", :yellow, "Ctrl+C", :reset, " to stop all processes cleanly"])
169+
Mix.shell().info("")
170+
Mix.shell().info([:yellow, "Don't have Overmind?", :reset])
171+
172+
Mix.shell().info([
173+
" • Install: ",
174+
:cyan,
175+
"go install github.com/DarthSim/overmind/v2@latest",
176+
:reset
177+
])
178+
179+
Mix.shell().info([
180+
" • Add to PATH: ",
181+
:cyan,
182+
"export PATH=$PATH:$(go env GOPATH)/bin",
183+
:reset
184+
])
185+
186+
Mix.shell().info("")
187+
end
188+
end
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
defmodule Mix.Tasks.Sentry.Tracing.Stop do
2+
@shortdoc "Stops the Phoenix and Svelte apps started by sentry.tracing.start"
3+
4+
@moduledoc """
5+
Stops both the Phoenix backend and Svelte frontend applications that were started
6+
by `mix sentry.tracing.start`.
7+
8+
## Usage
9+
10+
mix sentry.tracing.stop
11+
12+
This will kill all processes matching:
13+
- mix phx.server
14+
- vite dev server
15+
- npm run dev
16+
- inotifywait processes for phoenix_app
17+
18+
"""
19+
20+
@moduledoc since: "11.1.0"
21+
22+
use Mix.Task
23+
24+
@impl true
25+
def run(_args) do
26+
Mix.shell().info([:yellow, "Stopping distributed tracing test environment...", :reset])
27+
28+
# Kill Phoenix processes
29+
{_, phoenix_status} = System.cmd("pkill", ["-f", "mix phx.server"], stderr_to_stdout: true)
30+
31+
# Kill Vite/npm processes
32+
{_, vite_status} = System.cmd("pkill", ["-f", "vite"], stderr_to_stdout: true)
33+
{_, npm_status} = System.cmd("pkill", ["-f", "npm run dev"], stderr_to_stdout: true)
34+
35+
# Kill inotifywait processes
36+
{_, inotify_status} =
37+
System.cmd("pkill", ["-f", "inotifywait.*phoenix_app"], stderr_to_stdout: true)
38+
39+
Process.sleep(500)
40+
41+
if phoenix_status == 0 or vite_status == 0 or npm_status == 0 or inotify_status == 0 do
42+
Mix.shell().info([:green, "✓ Stopped all processes", :reset])
43+
else
44+
Mix.shell().info([:yellow, "No processes found to stop", :reset])
45+
end
46+
end
47+
end

0 commit comments

Comments
 (0)