diff --git a/lib/boom_notifier.ex b/lib/boom_notifier.ex index c5bdc40..2dbf215 100644 --- a/lib/boom_notifier.ex +++ b/lib/boom_notifier.ex @@ -8,8 +8,20 @@ defmodule BoomNotifier do alias BoomNotifier.ErrorInfo alias BoomNotifier.NotificationSender + @spec to_config(Keyword.t() | Atom) :: Keyword.t() + def to_config(config) when is_atom(config), + do: config.boom_config() + + def to_config(settings), + do: settings + + @doc """ + Runs BoomNotifier triggering logic according to the provided configuration which + can be specified either as a keyword list or as a module atom which uses BoomNotifier. + """ + @spec notify_error(Keyword.t(), Plug.Conn.t(), error :: any()) :: nil def notify_error(settings, conn, %{kind: :error, reason: %mod{}} = error) do - ignored_exceptions = Keyword.get(settings, :ignore_exceptions, []) + ignored_exceptions = Keyword.get(to_config(settings), :ignore_exceptions, []) unless Enum.member?(ignored_exceptions, mod) do trigger_notify_error(settings, conn, error) @@ -44,24 +56,15 @@ defmodule BoomNotifier do end defp run_callback(settings, callback) do - missing_keys = Enum.reject([:notifier, :options], &Keyword.has_key?(settings, &1)) - - case missing_keys do - [] -> - callback.(settings[:notifier], settings[:options]) - - [missing_key] -> - Logger.error("(BoomNotifier) #{inspect(missing_key)} parameter is missing") - - _ -> - Logger.error( - "(BoomNotifier) The following parameters are missing: #{inspect(missing_keys)}" - ) + if Keyword.has_key?(settings, :notifier) do + callback.(settings[:notifier], settings[:options]) + else + Logger.error("Parameter :notifier is missing in #{inspect(settings)}") end end defp trigger_notify_error(settings, conn, error) do - custom_data = Keyword.get(settings, :custom_data, :nothing) + custom_data = Keyword.get(to_config(settings), :custom_data, :nothing) error_info = ErrorInfo.build(error, conn, custom_data) NotificationSender.async_trigger_notify(settings, error_info) @@ -91,7 +94,11 @@ defmodule BoomNotifier do ) def notify_error(conn, error) do - BoomNotifier.notify_error(unquote(config), conn, error) + BoomNotifier.notify_error(__MODULE__, conn, error) + end + + def boom_config do + unquote(config) end end end diff --git a/lib/boom_notifier/notification_sender.ex b/lib/boom_notifier/notification_sender.ex index 2ac200b..7b52f5e 100644 --- a/lib/boom_notifier/notification_sender.ex +++ b/lib/boom_notifier/notification_sender.ex @@ -39,7 +39,15 @@ defmodule BoomNotifier.NotificationSender do ) end + @doc """ + Call notifiers if error_info should trigger a notification + according to settings and the acumulated errors. + + It returns :ok if notification were triggered or {:schedule, time} + if it should be delayed and by how much. + """ def trigger_notify(settings, error_info) do + settings = BoomNotifier.to_config(settings) timeout = Keyword.get(settings, :time_limit) ErrorStorage.store_error(error_info) diff --git a/test/unit/boom_notifier_test.exs b/test/unit/boom_notifier_test.exs new file mode 100644 index 0000000..d40e706 --- /dev/null +++ b/test/unit/boom_notifier_test.exs @@ -0,0 +1,30 @@ +defmodule BoomNotifier.BoomNotifierTest do + use BoomNotifier.Case + + defmodule FakeNotifier do + def notify(_, _), do: nil + end + + describe "to_config/1" do + defmodule ToConfigEndpoint do + def call(conn, _opts), do: conn + + use BoomNotifier, + notifier: FakeNotifier + end + + test "accepts a module name" do + assert BoomNotifier.to_config(ToConfigEndpoint) == ToConfigEndpoint.boom_config() + end + + test "it calls boom_notifier when a module is specified" do + assert_raise(UndefinedFunctionError, fn -> + BoomNotifier.to_config(Kernel) + end) + end + + test "accepts a keyword list" do + assert BoomNotifier.to_config(notifier: FakeNotifier) == ToConfigEndpoint.boom_config() + end + end +end diff --git a/test/unit/notifier_test.exs b/test/unit/notifier_test.exs index f857b5d..d72a8ec 100644 --- a/test/unit/notifier_test.exs +++ b/test/unit/notifier_test.exs @@ -319,24 +319,6 @@ defmodule NotifierTest do :elixir_config.put(:ignore_module_conflict, false) end - test "logs when parameters in config are missing" do - :elixir_config.put(:ignore_module_conflict, true) - - conn = conn(:get, "/") - - assert capture_log(fn -> - defmodule PlugLogWithMissingParameterNotifier do - use BoomNotifier, other: nil - - def call(_conn, _opts) do - raise TestException.exception([]) - end - end - end) =~ "(BoomNotifier) The following parameters are missing: [:notifier, :options]" - - :elixir_config.put(:ignore_module_conflict, false) - end - test "logs when one parameter in config is missing" do conn = conn(:get, "/") @@ -351,7 +333,7 @@ defmodule NotifierTest do raise TestException.exception([]) end end - end) =~ "(BoomNotifier) :notifier parameter is missing" + end) =~ "Parameter :notifier is missing" end describe "ignored exceptions" do