|
1 | | -####################################### |
2 | | -# Development Server for ErrorTracker. |
| 1 | +# This is the development server for Errortracker built on the PhoenixLiveDashboard project. |
| 2 | +# To start the development server run: |
| 3 | +# $ iex dev.exs |
3 | 4 | # |
4 | | -# Based on PhoenixLiveDashboard code. |
5 | | -# |
6 | | -# Usage: |
7 | | -# |
8 | | -# $ iex -S mix dev |
9 | | -####################################### |
10 | | -Logger.configure(level: :debug) |
11 | | - |
12 | | -# Get configuration |
13 | | -Config.Reader.read!("config/config.exs", env: :dev) |
14 | | - |
15 | | -# Prepare the repo |
16 | | -adapter = |
17 | | - case Application.get_env(:error_tracker, :ecto_adapter) do |
18 | | - :postgres -> Ecto.Adapters.Postgres |
19 | | - :mysql -> Ecto.Adapters.MyXQL |
20 | | - :sqlite3 -> Ecto.Adapters.SQLite3 |
21 | | - end |
| 5 | +Mix.install([ |
| 6 | + {:ecto_sqlite3, ">= 0.0.0"}, |
| 7 | + {:error_tracker, path: "."}, |
| 8 | + {:phoenix_playground, "~> 0.1.7"} |
| 9 | +]) |
22 | 10 |
|
23 | | -defmodule ErrorTrackerDev.Repo do |
24 | | - use Ecto.Repo, otp_app: :error_tracker, adapter: adapter |
25 | | -end |
| 11 | +otp_app = :error_tracker_dev |
26 | 12 |
|
27 | | -_ = adapter.storage_up(ErrorTrackerDev.Repo.config()) |
28 | | - |
29 | | -# Configures the endpoint |
30 | | -Application.put_env(:error_tracker, ErrorTrackerDevWeb.Endpoint, |
31 | | - url: [host: "localhost"], |
32 | | - secret_key_base: "Hu4qQN3iKzTV4fJxhorPQlA/osH9fAMtbtjVS58PFgfw3ja5Z18Q/WSNR9wP4OfW", |
33 | | - live_view: [signing_salt: "hMegieSe"], |
34 | | - http: [port: System.get_env("PORT") || 4000], |
35 | | - debug_errors: true, |
36 | | - check_origin: false, |
37 | | - pubsub_server: ErrorTrackerDev.PubSub, |
38 | | - watchers: [ |
39 | | - tailwind: {Tailwind, :install_and_run, [:default, ~w(--watch)]} |
| 13 | +Application.put_all_env( |
| 14 | + error_tracker_dev: [ |
| 15 | + {ErrorTrackerDev.Repo, [database: "priv/repo/dev.db"]} |
40 | 16 | ], |
41 | | - live_reload: [ |
42 | | - patterns: [ |
43 | | - ~r"dev.exs$", |
44 | | - ~r"dist/.*(js|css|png|jpeg|jpg|gif|svg)$", |
45 | | - ~r"lib/error_tracker/web/(live|views)/.*(ex)$", |
46 | | - ~r"lib/error_tracker/web/templates/.*(ex)$" |
47 | | - ] |
| 17 | + error_tracker: [ |
| 18 | + {:application, otp_app}, |
| 19 | + {:otp_app, otp_app}, |
| 20 | + {:repo, ErrorTrackerDev.Repo} |
48 | 21 | ] |
49 | 22 | ) |
50 | 23 |
|
51 | | -# Setup up the ErrorTracker configuration |
52 | | -Application.put_env(:error_tracker, :repo, ErrorTrackerDev.Repo) |
53 | | -Application.put_env(:error_tracker, :otp_app, :error_tracker_dev) |
54 | | -Application.put_env(:error_tracker, :prefix, "private") |
55 | | - |
56 | | -defmodule ErrorTrackerDevWeb.PageController do |
57 | | - import Plug.Conn |
58 | | - |
59 | | - def init(opts), do: opts |
60 | | - |
61 | | - def call(conn, :index) do |
62 | | - content(conn, """ |
63 | | - <h2>ErrorTracker Dev Server</h2> |
64 | | - <div><a href="/dev/errors">Open ErrorTracker</a></div> |
65 | | - <div><a href="/plug-exception">Generate Plug exception</a></div> |
66 | | - <div><a href="/404">Generate Router 404</a></div> |
67 | | - <div><a href="/noroute">Raise NoRouteError from a controller</a></div> |
68 | | - <div><a href="/exception">Generate Exception</a></div> |
69 | | - <div><a href="/exit">Generate Exit</a></div> |
70 | | - """) |
71 | | - end |
72 | | - |
73 | | - def call(conn, :noroute) do |
74 | | - ErrorTracker.add_breadcrumb("ErrorTrackerDevWeb.PageController.no_route") |
75 | | - raise Phoenix.Router.NoRouteError, conn: conn, router: ErrorTrackerDevWeb.Router |
76 | | - end |
77 | | - |
78 | | - def call(_conn, :exception) do |
79 | | - ErrorTracker.add_breadcrumb("ErrorTrackerDevWeb.PageController.exception") |
| 24 | +defmodule ErrorTrackerDev.Repo do |
| 25 | + require Logger |
| 26 | + use Ecto.Repo, otp_app: otp_app, adapter: Ecto.Adapters.SQLite3 |
80 | 27 |
|
81 | | - raise CustomException, |
82 | | - message: "This is a controller exception", |
83 | | - bread_crumbs: ["First", "Second"] |
84 | | - end |
| 28 | + defmodule Migration do |
| 29 | + use Ecto.Migration |
85 | 30 |
|
86 | | - def call(_conn, :exit) do |
87 | | - ErrorTracker.add_breadcrumb("ErrorTrackerDevWeb.PageController.exit") |
88 | | - exit(:timeout) |
| 31 | + def up, do: ErrorTracker.Migration.up() |
| 32 | + def down, do: ErrorTracker.Migration.down() |
89 | 33 | end |
90 | 34 |
|
91 | | - defp content(conn, content) do |
92 | | - conn |
93 | | - |> put_resp_header("content-type", "text/html") |
94 | | - |> send_resp(200, "<!doctype html><html><body>#{content}</body></html>") |
| 35 | + def migrate do |
| 36 | + Ecto.Migrator.run(__MODULE__, [{0, __MODULE__.Migration}], :up, all: true) |
95 | 37 | end |
96 | 38 | end |
97 | 39 |
|
98 | | -defmodule CustomException do |
99 | | - defexception [:message, :bread_crumbs] |
100 | | -end |
| 40 | +defmodule ErrorTrackerDev.Controller do |
| 41 | + use Phoenix.Controller, formats: [:html] |
| 42 | + use Phoenix.Component |
101 | 43 |
|
102 | | -defmodule ErrorTrackerDevWeb.ErrorView do |
103 | | - def render("404.html", _assigns) do |
104 | | - "This is a 404" |
105 | | - end |
| 44 | + plug :put_layout, false |
| 45 | + plug :put_view, __MODULE__ |
106 | 46 |
|
107 | | - def render("500.html", _assigns) do |
108 | | - "This is a 500" |
| 47 | + def index(conn, _opts) do |
| 48 | + render(conn) |
109 | 49 | end |
110 | | -end |
111 | 50 |
|
112 | | -defmodule ErrorTrackerDevWeb.Router do |
113 | | - use Phoenix.Router |
114 | | - use ErrorTracker.Web, :router |
| 51 | + def index(assigns) do |
| 52 | + ~H""" |
| 53 | + <h2>ErrorTracker Dev server</h2> |
115 | 54 |
|
116 | | - pipeline :browser do |
117 | | - plug :fetch_session |
118 | | - plug :protect_from_forgery |
| 55 | + <ul> |
| 56 | + <li></li> |
| 57 | + </ul> |
| 58 | + """ |
119 | 59 | end |
| 60 | +end |
120 | 61 |
|
121 | | - scope "/" do |
122 | | - pipe_through :browser |
123 | | - get "/", ErrorTrackerDevWeb.PageController, :index |
124 | | - get "/noroute", ErrorTrackerDevWeb.PageController, :noroute |
125 | | - get "/exception", ErrorTrackerDevWeb.PageController, :exception |
126 | | - get "/exit", ErrorTrackerDevWeb.PageController, :exit |
| 62 | +defmodule ErrorTrackerDev.Live do |
| 63 | + use Phoenix.LiveView |
127 | 64 |
|
128 | | - scope "/dev" do |
129 | | - error_tracker_dashboard "/errors", csp_nonce_assign_key: :my_csp_nonce |
| 65 | + def mount(params, _session, socket) do |
| 66 | + if params["crash_on_mount"] do |
| 67 | + raise("Crashed on mount/3") |
130 | 68 | end |
131 | | - end |
132 | | -end |
133 | 69 |
|
134 | | -defmodule ErrorTrackerDevWeb.Endpoint do |
135 | | - use Phoenix.Endpoint, otp_app: :error_tracker |
136 | | - use ErrorTracker.Integrations.Plug |
| 70 | + {:ok, socket} |
| 71 | + end |
137 | 72 |
|
138 | | - @session_options [ |
139 | | - store: :cookie, |
140 | | - key: "_error_tracker_dev", |
141 | | - signing_salt: "/VEDsdfsffMnp5", |
142 | | - same_site: "Lax" |
143 | | - ] |
| 73 | + def handle_params(params, _uri, socket) do |
| 74 | + if params["crash_on_handle_params"] do |
| 75 | + raise "Crashed on handle_params/3" |
| 76 | + end |
144 | 77 |
|
145 | | - socket "/live", Phoenix.LiveView.Socket, websocket: [connect_info: [session: @session_options]] |
146 | | - socket "/phoenix/live_reload/socket", Phoenix.LiveReloader.Socket |
| 78 | + {:noreply, socket} |
| 79 | + end |
147 | 80 |
|
148 | | - plug Phoenix.LiveReloader |
149 | | - plug Phoenix.CodeReloader |
| 81 | + def handle_event("crash_on_handle_event", _params, socket) do |
| 82 | + raise "Crashed on handle_event/3" |
| 83 | + end |
150 | 84 |
|
151 | | - plug Plug.Session, @session_options |
| 85 | + def handle_event("crash_on_render", _params, socket) do |
| 86 | + {:noreply, assign(socket, crash_on_render: true)} |
| 87 | + end |
152 | 88 |
|
153 | | - plug Plug.RequestId |
154 | | - plug Plug.Telemetry, event_prefix: [:phoenix, :endpoint] |
155 | | - plug :add_breadcrumb |
156 | | - plug :maybe_exception |
157 | | - plug :set_csp |
158 | | - plug ErrorTrackerDevWeb.Router |
| 89 | + def render(assigns) do |
| 90 | + if Map.has_key?(assigns, :crash_on_render) do |
| 91 | + raise "Crashed on render/1" |
| 92 | + end |
159 | 93 |
|
160 | | - def add_breadcrumb(conn, _) do |
161 | | - ErrorTracker.add_breadcrumb("ErrorTrackerDevWeb.Endpoint.add_breadcrumb") |
162 | | - conn |
| 94 | + ~H""" |
| 95 | + <h1>ErrorTracker Dev server</h1> |
| 96 | +
|
| 97 | + <.link href="/dev/errors" target="_blank">Open the ErrorTracker dashboard</.link> |
| 98 | +
|
| 99 | + <h2>LiveView example</h2> |
| 100 | +
|
| 101 | + <ul> |
| 102 | + <li> |
| 103 | + <.link href="/?crash_on_mount">Crash on mount/3</.link> |
| 104 | + </li> |
| 105 | + <li> |
| 106 | + <.link patch="/?crash_on_handle_params">Crash on handle_params/3</.link> |
| 107 | + </li> |
| 108 | + <li> |
| 109 | + <.link phx-click="crash_on_render">Crash on render/1</.link> |
| 110 | + </li> |
| 111 | + <li> |
| 112 | + <.link phx-click="crash_on_handle_event">Crash on handle_event/3</.link> |
| 113 | + </li> |
| 114 | + </ul> |
| 115 | +
|
| 116 | + <h2>Controller example</h2> |
| 117 | + """ |
163 | 118 | end |
| 119 | +end |
164 | 120 |
|
165 | | - def maybe_exception(%Plug.Conn{path_info: ["plug-exception"]}, _), do: raise("Plug exception") |
166 | | - def maybe_exception(conn, _), do: conn |
167 | | - |
168 | | - defp set_csp(conn, _opts) do |
169 | | - nonce = 10 |> :crypto.strong_rand_bytes() |> Base.encode64() |
| 121 | +defmodule ErrorTrackerDev.Router do |
| 122 | + use Phoenix.Router |
| 123 | + use ErrorTracker.Web, :router |
170 | 124 |
|
171 | | - policies = [ |
172 | | - "script-src 'self' 'nonce-#{nonce}';", |
173 | | - "style-src 'self' 'nonce-#{nonce}';" |
174 | | - ] |
| 125 | + import Phoenix.LiveView.Router |
175 | 126 |
|
176 | | - conn |
177 | | - |> Plug.Conn.assign(:my_csp_nonce, "#{nonce}") |
178 | | - |> Plug.Conn.put_resp_header("content-security-policy", Enum.join(policies, " ")) |
| 127 | + pipeline :browser do |
| 128 | + plug :accepts, [:html] |
| 129 | + plug :put_root_layout, html: {PhoenixPlayground.Layout, :root} |
| 130 | + plug :put_secure_browser_headers |
179 | 131 | end |
180 | | -end |
181 | 132 |
|
182 | | -defmodule ErrorTrackerDev.Telemetry do |
183 | | - require Logger |
| 133 | + scope "/" do |
| 134 | + pipe_through :browser |
184 | 135 |
|
185 | | - def start do |
186 | | - :telemetry.attach_many( |
187 | | - "error-tracker-events", |
188 | | - [ |
189 | | - [:error_tracker, :error, :new], |
190 | | - [:error_tracker, :error, :resolved], |
191 | | - [:error_tracker, :error, :unresolved], |
192 | | - [:error_tracker, :occurrence, :new] |
193 | | - ], |
194 | | - &__MODULE__.handle_event/4, |
195 | | - [] |
196 | | - ) |
197 | | - |
198 | | - Logger.info("Telemtry attached") |
199 | | - end |
| 136 | + live "/", ErrorTrackerDev.Live |
200 | 137 |
|
201 | | - def handle_event(event, measure, metadata, _opts) do |
202 | | - dbg([event, measure, metadata]) |
| 138 | + scope "/dev" do |
| 139 | + error_tracker_dashboard "/errors" |
| 140 | + end |
203 | 141 | end |
204 | 142 | end |
205 | 143 |
|
206 | | -Application.put_env(:phoenix, :serve_endpoints, true) |
207 | | - |
208 | | -Task.async(fn -> |
209 | | - children = [ |
210 | | - {Phoenix.PubSub, [name: ErrorTrackerDev.PubSub, adapter: Phoenix.PubSub.PG2]}, |
211 | | - ErrorTrackerDev.Repo, |
212 | | - ErrorTrackerDevWeb.Endpoint |
213 | | - ] |
214 | | - |
215 | | - ErrorTrackerDev.Telemetry.start() |
| 144 | +defmodule ErrorTrackerDev.Endpoint do |
| 145 | + # Default PhoenixPlayground.Endpoint |
| 146 | + use Phoenix.Endpoint, otp_app: :phoenix_playground |
| 147 | + plug Plug.Logger |
| 148 | + socket "/live", Phoenix.LiveView.Socket |
| 149 | + plug Plug.Static, from: {:phoenix, "priv/static"}, at: "/assets/phoenix" |
| 150 | + plug Plug.Static, from: {:phoenix_live_view, "priv/static"}, at: "/assets/phoenix_live_view" |
| 151 | + socket "/phoenix/live_reload/socket", Phoenix.LiveReloader.Socket |
| 152 | + plug Phoenix.LiveReloader |
| 153 | + plug Phoenix.CodeReloader, reloader: &PhoenixPlayground.CodeReloader.reload/2 |
216 | 154 |
|
217 | | - {:ok, _} = Supervisor.start_link(children, strategy: :one_for_one) |
| 155 | + # Our custom router which allows us to have regular controllers and live views |
| 156 | + plug ErrorTrackerDev.Router |
| 157 | +end |
218 | 158 |
|
219 | | - # Automatically run the migrations on boot |
220 | | - Ecto.Migrator.run(ErrorTrackerDev.Repo, :up, all: true, log_migrations_sql: :debug) |
| 159 | +PhoenixPlayground.start( |
| 160 | + endpoint: ErrorTrackerDev.Endpoint, |
| 161 | + child_specs: [{ErrorTrackerDev.Repo, []}] |
| 162 | +) |
221 | 163 |
|
222 | | - Process.sleep(:infinity) |
223 | | -end) |
| 164 | +ErrorTrackerDev.Repo.migrate() |
0 commit comments