Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Chore] Pass around boom module as settings #100

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 23 additions & 16 deletions lib/boom_notifier.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down
47 changes: 25 additions & 22 deletions lib/boom_notifier/notification_sender.ex
Original file line number Diff line number Diff line change
Expand Up @@ -14,33 +14,19 @@ defmodule BoomNotifier.NotificationSender do
GenServer.start_link(__MODULE__, :ok, name: __MODULE__)
end

def async_notify(notifier, occurrences, options) do
GenServer.cast(__MODULE__, {:notify, notifier, occurrences, options})
end

def async_trigger_notify(settings, error_info) do
GenServer.cast(__MODULE__, {:trigger_notify, settings, error_info})
end

def notify(notifier, occurrences, options) do
spawn_link(fn ->
notifier.notify(occurrences, options)
end)
end

def notify_all(settings, error_info) do
notification_trigger = Keyword.get(settings, :notification_trigger, :always)
occurrences = Map.put(error_info, :occurrences, ErrorStorage.get_error_stats(error_info))

ErrorStorage.reset_accumulated_errors(notification_trigger, error_info)

BoomNotifier.walkthrough_notifiers(
settings,
fn notifier, options -> notify(notifier, occurrences, options) end
)
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)
Expand All @@ -57,6 +43,24 @@ defmodule BoomNotifier.NotificationSender do
end
end

defp notify_all(settings, error_info) do
notification_trigger = Keyword.get(settings, :notification_trigger, :always)
occurrences = Map.put(error_info, :occurrences, ErrorStorage.get_error_stats(error_info))

ErrorStorage.reset_accumulated_errors(notification_trigger, error_info)

BoomNotifier.walkthrough_notifiers(
settings,
fn notifier, options -> notify(notifier, occurrences, options) end
)
end

defp notify(notifier, occurrences, options) do
spawn_link(fn ->
notifier.notify(occurrences, options)
end)
end

# Server callbacks

@impl true
Expand All @@ -72,7 +76,6 @@ defmodule BoomNotifier.NotificationSender do
{:noreply, state}
end

@impl true
def handle_cast({:trigger_notify, settings, error_info}, state) do
{timer, state} = Map.pop(state, error_info.key)

Expand Down
32 changes: 32 additions & 0 deletions test/unit/boom_notifier_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
defmodule BoomNotifier.BoomNotifierTest do
use BoomNotifier.Case

@receive_timeout 100

Check warning on line 4 in test/unit/boom_notifier_test.exs

View workflow job for this annotation

GitHub Actions / Build and test (1.11, 21)

module attribute @receive_timeout was set but never used

Check warning on line 4 in test/unit/boom_notifier_test.exs

View workflow job for this annotation

GitHub Actions / Build and test (1.10, 22)

module attribute @receive_timeout was set but never used

Check warning on line 4 in test/unit/boom_notifier_test.exs

View workflow job for this annotation

GitHub Actions / Build and test (1.12, 22)

module attribute @receive_timeout was set but never used

Check warning on line 4 in test/unit/boom_notifier_test.exs

View workflow job for this annotation

GitHub Actions / Build and test (1.10, 21)

module attribute @receive_timeout was set but never used

Check warning on line 4 in test/unit/boom_notifier_test.exs

View workflow job for this annotation

GitHub Actions / Build and test (1.12, 24)

module attribute @receive_timeout was set but never used

Check warning on line 4 in test/unit/boom_notifier_test.exs

View workflow job for this annotation

GitHub Actions / Build and test (1.11, 22)

module attribute @receive_timeout was set but never used

Check warning on line 4 in test/unit/boom_notifier_test.exs

View workflow job for this annotation

GitHub Actions / Build and test (1.11, 24)

module attribute @receive_timeout was set but never used

Check warning on line 4 in test/unit/boom_notifier_test.exs

View workflow job for this annotation

GitHub Actions / Build and test (1.12, 24)

module attribute @receive_timeout was set but never used

Check warning on line 4 in test/unit/boom_notifier_test.exs

View workflow job for this annotation

GitHub Actions / Build and test (1.10, 23)

module attribute @receive_timeout was set but never used

Check warning on line 4 in test/unit/boom_notifier_test.exs

View workflow job for this annotation

GitHub Actions / Build and test (1.12, 23)

module attribute @receive_timeout was set but never used

Check warning on line 4 in test/unit/boom_notifier_test.exs

View workflow job for this annotation

GitHub Actions / Build and test (1.11, 23)

module attribute @receive_timeout was set but never used

Check warning on line 4 in test/unit/boom_notifier_test.exs

View workflow job for this annotation

GitHub Actions / Build and test (1.13, 24)

module attribute @receive_timeout was set but never used

Check warning on line 4 in test/unit/boom_notifier_test.exs

View workflow job for this annotation

GitHub Actions / Build and test (1.14, 25)

module attribute @receive_timeout was set but never used

Check warning on line 4 in test/unit/boom_notifier_test.exs

View workflow job for this annotation

GitHub Actions / Build and test (1.13, 22)

module attribute @receive_timeout was set but never used

Check warning on line 4 in test/unit/boom_notifier_test.exs

View workflow job for this annotation

GitHub Actions / Build and test (1.14, 24)

module attribute @receive_timeout was set but never used

Check warning on line 4 in test/unit/boom_notifier_test.exs

View workflow job for this annotation

GitHub Actions / Build and test (1.14, 23)

module attribute @receive_timeout was set but never used

Check warning on line 4 in test/unit/boom_notifier_test.exs

View workflow job for this annotation

GitHub Actions / Build and test (1.13, 23)

module attribute @receive_timeout was set but never used

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
20 changes: 1 addition & 19 deletions test/unit/notifier_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -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, "/")

Expand All @@ -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
Expand Down
Loading