diff --git a/lib/error_tracker.ex b/lib/error_tracker.ex index f05a51b..327ce86 100644 --- a/lib/error_tracker.ex +++ b/lib/error_tracker.ex @@ -94,26 +94,11 @@ defmodule ErrorTracker do * An exception struct: the module of the exception is stored along with the exception message. - * A `{kind, exception}` tuple in which the `exception` is a struct: it - behaves the same as when passing just the exception struct. - - * A `{kind, reason}` tuple: it stores the kind and the message itself cast - to strings, which is useful for some errors like EXIT signals or custom error - messages. + * A `{kind, exception}` tuple in which case the information is converted to + an Elixir exception (if possible) and stored. """ def report(exception, stacktrace, given_context \\ %{}) do - {kind, reason} = - case exception do - %struct{} = ex when is_exception(ex) -> - {to_string(struct), Exception.message(ex)} - - {_kind, %struct{} = ex} when is_exception(ex) -> - {to_string(struct), Exception.message(ex)} - - {kind, ex} -> - {to_string(kind), to_string(ex)} - end - + {kind, reason} = normalize_exception(exception, stacktrace) {:ok, stacktrace} = ErrorTracker.Stacktrace.new(stacktrace) {:ok, error} = Error.new(kind, reason, stacktrace) @@ -181,4 +166,18 @@ defmodule ErrorTracker do def get_context do Process.get(:error_tracker_context, %{}) end + + defp normalize_exception(%struct{} = ex, _stacktrace) when is_exception(ex) do + {to_string(struct), Exception.message(ex)} + end + + defp normalize_exception({kind, ex}, stacktrace) do + case Exception.normalize(kind, ex, stacktrace) do + %struct{} = ex -> + {to_string(struct), Exception.message(ex)} + + other -> + {to_string(kind), to_string(other)} + end + end end diff --git a/lib/error_tracker/schemas/error.ex b/lib/error_tracker/schemas/error.ex index fb3808a..26265d4 100644 --- a/lib/error_tracker/schemas/error.ex +++ b/lib/error_tracker/schemas/error.ex @@ -29,10 +29,11 @@ defmodule ErrorTracker.Error do @doc false def new(kind, reason, stacktrace = %ErrorTracker.Stacktrace{}) do source = ErrorTracker.Stacktrace.source(stacktrace) + source_line = if source.file, do: "#{source.file}:#{source.line}", else: "nofile" params = [ kind: to_string(kind), - source_line: "#{source.file}:#{source.line}", + source_line: source_line, source_function: "#{source.module}.#{source.function}/#{source.arity}" ] diff --git a/lib/error_tracker/schemas/stacktrace.ex b/lib/error_tracker/schemas/stacktrace.ex index 14f3517..cf22f31 100644 --- a/lib/error_tracker/schemas/stacktrace.ex +++ b/lib/error_tracker/schemas/stacktrace.ex @@ -27,7 +27,7 @@ defmodule ErrorTracker.Stacktrace do application: to_string(application), module: module |> to_string() |> String.replace_prefix("Elixir.", ""), function: to_string(function), - arity: arity, + arity: normalize_arity(arity), file: to_string(opts[:file]), line: opts[:line] } @@ -39,6 +39,9 @@ defmodule ErrorTracker.Stacktrace do |> Ecto.Changeset.apply_action(:new) end + defp normalize_arity(a) when is_integer(a), do: a + defp normalize_arity(a) when is_list(a), do: length(a) + defp line_changeset(line = %__MODULE__.Line{}, params) do Ecto.Changeset.cast(line, params, ~w[application module function arity file line]a) end diff --git a/lib/error_tracker/web/live/show.html.heex b/lib/error_tracker/web/live/show.html.heex index d93d199..ebf974b 100644 --- a/lib/error_tracker/web/live/show.html.heex +++ b/lib/error_tracker/web/live/show.html.heex @@ -48,7 +48,7 @@
(<%= line.application || @app %>)
<%= "#{sanitize_module(line.module)}.#{line.function}/#{line.arity}" %>
-                <%= "#{line.file}.#{line.line}" %>
+ <%= if line.line, do: "#{line.file}:#{line.line}", else: "nofile" %>