Skip to content

Commit

Permalink
handles uncaught throw's
Browse files Browse the repository at this point in the history
  • Loading branch information
grzuy committed Jun 4, 2024
1 parent 7b3828d commit 623c295
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 11 deletions.
11 changes: 10 additions & 1 deletion lib/tower.ex
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,22 @@ defmodule Tower do
:ok = Tower.LoggerHandler.detach()
end

def report_exception(exception, stacktrace, meta \\ %{}) do
def report_exception(exception, stacktrace, meta \\ %{})
when is_exception(exception) and is_list(stacktrace) do
reporters()
|> Enum.each(fn reporter ->
reporter.report_exception(exception, stacktrace, meta)
end)
end

def report(type, reason, stacktrace, meta \\ %{})
when is_atom(type) and is_binary(reason) and is_list(stacktrace) do
reporters()
|> Enum.each(fn reporter ->
reporter.report(type, reason, stacktrace, meta)
end)
end

def reporters do
[
Tower.EphemeralReporter
Expand Down
26 changes: 22 additions & 4 deletions lib/tower/ephemeral_reporter.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,34 @@ defmodule Tower.EphemeralReporter do
when is_exception(exception) and is_list(stacktrace) do
Agent.update(
__MODULE__,
fn exceptions ->
fn errors ->
[
%{timestamp: DateTime.utc_now(), exception: exception, stacktrace: stacktrace}
| exceptions
%{
timestamp: DateTime.utc_now(),
type: exception.__struct__,
reason: Exception.message(exception),
stacktrace: stacktrace
}
| errors
]
end
)
end

def exceptions do
def report(type, reason, stacktrace, _meta \\ %{})
when is_atom(type) and is_binary(reason) and is_list(stacktrace) do
Agent.update(
__MODULE__,
fn errors ->
[
%{timestamp: DateTime.utc_now(), type: type, reason: reason, stacktrace: stacktrace}
| errors
]
end
)
end

def errors do
Agent.get(__MODULE__, & &1)
end
end
8 changes: 7 additions & 1 deletion lib/tower/logger_handler.ex
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,19 @@ defmodule Tower.LoggerHandler do
:ok
end

def log(%{level: _level, meta: %{crash_reason: {exception, stacktrace}} = meta}, _config)
def log(%{level: :error, meta: %{crash_reason: {exception, stacktrace}} = meta}, _config)
when is_exception(exception) and is_list(stacktrace) do
IO.puts("[Tower.LoggerHandler] EXCEPTION #{inspect(exception)}")

Tower.report_exception(exception, stacktrace, meta)
end

def log(%{level: :error, meta: %{crash_reason: {{:nocatch, reason}, stacktrace}} = meta}, _config) when is_list(stacktrace) do
IO.puts("[Tower.LoggerHandler] NOCATCH #{inspect(reason)}")

Tower.report(:nocatch, reason, stacktrace, meta)
end

def log(log_event, _config) do
IO.puts(
"[Tower.LoggerHandler] UNHANDLED LOG EVENT log_event=#{inspect(log_event, pretty: true)}"
Expand Down
32 changes: 27 additions & 5 deletions test/tower_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ defmodule TowerTest do
test "starts with 0 exceptions" do
Tower.EphemeralReporter.start_link([])

assert Tower.EphemeralReporter.exceptions() |> length() == 0
assert [] = Tower.EphemeralReporter.errors()
end

test "reports a raise" do
Expand All @@ -26,10 +26,31 @@ defmodule TowerTest do
assert(
[
%{
exception: %RuntimeError{message: "error inside process"},
type: RuntimeError,
reason: "error inside process",
stacktrace: stacktrace
}
] = Tower.EphemeralReporter.exceptions()
] = Tower.EphemeralReporter.errors()
)

assert is_list(stacktrace)
end

test "reports a throw" do
Tower.EphemeralReporter.start_link([])

in_unlinked_process(fn ->
throw "error"
end)

assert(
[
%{
type: :nocatch,
reason: "error",
stacktrace: stacktrace
}
] = Tower.EphemeralReporter.errors()
)

assert is_list(stacktrace)
Expand All @@ -45,10 +66,11 @@ defmodule TowerTest do
assert(
[
%{
exception: %ArithmeticError{message: "bad argument in arithmetic expression"},
type: ArithmeticError,
reason: "bad argument in arithmetic expression",
stacktrace: stacktrace
}
] = Tower.EphemeralReporter.exceptions()
] = Tower.EphemeralReporter.errors()
)

assert is_list(stacktrace)
Expand Down

0 comments on commit 623c295

Please sign in to comment.