From fc0d3ccf6bcadac0831ae8eae751417195aa6637 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=93scar=20de=20Arriba?= Date: Fri, 26 Jul 2024 17:18:29 +0200 Subject: [PATCH 01/23] Documentation changes --- lib/error_tracker/integrations/oban.ex | 2 +- lib/error_tracker/integrations/phoenix.ex | 2 +- lib/error_tracker/integrations/plug.ex | 4 ++-- lib/error_tracker/{migrations.ex => migration.ex} | 13 +++++++------ lib/error_tracker/repo.ex | 3 ++- lib/error_tracker/schemas/error.ex | 6 +++++- lib/error_tracker/schemas/occurrence.ex | 2 +- lib/error_tracker/web/components/layouts.ex | 1 + lib/error_tracker/web/hooks/set_assigns.ex | 4 +--- lib/error_tracker/web/router.ex | 4 +++- lib/error_tracker/web/router/routes.ex | 4 +--- 11 files changed, 25 insertions(+), 20 deletions(-) rename lib/error_tracker/{migrations.ex => migration.ex} (99%) diff --git a/lib/error_tracker/integrations/oban.ex b/lib/error_tracker/integrations/oban.ex index cc8e815..58fc894 100644 --- a/lib/error_tracker/integrations/oban.ex +++ b/lib/error_tracker/integrations/oban.ex @@ -1,6 +1,6 @@ defmodule ErrorTracker.Integrations.Oban do @moduledoc """ - The ErrorTracker integration with Oban. + Integration with Oban. ## How it works diff --git a/lib/error_tracker/integrations/phoenix.ex b/lib/error_tracker/integrations/phoenix.ex index 272ed42..26c537f 100644 --- a/lib/error_tracker/integrations/phoenix.ex +++ b/lib/error_tracker/integrations/phoenix.ex @@ -1,6 +1,6 @@ defmodule ErrorTracker.Integrations.Phoenix do @moduledoc """ - The ErrorTracker integration with Phoenix applications. + Integration with Phoenix applications. ## How it works diff --git a/lib/error_tracker/integrations/plug.ex b/lib/error_tracker/integrations/plug.ex index 51112a4..3353e14 100644 --- a/lib/error_tracker/integrations/plug.ex +++ b/lib/error_tracker/integrations/plug.ex @@ -1,10 +1,10 @@ defmodule ErrorTracker.Integrations.Plug do @moduledoc """ - The ErrorTracker integration with Plug applications. + Integration with Plug applications. ## How it works - The way to use this integration is by adding it to either your `Plug.Builder`` + The way to use this integration is by adding it to either your `Plug.Builder` or `Plug.Router`: ```elixir diff --git a/lib/error_tracker/migrations.ex b/lib/error_tracker/migration.ex similarity index 99% rename from lib/error_tracker/migrations.ex rename to lib/error_tracker/migration.ex index 94a4c32..7caec9c 100644 --- a/lib/error_tracker/migrations.ex +++ b/lib/error_tracker/migration.ex @@ -1,4 +1,11 @@ defmodule ErrorTracker.Migrations do + @moduledoc false + + defdelegate up(opts \\ []), to: ErrorTracker.Migration + defdelegate down(opts \\ []), to: ErrorTracker.Migration +end + +defmodule ErrorTracker.Migration do @moduledoc """ Create and modify the database tables for the ErrorTracker. @@ -92,12 +99,6 @@ defmodule ErrorTracker.Migrations do config :error_tracker, :prefix, "custom_schema" ``` """ - defdelegate up(opts \\ []), to: ErrorTracker.Migration - defdelegate down(opts \\ []), to: ErrorTracker.Migration -end - -defmodule ErrorTracker.Migration do - @moduledoc false @callback up(Keyword.t()) :: :ok @callback down(Keyword.t()) :: :ok diff --git a/lib/error_tracker/repo.ex b/lib/error_tracker/repo.ex index f736052..913616a 100644 --- a/lib/error_tracker/repo.ex +++ b/lib/error_tracker/repo.ex @@ -1,7 +1,8 @@ defmodule ErrorTracker.Repo do @moduledoc """ - Wraps Ecto.Repo calls and applies default options. + Wrapper around Ecto Repo calls to apply default options. """ + def insert!(struct_or_changeset, opts \\ []) do dispatch(:insert!, [struct_or_changeset], opts) end diff --git a/lib/error_tracker/schemas/error.ex b/lib/error_tracker/schemas/error.ex index 4e1c2e6..64aa97a 100644 --- a/lib/error_tracker/schemas/error.ex +++ b/lib/error_tracker/schemas/error.ex @@ -1,9 +1,13 @@ defmodule ErrorTracker.Error do @moduledoc """ - An Error is a type of exception recorded by the ErrorTracker. + Schema to store an error or exception recorded by the ErrorTracker. It stores a kind, reason and source code location to generate a unique fingerprint that can be used to avoid duplicates. + + The fingerprint currently does not include the reason itself because it can + contain specific details that can change on the same error depending on + runtime conditions. """ use Ecto.Schema diff --git a/lib/error_tracker/schemas/occurrence.ex b/lib/error_tracker/schemas/occurrence.ex index ab76a5c..f36c583 100644 --- a/lib/error_tracker/schemas/occurrence.ex +++ b/lib/error_tracker/schemas/occurrence.ex @@ -1,6 +1,6 @@ defmodule ErrorTracker.Occurrence do @moduledoc """ - An Occurrence is a particular instance of an error in a given time. + Schema to store a particular instance of an error in a given time. It contains all the metadata available about the moment and the environment in which the exception raised. diff --git a/lib/error_tracker/web/components/layouts.ex b/lib/error_tracker/web/components/layouts.ex index 292429f..a7aaeb8 100644 --- a/lib/error_tracker/web/components/layouts.ex +++ b/lib/error_tracker/web/components/layouts.ex @@ -1,4 +1,5 @@ defmodule ErrorTracker.Web.Layouts do + @moduledoc false use ErrorTracker.Web, :html alias ErrorTracker.Web.Layouts.Navbar diff --git a/lib/error_tracker/web/hooks/set_assigns.ex b/lib/error_tracker/web/hooks/set_assigns.ex index 653aab0..192f690 100644 --- a/lib/error_tracker/web/hooks/set_assigns.ex +++ b/lib/error_tracker/web/hooks/set_assigns.ex @@ -1,7 +1,5 @@ defmodule ErrorTracker.Web.Hooks.SetAssigns do - @moduledoc """ - Mounting hooks to set environment configuration on the socket. - """ + @moduledoc false import Phoenix.Component def on_mount({:set_dashboard_path, path}, _params, _session, socket) do diff --git a/lib/error_tracker/web/router.ex b/lib/error_tracker/web/router.ex index 8254b34..4041689 100644 --- a/lib/error_tracker/web/router.ex +++ b/lib/error_tracker/web/router.ex @@ -1,5 +1,7 @@ defmodule ErrorTracker.Web.Router do - @moduledoc false + @moduledoc """ + Integration of the ErrorTracker UI into your application's router. + """ @doc """ Creates the routes needed to use the `ErrorTracker` web interface. diff --git a/lib/error_tracker/web/router/routes.ex b/lib/error_tracker/web/router/routes.ex index 5945b42..1d8bb96 100644 --- a/lib/error_tracker/web/router/routes.ex +++ b/lib/error_tracker/web/router/routes.ex @@ -1,7 +1,5 @@ defmodule ErrorTracker.Web.Router.Routes do - @moduledoc """ - Module used to generate dashboard routes. - """ + @moduledoc false alias ErrorTracker.Error alias ErrorTracker.Occurrence From 05416d2f36f5d13366dce1f6220ce364b2fd7f5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=93scar=20de=20Arriba?= Date: Fri, 26 Jul 2024 17:35:43 +0200 Subject: [PATCH 02/23] More documentation --- lib/error_tracker.ex | 48 ++++++++++++++++++++++++++ lib/error_tracker/integrations/oban.ex | 24 ++++++++++++- lib/error_tracker/schemas/error.ex | 4 +++ 3 files changed, 75 insertions(+), 1 deletion(-) diff --git a/lib/error_tracker.ex b/lib/error_tracker.ex index aa83fb8..f0db488 100644 --- a/lib/error_tracker.ex +++ b/lib/error_tracker.ex @@ -11,6 +11,27 @@ defmodule ErrorTracker do alias ErrorTracker.Error alias ErrorTracker.Repo + @doc """ + Report a exception to be stored. + + Aside from the exception, it is expected to receive the stacktrace and, + optionally, a context map which will be merged with the current process + context. + + ## Exceptions + + Exceptions passed can be in three different forms: + + * An exception struct: the module of the exception is stored alongside with + the exception message. + + * A `{kind, exception}` tuple in which the `exception` is an struct: it + behaves the same as when passing just the exception struct. + + * A `{kind, reason}` tuple: it stores the kind and the message itself casted + to strings, as it is useful for some errors like EXIT signals or custom error + messages. + """ def report(exception, stacktrace, given_context \\ %{}) do {kind, reason} = case exception do @@ -40,18 +61,42 @@ defmodule ErrorTracker do |> Repo.insert!() end + @doc """ + Marks an error as resolved. + + If an error is marked as resolved and it happens again, it will automatically + appear as unresolved again. + """ def resolve(error = %Error{status: :unresolved}) do changeset = Ecto.Changeset.change(error, status: :resolved) Repo.update(changeset) end + @doc """ + Marks an error as unresolved. + """ def unresolve(error = %Error{status: :resolved}) do changeset = Ecto.Changeset.change(error, status: :unresolved) Repo.update(changeset) end + @doc """ + Sets current process context. + + By default it will merge the current context with the new one received, taking + preference the new context's contents over the existsing ones if any key + matches. + + ## Depth of the context + + You can store context on more than one level of depth, but take into account + that the merge operation is performed on the first level. + + That means that any existing data on deep levels fot he current context will + be replaced if the first level key is received on the new contents. + """ @spec set_context(context()) :: context() def set_context(params) when is_map(params) do current_context = Process.get(:error_tracker_context, %{}) @@ -61,6 +106,9 @@ defmodule ErrorTracker do params end + @doc """ + Obtain the context of the current process. + """ @spec get_context() :: context() def get_context do Process.get(:error_tracker_context, %{}) diff --git a/lib/error_tracker/integrations/oban.ex b/lib/error_tracker/integrations/oban.ex index 58fc894..ec58cd7 100644 --- a/lib/error_tracker/integrations/oban.ex +++ b/lib/error_tracker/integrations/oban.ex @@ -2,10 +2,32 @@ defmodule ErrorTracker.Integrations.Oban do @moduledoc """ Integration with Oban. - ## How it works + ## How to use it + + It is a plug&play integration. As long as you have Oban installed the + ErrorTracker will receive and store the errors as they are reported. + + ### How it works It works using your application's Telemetry events, so you don't need to modify anything on your application. + + ### Default context + + By default we store some context for you on errors generated in an Oban + process: + + * `job.id`: the unqiue ID of the job. + + * `job.worker`: the name of the worker module. + + * `job.queue`: the name of the queue in which the job was inserted. + + * `job.args`: the arguments of the job being executed. + + * `job.priority`: the priority of the job. + + * `job.attempt`: the number of attempts performed for the job. """ # https://hexdocs.pm/oban/Oban.Telemetry.html diff --git a/lib/error_tracker/schemas/error.ex b/lib/error_tracker/schemas/error.ex index 64aa97a..b54beb4 100644 --- a/lib/error_tracker/schemas/error.ex +++ b/lib/error_tracker/schemas/error.ex @@ -26,6 +26,10 @@ defmodule ErrorTracker.Error do timestamps(type: :utc_datetime_usec) end + @doc """ + Generates a new structure with all required metadata, including fingerprint + calculation. + """ def new(kind, reason, stacktrace = %ErrorTracker.Stacktrace{}) do source = ErrorTracker.Stacktrace.source(stacktrace) From 675a14f1a514331156779c99f353ba3a8882c603 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=93scar=20de=20Arriba?= Date: Fri, 26 Jul 2024 17:39:45 +0200 Subject: [PATCH 03/23] Update docs --- lib/error_tracker/integrations/oban.ex | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/lib/error_tracker/integrations/oban.ex b/lib/error_tracker/integrations/oban.ex index ec58cd7..34c9fad 100644 --- a/lib/error_tracker/integrations/oban.ex +++ b/lib/error_tracker/integrations/oban.ex @@ -4,13 +4,13 @@ defmodule ErrorTracker.Integrations.Oban do ## How to use it - It is a plug&play integration. As long as you have Oban installed the + It is a plug and play integration: as long as you have Oban installed the ErrorTracker will receive and store the errors as they are reported. ### How it works - It works using your application's Telemetry events, so you don't need to - modify anything on your application. + It works using Oban's Telemetry events, so you don't need to modify anything + on your application. ### Default context @@ -36,12 +36,19 @@ defmodule ErrorTracker.Integrations.Oban do [:oban, :job, :exception] ] + @doc """ + Attachs to Oban's Telemtry events if the library is detected. + + This function is usually called internally during the startup process so you + don't have to. + """ def attach do if Application.spec(:oban) do :telemetry.attach_many(__MODULE__, @events, &__MODULE__.handle_event/4, :no_config) end end + @doc false def handle_event([:oban, :job, :start], _measurements, metadata, :no_config) do %{job: job} = metadata From 01eef2c29c4dbe2c22966c133d2d95f796e4b536 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=93scar=20de=20Arriba?= Date: Fri, 26 Jul 2024 20:09:06 +0200 Subject: [PATCH 04/23] Update docs --- lib/error_tracker/integrations/oban.ex | 2 +- lib/error_tracker/integrations/phoenix.ex | 52 +++++++++++++++++++++-- lib/error_tracker/integrations/plug.ex | 32 +++++++++++++- 3 files changed, 80 insertions(+), 6 deletions(-) diff --git a/lib/error_tracker/integrations/oban.ex b/lib/error_tracker/integrations/oban.ex index 34c9fad..69644e7 100644 --- a/lib/error_tracker/integrations/oban.ex +++ b/lib/error_tracker/integrations/oban.ex @@ -37,7 +37,7 @@ defmodule ErrorTracker.Integrations.Oban do ] @doc """ - Attachs to Oban's Telemtry events if the library is detected. + Attachs to Oban's Telemetry events if the library is detected. This function is usually called internally during the startup process so you don't have to. diff --git a/lib/error_tracker/integrations/phoenix.ex b/lib/error_tracker/integrations/phoenix.ex index 26c537f..9da9134 100644 --- a/lib/error_tracker/integrations/phoenix.ex +++ b/lib/error_tracker/integrations/phoenix.ex @@ -2,10 +2,49 @@ defmodule ErrorTracker.Integrations.Phoenix do @moduledoc """ Integration with Phoenix applications. - ## How it works + ## How to use it - It works using your application's Telemetry events, so you don't need to - modify anything on your application. + It is a plug and play integration: as long as you have Phoenix installed the + ErrorTracker will receive and store the errors as they are reported. + + It also collects the exceptions that raise on your LiveView modules. + + ### How it works + + It works using Phoenix's Telemetry events, so you don't need to modify + anything on your application. + + ### Errors on the Endpoint + + This integration only catches errors that raise after the requests hits your + Router. That means that an exception on a plug defined on your Endpoint will + not be reported. + + If you want to also catch those errors, we recommend you to set up the + `ErrorTracker.Integrations.Plug` integration too. + + ### Default context + + For errors that are reported when executing regular HTTP requests (the ones + that go to Controllers), the context added by default is the same that you + can find on the `ErrorTracker.Integrations.Plug` integration. + + As for exceptions generated in LiveView processes, we collect some special + information on the context: + + * `live_view.view`: the LiveView module itself, + + * `live_view.uri`: last URI that loaded the LiveView (available when the + `handle_params` function is invoked). + + * `live_view.params`: the params received by the LiveView (available when the + `handle_params` function is invoked). + + * `live_view.event`: last event received by the LiveView (available when the + `handle_event` function is invoked). + + * `live_view.event_params`: last event params received by the LiveView + (available when the `handle_event` function is invoked). """ alias ErrorTracker.Integrations.Plug, as: PlugIntegration @@ -24,12 +63,19 @@ defmodule ErrorTracker.Integrations.Phoenix do [:phoenix, :live_view, :render, :exception] ] + @doc """ + Attachs to Phoenix's Telemetry events if the library is detected. + + This function is usually called internally during the startup process so you + don't have to. + """ def attach do if Application.spec(:phoenix) do :telemetry.attach_many(__MODULE__, @events, &__MODULE__.handle_event/4, :no_config) end end + @doc false def handle_event([:phoenix, :router_dispatch, :start], _measurements, metadata, :no_config) do PlugIntegration.set_context(metadata.conn) end diff --git a/lib/error_tracker/integrations/plug.ex b/lib/error_tracker/integrations/plug.ex index 3353e14..07b24c7 100644 --- a/lib/error_tracker/integrations/plug.ex +++ b/lib/error_tracker/integrations/plug.ex @@ -2,7 +2,9 @@ defmodule ErrorTracker.Integrations.Plug do @moduledoc """ Integration with Plug applications. - ## How it works + ## How to use it + + ### Plug applications The way to use this integration is by adding it to either your `Plug.Builder` or `Plug.Router`: @@ -16,7 +18,7 @@ defmodule ErrorTracker.Integrations.Plug do end ``` - ## Using it with Phoenix + ### Phoenix applications There is a particular use case which can be useful when running a Phoenix web application. @@ -33,6 +35,30 @@ defmodule ErrorTracker.Integrations.Plug do ... end ``` + + ### Default context + + By default we store some context for you on errors generated during a Plug + request: + + * `request.host`: the `conn.host` value. + + * `request.ip`: the IP address that initiated the request. It includes parsing + proxy headers + + * `request.method`: the HTTP method of the request. + + * `request.path`: the path of the request. + + * `request.query`: the query string of the request. + + * `request.params`: parsed params of the request (only available if they have + been fetched and parsed as part of the Plug pipeline). + + * `request.headers`: headers received on the request. All headers are included + by default except for the `Cookie` ones, as they may include large and + sensitive content like sessions. + """ defmacro __using__(_opts) do @@ -69,6 +95,7 @@ defmodule ErrorTracker.Integrations.Plug do end end + @doc false def report_error(conn, reason, stack) do unless Process.get(:error_tracker_router_exception_reported) do try do @@ -79,6 +106,7 @@ defmodule ErrorTracker.Integrations.Plug do end end + @doc false def set_context(conn = %Plug.Conn{}) do conn |> build_context |> ErrorTracker.set_context() end From aa2c65775f0c2ea8366cc6dcc389aed965e24550 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=93scar=20de=20Arriba?= Date: Fri, 26 Jul 2024 20:22:06 +0200 Subject: [PATCH 05/23] More documentation --- lib/error_tracker.ex | 58 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/lib/error_tracker.ex b/lib/error_tracker.ex index f0db488..c9acefc 100644 --- a/lib/error_tracker.ex +++ b/lib/error_tracker.ex @@ -1,6 +1,64 @@ defmodule ErrorTracker do @moduledoc """ En Elixir based built-in error tracking solution. + + The main objectives behind this project are: + + * Provide a basic free error tracking solution: because tracking errors on + your application should be a requirement to almost any project, and helps to + provide quality and maintenance to your project. + + * Easy to use: by providing plug and play integrations, documentation and a + simple UI to manage your errors. + + * Be as minimalistic as possible: you just need a database to store errors and + an Phoenix application if you want to inspect them via web. That's all. + + ## How to report an error + + You can report an exception as easy as: + + ```elixir + try do + # your code + catch + e -> + ErrorTracker.report(e, __STACKTRACE__) + end + ``` + + ## Integrations + + We currently include integrations for what we consider the basic stack of + an application: Phoenix, Plug and Oban. + + However, we may continue working in adding support for more systems and + libraries in the future if there is enough interest by the community. + + ## Context + + Aside from the information abot each exception (kind, message, stacktrace...) + we also store contexts. + + Contexts are arbitrary maps that allow you to store extra information of an + exception to be able to reproduce it later. + + Each integration includes a default context with the useful information they + can gather, but aside from that you can also add your own information: + + ```elixir + ErrorTracker.set_context(%{user_id: conn.assigns.current_user.id}) + ``` + + ## Migrations + + As we store information in a database, there are migrations to create the + required database objects (tables, indices...) for you to stay up to date with + the project. + + Please, check the documentation of the `ErrorTracker.Migration` module for + more details. + """ @typedoc """ From 2bd8358f3e25228ae45c9f71b2f6a88f5e517bc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=93scar=20de=20Arriba?= Date: Fri, 26 Jul 2024 20:41:46 +0200 Subject: [PATCH 06/23] More documentation --- lib/error_tracker.ex | 9 +++++++++ lib/error_tracker/web.ex | 23 +++++++++++++++++++++-- lib/error_tracker/web/router.ex | 8 ++++++++ 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/lib/error_tracker.ex b/lib/error_tracker.ex index c9acefc..b8d4327 100644 --- a/lib/error_tracker.ex +++ b/lib/error_tracker.ex @@ -59,6 +59,15 @@ defmodule ErrorTracker do Please, check the documentation of the `ErrorTracker.Migration` module for more details. + ## Web UI + + We have included a dashboard (built with the awesome LiveView library) that + can be used to see the errors recorded for your project, as well as mark them + as resolved. + + You can find more information about how to integrate it on your Phoenix + application on the documentation of `ErrorTracker.Web`. + """ @typedoc """ diff --git a/lib/error_tracker/web.ex b/lib/error_tracker/web.ex index eb291c6..b1f865a 100644 --- a/lib/error_tracker/web.ex +++ b/lib/error_tracker/web.ex @@ -1,6 +1,6 @@ defmodule ErrorTracker.Web do @moduledoc """ - ErrorTracker includes a Web UI to view and inspect errors occurred on your + ErrorTracker includes a dashboard to view and inspect errors occurred on your application and already stored on the database. In order to use it, you need to add the following to your Phoenix's ` @@ -17,7 +17,22 @@ defmodule ErrorTracker.Web do end ``` - This will add the routes needed for the ErrorTracker LiveView UI to work. + This will add the routes needed for the ErrorTracker dashboard to work. + + ## Security considerations + + Errors may contain sensitive information, like IP addresses, users information + or even passwords sent on forms! + + Securing your dashboard is an important part of integrating `ErrorTracker` on + your project. + + In order to do so, we recommend implementing your own security mechanisms in + the form of a mount hook and pass it to the `error_tracker_dashboard` macro + using the `on_mount` option. + + You can find more details on + `ErrorTracker.Web.Router.error_tracker_dashboard/2`. ## LiveView socket options @@ -36,6 +51,7 @@ defmodule ErrorTracker.Web do ``` """ + @doc false def html do quote do import Phoenix.Controller, only: [get_csrf_token: 0] @@ -44,6 +60,7 @@ defmodule ErrorTracker.Web do end end + @doc false def live_view do quote do use Phoenix.LiveView, layout: {ErrorTracker.Web.Layouts, :live} @@ -52,6 +69,7 @@ defmodule ErrorTracker.Web do end end + @doc false def live_component do quote do use Phoenix.LiveComponent @@ -60,6 +78,7 @@ defmodule ErrorTracker.Web do end end + @doc false def router do quote do import ErrorTracker.Web.Router diff --git a/lib/error_tracker/web/router.ex b/lib/error_tracker/web/router.ex index 4041689..74c3af5 100644 --- a/lib/error_tracker/web/router.ex +++ b/lib/error_tracker/web/router.ex @@ -7,6 +7,14 @@ defmodule ErrorTracker.Web.Router do Creates the routes needed to use the `ErrorTracker` web interface. It requires a path in which you are going to serve the web interface. + + ## Options + + * `on_mount`: a list of mount hooks to use before invoking the dashboard + LiveView views. + + * `as`: a session name to use for the dashboard LiveView session. By default + it uses `:error_tracker_dashboard`. """ defmacro error_tracker_dashboard(path, opts \\ []) do {session_name, session_opts} = parse_options(opts, path) From d2901a519749aac8f9a9c89b4c77cb26143b5e4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=93scar=20de=20Arriba?= Date: Fri, 26 Jul 2024 20:59:14 +0200 Subject: [PATCH 07/23] Update docs --- lib/error_tracker.ex | 37 +++++++++++++++++++++++++++---------- mix.exs | 28 +++++++++++++++++++++++++++- 2 files changed, 54 insertions(+), 11 deletions(-) diff --git a/lib/error_tracker.ex b/lib/error_tracker.ex index b8d4327..1612d06 100644 --- a/lib/error_tracker.ex +++ b/lib/error_tracker.ex @@ -14,18 +14,21 @@ defmodule ErrorTracker do * Be as minimalistic as possible: you just need a database to store errors and an Phoenix application if you want to inspect them via web. That's all. - ## How to report an error + ## Requirements - You can report an exception as easy as: + ErrorTracker requires: - ```elixir - try do - # your code - catch - e -> - ErrorTracker.report(e, __STACKTRACE__) - end - ``` + * Elixir: `~> 1.15` + + * Ecto: `~> 3.11` + + * Phoenix LiveView `~> 0.19` or `~> 1.0` + + * PostgreSQL + + ## Installation + + TODO ## Integrations @@ -35,6 +38,20 @@ defmodule ErrorTracker do However, we may continue working in adding support for more systems and libraries in the future if there is enough interest by the community. + ## Report an error + + You may relay on already built integrations by default, but in case you want + to report an exception by yourself, it is an easy as: + + ```elixir + try do + # your code + catch + e -> + ErrorTracker.report(e, __STACKTRACE__) + end + ``` + ## Context Aside from the information abot each exception (kind, message, stacktrace...) diff --git a/mix.exs b/mix.exs index f40688d..265c79e 100644 --- a/mix.exs +++ b/mix.exs @@ -12,7 +12,13 @@ defmodule ErrorTracker.MixProject do package: package(), description: description(), source_url: "https://github.com/elixir-error-tracker/error-tracker", - aliases: aliases() + aliases: aliases(), + name: "ErrorTracker", + docs: [ + main: "ErrorTracker", + formatters: ["html"], + groups_for_modules: groups_for_modules() + ] ] end @@ -40,6 +46,26 @@ defmodule ErrorTracker.MixProject do "An Elixir based built-in error tracking solution" end + defp groups_for_modules do + [ + Integrations: [ + ErrorTracker.Integrations.Oban, + ErrorTracker.Integrations.Phoenix, + ErrorTracker.Integrations.Plug + ], + Schemas: [ + ErrorTracker.Error, + ErrorTracker.Occurrence, + ErrorTracker.Stacktrace, + ErrorTracker.Stacktrace.Line + ], + "Web UI": [ + ErrorTracker.Web, + ErrorTracker.Web.Router + ] + ] + end + # Run "mix help deps" to learn about dependencies. defp deps do [ From 5d5c617bac0944c24f6e37b86ad46de048be0d87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=93scar=20de=20Arriba?= Date: Fri, 26 Jul 2024 21:00:30 +0200 Subject: [PATCH 08/23] Update --- lib/error_tracker.ex | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/lib/error_tracker.ex b/lib/error_tracker.ex index 1612d06..853b592 100644 --- a/lib/error_tracker.ex +++ b/lib/error_tracker.ex @@ -16,15 +16,7 @@ defmodule ErrorTracker do ## Requirements - ErrorTracker requires: - - * Elixir: `~> 1.15` - - * Ecto: `~> 3.11` - - * Phoenix LiveView `~> 0.19` or `~> 1.0` - - * PostgreSQL + ErrorTracker requires Elixir 1.15+, Ecto 3.11+, Phoenix LiveView 0.19+ and PostgreSQL ## Installation From db79bd6b2700e78681e4e5da68446ab4432f0c2b Mon Sep 17 00:00:00 2001 From: crbelaus Date: Mon, 29 Jul 2024 17:19:04 +0200 Subject: [PATCH 09/23] Security considerations for Router docs This is already mentioned on the Web module docs, but it is important enough to be mentioned again here. --- lib/error_tracker/web/router.ex | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/error_tracker/web/router.ex b/lib/error_tracker/web/router.ex index 74c3af5..800385b 100644 --- a/lib/error_tracker/web/router.ex +++ b/lib/error_tracker/web/router.ex @@ -8,6 +8,12 @@ defmodule ErrorTracker.Web.Router do It requires a path in which you are going to serve the web interface. + ## Security considerations + + Errors may contain sensitive information so it is recommended to use the `on_mount` + option to provide a custom hook that implements authentication and authorization + for access control. + ## Options * `on_mount`: a list of mount hooks to use before invoking the dashboard From b89dd16bdb40a8ade01499f738d890328b5ab824 Mon Sep 17 00:00:00 2001 From: crbelaus Date: Mon, 29 Jul 2024 17:33:42 +0200 Subject: [PATCH 10/23] Few improvements to the ErrorTracker module docs --- lib/error_tracker.ex | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/lib/error_tracker.ex b/lib/error_tracker.ex index 853b592..83803ee 100644 --- a/lib/error_tracker.ex +++ b/lib/error_tracker.ex @@ -8,7 +8,7 @@ defmodule ErrorTracker do your application should be a requirement to almost any project, and helps to provide quality and maintenance to your project. - * Easy to use: by providing plug and play integrations, documentation and a + * Be easy to use: by providing plug and play integrations, documentation and a simple UI to manage your errors. * Be as minimalistic as possible: you just need a database to store errors and @@ -32,7 +32,7 @@ defmodule ErrorTracker do ## Report an error - You may relay on already built integrations by default, but in case you want + You may rely on already built integrations by default, but in case you want to report an exception by yourself, it is an easy as: ```elixir @@ -53,12 +53,35 @@ defmodule ErrorTracker do exception to be able to reproduce it later. Each integration includes a default context with the useful information they - can gather, but aside from that you can also add your own information: + can gather, but aside from that you can also add your own information. You can + do this in a per-process way or in a per-call way (or both). + + **Per process** + + This allows you to set general context for the current process such as a Phoenix + request or an Oban job. For example you could include the following code in your + authentication Plug to automatically include the user ID on any error that is + tracked during the Phoenix request handling. ```elixir ErrorTracker.set_context(%{user_id: conn.assigns.current_user.id}) ``` + **Per call** + + As we had seen before you can use `ErrorTracker.report/3` to manually report an + error. The third parameter of this function is optional and allows you to include + extra context that will be tracked along with that error. + + ```elixir + try do + # your code + catch + e -> + ErrorTracker.report(e, __STACKTRACE__, %{user_id: your_user_id}) + end + ``` + ## Migrations As we store information in a database, there are migrations to create the From 6b9325844a509199fc418ed3c67a738725abc31d Mon Sep 17 00:00:00 2001 From: crbelaus Date: Mon, 29 Jul 2024 17:34:38 +0200 Subject: [PATCH 11/23] Do not expose ErrorTracker.Error.new/2 This function should not be used directly. ErrorTracker.report/3 should be used insted. --- lib/error_tracker/schemas/error.ex | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/error_tracker/schemas/error.ex b/lib/error_tracker/schemas/error.ex index b54beb4..2d55554 100644 --- a/lib/error_tracker/schemas/error.ex +++ b/lib/error_tracker/schemas/error.ex @@ -26,10 +26,7 @@ defmodule ErrorTracker.Error do timestamps(type: :utc_datetime_usec) end - @doc """ - Generates a new structure with all required metadata, including fingerprint - calculation. - """ + @doc false def new(kind, reason, stacktrace = %ErrorTracker.Stacktrace{}) do source = ErrorTracker.Stacktrace.source(stacktrace) From 1cd60596e2e5f7440b1014767a1fc531ac22c952 Mon Sep 17 00:00:00 2001 From: crbelaus Date: Mon, 29 Jul 2024 18:53:59 +0200 Subject: [PATCH 12/23] Getting Started guide --- README.md | 23 +------ guides/Getting Started.md | 128 ++++++++++++++++++++++++++++++++++++++ lib/error_tracker.ex | 59 +++++------------- mix.exs | 6 +- 4 files changed, 148 insertions(+), 68 deletions(-) create mode 100644 guides/Getting Started.md diff --git a/README.md b/README.md index 1430ec5..3edbd59 100644 --- a/README.md +++ b/README.md @@ -4,26 +4,7 @@ En Elixir based built-in error tracking solution. ## Configuration -Set up the repository: - -```elixir -config :error_tracker, - repo: MyApp.Repo -``` - -And you are ready to go! - -By default Phoenix and Oban integrations will start registering exceptions. - -If you want to also catch exceptions before your Phoenix Router (in plugs used -on your Endpoint) or your application just use `Plug` but not `Phoenix`, you can -attach to those errors with: - -```elixir -defmodule MyApp.Endpoint do - use ErrorTracker.Integrations.Plug -end -``` +Take a look at the [Getting Started](/guides/Getting%20Started.md) guide. ## Development @@ -61,5 +42,3 @@ To do so you can execute this task in a separate terminal: ``` mix assets.watch ``` - - diff --git a/guides/Getting Started.md b/guides/Getting Started.md new file mode 100644 index 0000000..0f7b9c0 --- /dev/null +++ b/guides/Getting Started.md @@ -0,0 +1,128 @@ +# Getting Started + +This guide is an introduction to the ErrorTracker, an Elixir based built-in error tracking solution. The ErrorTracker provides a basic and free error-tracking solution integrated in your own application. It is designed to be easy to install and easy to use so you can integrate it in your existing project with minimal changes. The only requirement is a relational database in which errors will be tracked. + +In this guide we will learn how to install the ErrorTracker in an Elixir project so you can start reporting errors as soon as possible. We will also cover more advanced topics such as how to report custom errors and how to add extra context to reported errors. + +**This guide requires you to have setup Ecto with PostgreSQL beforehand.** + +## Installing the ErrorTracking as a dependency + +The first step add the ErrorTracker to your application is to declare the package as a dependency in your `mix.exs` file: + +```elixir +# mix.exs +defp deps do + [ + {:error_tracker, "~> 1.0"} + ] +end +``` + +Once the ErrorTracker is declared as a dependency of your application, you can install it with the following command: + +```bash +mix deps.get +``` + +## Configuring the ErrorTracker + +The ErrorTracker needs a few configuration options to work. This configuration should be added in your `config/config.exs` file: + +```elixir +config :error_tracker, + repo: MyApp.Repo, + otp_app: :my_app +``` + +The `:repo` option specifies the repository that will be used by the ErrorTracker. You can use your regular application repository or, if you prefer to keep errors in a different database, a different one. + +The `:otp_app` option specifies your application name. When an error happens the ErrorTracker will use this information to understand which parts of the stacktrace belong to your application and which parts belong to third party dependencies. This allows you to filter in-app vs third-party frames when viewing errors. + +## Setting up the database + +Since the ErrorTracker tracks errors in the database you must create a database migration to add the `error_tracker_errors` table: + +``` +mix ecto.gen.migration add_error_tracker +``` + +Open the generated migration and call the `up` and `down` functions on `ErrorTracker.Migration`: + +```elixir +defmodule MyApp.Repo.Migrations.AddErrorTracker do + use Ecto.Migration + + def up, do: ErrorTracker.Migrations.up() + def down, do: ErrorTracker.Migrations.down() +end +``` + +You can run the migration and perform the database changes with the following command: + +```bash +mix ecto.migrate +``` + +For more information about how to handle migrations take a look at the `ErrorTracker.Migration` module docs. + + + +## Automatic error tracking + +At this point, the ErrorTracker is ready to track errors. It will automatically start when your application boots and track errors that happen in your Phoenix controllers, Phoenix LiveViews and Oban jobs. The `ErrorTracker.Integrations.Phoenix` and `ErrorTracker.Integrations.Oban` provide detailed information about how this works. + +If your application uses Plug but not Phoenix, you will need to add the relevant integration in your `Plug.Builder` or `Plug.Router` module. + +```elixir +defmodule MyApp.Router do + use Plug.Router + use ErrorTracker.Integrations.Plug + + # Your code here +end +``` + +This is also required if you want to track errors that happen in your Phoenix endpoint, before the Phoenix router starts running. Keep in mind that this won't be needed in most cases as endpoint errors are very infrequent. + +```elixir +defmodule MyApp.Endpoint do + use Phoenix.Endpoint + use ErrorTracker.Integrations.Plug + + # Your code here +end +``` + +You can learn more about this in the `ErrorTracker.Integrations.Plug` module documentation. + +## Error context + +The default integrations include some additional context when tracking errors. You can take a look at the relevant integration modules to see what is being tracked. + +In certain cases you may want to include some additional information when tracking errors. For example it may be useful to track the user ID that was using the application when an error happened. Fortunately, the ErrorTracker allows you to enrich the default context with custom information. + +The `ErrorTracker.set_context/1` function stores the given context in the current process so any errors that happen in that proces (for example a Phoenix request or an Oban job) will include this given context along with the default integration context. + +```elixir +ErrorTracker.set_context(%{user_id: conn.assigns.current_user.id}) +``` + +## Manual error tracking + +If you want to report custom errors that fall outside the default integrations scope you may use `ErrorTracker.report/2`. This allows you to report an exception by yourself: + +```elixir +try do + # your code +catch + e -> + ErrorTracker.report(e, __STACKTRACE__) +end +``` + +You can also use `ErrorTracker.report/3` and set some custom context that will be included along with the reported error. + +## Web UI + +The ErrorTracker also provides a dashboard built with Phoenix LiveView that can be used to see and manage the recorded errors. This is completely optional and you can find more information about it in the `ErrorTracker.Web` module documentation. diff --git a/lib/error_tracker.ex b/lib/error_tracker.ex index 83803ee..c84c0e6 100644 --- a/lib/error_tracker.ex +++ b/lib/error_tracker.ex @@ -18,10 +18,6 @@ defmodule ErrorTracker do ErrorTracker requires Elixir 1.15+, Ecto 3.11+, Phoenix LiveView 0.19+ and PostgreSQL - ## Installation - - TODO - ## Integrations We currently include integrations for what we consider the basic stack of @@ -30,19 +26,7 @@ defmodule ErrorTracker do However, we may continue working in adding support for more systems and libraries in the future if there is enough interest by the community. - ## Report an error - - You may rely on already built integrations by default, but in case you want - to report an exception by yourself, it is an easy as: - - ```elixir - try do - # your code - catch - e -> - ErrorTracker.report(e, __STACKTRACE__) - end - ``` + If you want to manually report an error you can use the `ErrorTracker.report/3` function. ## Context @@ -72,34 +56,6 @@ defmodule ErrorTracker do As we had seen before you can use `ErrorTracker.report/3` to manually report an error. The third parameter of this function is optional and allows you to include extra context that will be tracked along with that error. - - ```elixir - try do - # your code - catch - e -> - ErrorTracker.report(e, __STACKTRACE__, %{user_id: your_user_id}) - end - ``` - - ## Migrations - - As we store information in a database, there are migrations to create the - required database objects (tables, indices...) for you to stay up to date with - the project. - - Please, check the documentation of the `ErrorTracker.Migration` module for - more details. - - ## Web UI - - We have included a dashboard (built with the awesome LiveView library) that - can be used to see the errors recorded for your project, as well as mark them - as resolved. - - You can find more information about how to integrate it on your Phoenix - application on the documentation of `ErrorTracker.Web`. - """ @typedoc """ @@ -117,6 +73,19 @@ defmodule ErrorTracker do optionally, a context map which will be merged with the current process context. + Keep in mind that errors that happen in Phoenix controllers, Phoenix live views + and Oban jobs are automatically reported. You will need this function only if you + want to report custom errors. + + ```elixir + try do + # your code + catch + e -> + ErrorTracker.report(e, __STACKTRACE__) + end + ``` + ## Exceptions Exceptions passed can be in three different forms: diff --git a/mix.exs b/mix.exs index 265c79e..01c2f46 100644 --- a/mix.exs +++ b/mix.exs @@ -17,7 +17,11 @@ defmodule ErrorTracker.MixProject do docs: [ main: "ErrorTracker", formatters: ["html"], - groups_for_modules: groups_for_modules() + groups_for_modules: groups_for_modules(), + extra_section: "GUIDES", + extras: [ + "guides/Getting Started.md" + ] ] ] end From c0795a3d3efd75f12a59154325724069205d3e58 Mon Sep 17 00:00:00 2001 From: crbelaus Date: Mon, 29 Jul 2024 18:57:27 +0200 Subject: [PATCH 13/23] Getting started is the main doc page --- mix.exs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mix.exs b/mix.exs index 01c2f46..aca98f2 100644 --- a/mix.exs +++ b/mix.exs @@ -21,7 +21,9 @@ defmodule ErrorTracker.MixProject do extra_section: "GUIDES", extras: [ "guides/Getting Started.md" - ] + ], + api_reference: false, + main: "getting-started" ] ] end From f17c47c2c26e4591e16cb3caf072b90d29ff4997 Mon Sep 17 00:00:00 2001 From: crbelaus Date: Mon, 29 Jul 2024 19:01:28 +0200 Subject: [PATCH 14/23] Include maintainers names --- mix.exs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mix.exs b/mix.exs index aca98f2..14c11b5 100644 --- a/mix.exs +++ b/mix.exs @@ -44,7 +44,8 @@ defmodule ErrorTracker.MixProject do licenses: ["Apache-2.0"], links: %{ "GitHub" => "https://github.com/elixir-error-tracker/error-tracker" - } + }, + maintainers: ["Oscar de Arriba González", "Cristian Álvarez Belaustegui"] ] end From d66c84504a72d3ef5f05e8806fed81fc6d18e754 Mon Sep 17 00:00:00 2001 From: crbelaus Date: Mon, 29 Jul 2024 19:24:08 +0200 Subject: [PATCH 15/23] Rename :application to :otp_app --- lib/error_tracker/schemas/stacktrace.ex | 2 +- lib/error_tracker/web/live/show.ex | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/error_tracker/schemas/stacktrace.ex b/lib/error_tracker/schemas/stacktrace.ex index 2589f3a..14f3517 100644 --- a/lib/error_tracker/schemas/stacktrace.ex +++ b/lib/error_tracker/schemas/stacktrace.ex @@ -50,7 +50,7 @@ defmodule ErrorTracker.Stacktrace do application, just the first line. """ def source(stack = %__MODULE__{}) do - client_app = Application.fetch_env!(:error_tracker, :application) + client_app = Application.fetch_env!(:error_tracker, :otp_app) Enum.find(stack.lines, &(&1.application == client_app)) || List.first(stack.lines) end diff --git a/lib/error_tracker/web/live/show.ex b/lib/error_tracker/web/live/show.ex index 29244c4..a5c536d 100644 --- a/lib/error_tracker/web/live/show.ex +++ b/lib/error_tracker/web/live/show.ex @@ -13,7 +13,7 @@ defmodule ErrorTracker.Web.Live.Show do @impl Phoenix.LiveView def mount(%{"id" => id}, _session, socket) do error = Repo.get!(Error, id) - {:ok, assign(socket, error: error, app: Application.fetch_env!(:error_tracker, :application))} + {:ok, assign(socket, error: error, app: Application.fetch_env!(:error_tracker, :otp_app))} end @impl Phoenix.LiveView From ac1b6287cdd582b0ed961a71ad7e21dfdb18000a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=93scar=20de=20Arriba?= Date: Mon, 29 Jul 2024 19:47:15 +0200 Subject: [PATCH 16/23] Some tweaks to getting started --- guides/Getting Started.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/guides/Getting Started.md b/guides/Getting Started.md index 0f7b9c0..d6c531d 100644 --- a/guides/Getting Started.md +++ b/guides/Getting Started.md @@ -35,13 +35,13 @@ config :error_tracker, otp_app: :my_app ``` -The `:repo` option specifies the repository that will be used by the ErrorTracker. You can use your regular application repository or, if you prefer to keep errors in a different database, a different one. +The `:repo` option specifies the repository that will be used by the ErrorTracker. You can use your regular application repository, or a different one if you prefer to keep errors in a different database. The `:otp_app` option specifies your application name. When an error happens the ErrorTracker will use this information to understand which parts of the stacktrace belong to your application and which parts belong to third party dependencies. This allows you to filter in-app vs third-party frames when viewing errors. ## Setting up the database -Since the ErrorTracker tracks errors in the database you must create a database migration to add the `error_tracker_errors` table: +Since the ErrorTracker stores errors in the database you must create a database migration to add the required tables: ``` mix ecto.gen.migration add_error_tracker @@ -53,8 +53,8 @@ Open the generated migration and call the `up` and `down` functions on `ErrorTra defmodule MyApp.Repo.Migrations.AddErrorTracker do use Ecto.Migration - def up, do: ErrorTracker.Migrations.up() - def down, do: ErrorTracker.Migrations.down() + def up, do: ErrorTracker.Migration.up() + def down, do: ErrorTracker.Migration.down() end ``` @@ -66,8 +66,6 @@ mix ecto.migrate For more information about how to handle migrations take a look at the `ErrorTracker.Migration` module docs. - - ## Automatic error tracking At this point, the ErrorTracker is ready to track errors. It will automatically start when your application boots and track errors that happen in your Phoenix controllers, Phoenix LiveViews and Oban jobs. The `ErrorTracker.Integrations.Phoenix` and `ErrorTracker.Integrations.Oban` provide detailed information about how this works. @@ -83,7 +81,7 @@ defmodule MyApp.Router do end ``` -This is also required if you want to track errors that happen in your Phoenix endpoint, before the Phoenix router starts running. Keep in mind that this won't be needed in most cases as endpoint errors are very infrequent. +This is also required if you want to track errors that happen in your Phoenix endpoint, before the Phoenix router starts handling the request. Keep in mind that this won't be needed in most cases as endpoint errors are very infrequent. ```elixir defmodule MyApp.Endpoint do @@ -98,11 +96,11 @@ You can learn more about this in the `ErrorTracker.Integrations.Plug` module doc ## Error context -The default integrations include some additional context when tracking errors. You can take a look at the relevant integration modules to see what is being tracked. +The default integrations include some additional context when tracking errors. You can take a look at the relevant integration modules to see what is being tracked out of the box. In certain cases you may want to include some additional information when tracking errors. For example it may be useful to track the user ID that was using the application when an error happened. Fortunately, the ErrorTracker allows you to enrich the default context with custom information. -The `ErrorTracker.set_context/1` function stores the given context in the current process so any errors that happen in that proces (for example a Phoenix request or an Oban job) will include this given context along with the default integration context. +The `ErrorTracker.set_context/1` function stores the given context in the current process so any errors that happen in that process (for example a Phoenix request or an Oban job) will include this given context along with the default integration context. ```elixir ErrorTracker.set_context(%{user_id: conn.assigns.current_user.id}) @@ -125,4 +123,6 @@ You can also use `ErrorTracker.report/3` and set some custom context that will b ## Web UI -The ErrorTracker also provides a dashboard built with Phoenix LiveView that can be used to see and manage the recorded errors. This is completely optional and you can find more information about it in the `ErrorTracker.Web` module documentation. +The ErrorTracker also provides a dashboard built with Phoenix LiveView that can be used to see and manage the recorded errors. + +This is completely optional and you can find more information about it in the `ErrorTracker.Web` module documentation. From 0a047eeaf7dc1bd2b421d65b391c42ef203f30e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=93scar=20de=20Arriba?= Date: Mon, 29 Jul 2024 19:52:23 +0200 Subject: [PATCH 17/23] Hide custom repo config --- lib/error_tracker/repo.ex | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/error_tracker/repo.ex b/lib/error_tracker/repo.ex index 913616a..e243a6b 100644 --- a/lib/error_tracker/repo.ex +++ b/lib/error_tracker/repo.ex @@ -1,7 +1,5 @@ defmodule ErrorTracker.Repo do - @moduledoc """ - Wrapper around Ecto Repo calls to apply default options. - """ + @moduledoc false def insert!(struct_or_changeset, opts \\ []) do dispatch(:insert!, [struct_or_changeset], opts) From 5a0946fb288155586fe4cadecaa1f0e88b86ed4a Mon Sep 17 00:00:00 2001 From: crbelaus Date: Mon, 29 Jul 2024 19:46:06 +0200 Subject: [PATCH 18/23] Handle scoped paths for the dashboard --- lib/error_tracker/web/router.ex | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/lib/error_tracker/web/router.ex b/lib/error_tracker/web/router.ex index 800385b..b01d78d 100644 --- a/lib/error_tracker/web/router.ex +++ b/lib/error_tracker/web/router.ex @@ -23,16 +23,20 @@ defmodule ErrorTracker.Web.Router do it uses `:error_tracker_dashboard`. """ defmacro error_tracker_dashboard(path, opts \\ []) do - {session_name, session_opts} = parse_options(opts, path) - - quote do - scope unquote(path), alias: false, as: false do + quote bind_quoted: [path: path, opts: opts] do + # Ensure that the given path includes previous scopes so we can generate proper + # paths for navigating through the dashboard. + scoped_path = Phoenix.Router.scoped_path(__MODULE__, path) + # Generate the session name and session hooks. + {session_name, session_opts} = parse_options(opts, scoped_path) + + scope path, alias: false, as: false do import Phoenix.LiveView.Router, only: [live: 4, live_session: 3] - live_session unquote(session_name), unquote(session_opts) do - live "/", ErrorTracker.Web.Live.Dashboard, :index, as: unquote(session_name) - live "/:id", ErrorTracker.Web.Live.Show, :show, as: unquote(session_name) - live "/:id/:occurrence_id", ErrorTracker.Web.Live.Show, :show, as: unquote(session_name) + live_session session_name, session_opts do + live "/", ErrorTracker.Web.Live.Dashboard, :index, as: session_name + live "/:id", ErrorTracker.Web.Live.Show, :show, as: session_name + live "/:id/:occurrence_id", ErrorTracker.Web.Live.Show, :show, as: session_name end end end From 05de05d63ac1883d787d99fe1112a01f8129d90f Mon Sep 17 00:00:00 2001 From: crbelaus Date: Mon, 29 Jul 2024 19:54:36 +0200 Subject: [PATCH 19/23] Store dashboard path in socket's private map --- lib/error_tracker/web/components/layouts/navbar.ex | 2 +- lib/error_tracker/web/hooks/set_assigns.ex | 3 +-- lib/error_tracker/web/live/dashboard.html.heex | 2 +- lib/error_tracker/web/live/show.ex | 2 +- lib/error_tracker/web/live/show.html.heex | 2 +- lib/error_tracker/web/router/routes.ex | 14 ++++++++++---- 6 files changed, 15 insertions(+), 10 deletions(-) diff --git a/lib/error_tracker/web/components/layouts/navbar.ex b/lib/error_tracker/web/components/layouts/navbar.ex index d4478d5..b5ee233 100644 --- a/lib/error_tracker/web/components/layouts/navbar.ex +++ b/lib/error_tracker/web/components/layouts/navbar.ex @@ -7,7 +7,7 @@ defmodule ErrorTracker.Web.Layouts.Navbar do