I have a GenEvent
that has been added as a handler like so :error_logger.add_report_handler(HoloNet.ErrorLogger)
So that errors/exceptions are captured and forwarded to a exception monitoring service.
I have the following code in a event behaviour
defmodule MyApp.ErrorLogger do
use GenEvent
@bugsnag_client Application.get_env(:my_app, :bugsnag_client)
def init(_opts), do: {:ok, self}
def handle_event({:error_report, _gl, {_pid, _type, [message | _]}}, state) do
{ error, stacktrace } = extract_exception(message[:error_info])
context = extract_context(stacktrace)
@bugsnag_client.notify(error,stacktrace, context: context, release_stage: Mix.env |> to_string)
{:ok, state}
end
def handle_event({_level, _gl, _event}, state) do
{:ok, state}
end
defp extract_exception(error_info) do
{ _, exception, _ } = error_info
exception
end
defp extract_context(stacktrace) do
stacktrace |> List.first |> elem 0
end
end
The Client that makes the http request is mocked out using the application config.
defmodule Bugsnag.Mock do
@behaviour Bugsnag
def notify(error,stacktrace, options \\ []), do: nil
end
It works as it should when in production, but I wanted to have some test coverage.
I was thinking of testing this by crashing a GenServer or causing some exception then see if notify gets called. This doesn't feel very functional/Elixir, but I wanted to test that errors would be captured when an error is caused.
I say go ahead and crash things. :erlang.exit/2
will do the trick.
OTP and supervision trees are not easy. Testing how the application behaves under error conditions is necessary it you really want to achieve elixir's promised fault-tolerance.