-
Notifications
You must be signed in to change notification settings - Fork 13
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
[Fix] ErrorStorage agent calls #98
Changes from 4 commits
f6bc748
f06f043
604c4a4
e495273
cc11118
e13cb17
69676e9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -37,19 +37,14 @@ defmodule BoomNotifier.ErrorStorage do | |
%{key: error_hash_key} = error_info | ||
timestamp = error_info.timestamp || DateTime.utc_now() | ||
|
||
default_error_storage_info = %__MODULE__{ | ||
accumulated_occurrences: 1, | ||
first_occurrence: timestamp, | ||
last_occurrence: timestamp, | ||
__max_storage_capacity__: 1 | ||
} | ||
|
||
Agent.update( | ||
:boom_notifier, | ||
&Map.update( | ||
&1, | ||
error_hash_key, | ||
default_error_storage_info, | ||
timestamp | ||
|> default_error_storage() | ||
|> Map.put(:accumulated_occurrences, 1), | ||
fn error_storage_item -> | ||
error_storage_item | ||
|> Map.update!(:accumulated_occurrences, fn current -> current + 1 end) | ||
|
@@ -65,12 +60,11 @@ defmodule BoomNotifier.ErrorStorage do | |
@doc """ | ||
Given an error info, it returns the aggregated info stored in the agent. | ||
""" | ||
@spec get_error_stats(ErrorInfo.t()) :: %__MODULE__{} | ||
@spec get_error_stats(ErrorInfo.t()) :: __MODULE__.t() | nil | ||
def get_error_stats(error_info) do | ||
%{key: error_hash_key} = error_info | ||
|
||
Agent.get(:boom_notifier, fn state -> state end) | ||
|> Map.get(error_hash_key) | ||
Agent.get(:boom_notifier, &Map.get(&1, error_hash_key)) | ||
end | ||
|
||
@doc """ | ||
|
@@ -81,53 +75,59 @@ defmodule BoomNotifier.ErrorStorage do | |
""" | ||
@spec send_notification?(ErrorInfo.t()) :: boolean() | ||
def send_notification?(error_info) do | ||
%{key: error_hash_key} = error_info | ||
|
||
error_storage_item = | ||
Agent.get(:boom_notifier, fn state -> state end) | ||
|> Map.get(error_hash_key) | ||
|
||
do_send_notification?(error_storage_item) | ||
error_info | ||
|> get_error_stats() | ||
|> do_send_notification?() | ||
end | ||
|
||
@doc """ | ||
Reset the accumulated_occurrences for the given error info to zero. It also | ||
increments the max storage capacity based on the notification strategy. | ||
|
||
Returns error storage entry before reset | ||
""" | ||
@spec reset_accumulated_errors(error_strategy, ErrorInfo.t()) :: :ok | ||
def reset_accumulated_errors(:exponential, error_info) do | ||
%{key: error_hash_key} = error_info | ||
@spec reset(ErrorInfo.t()) :: __MODULE__.t() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Loved the rename of this function 😍 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What about something like I'm thinking about the occurrences = ErrorStorage.reset_stats(error_info, notification_trigger) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. makes sense to be consistent with other ErrorStorage's functions |
||
@spec reset(ErrorInfo.t(), count_strategy :: :exponential | :always | nil) :: __MODULE__.t() | ||
def reset(error_info), do: reset(error_info, nil) | ||
|
||
Agent.update( | ||
:boom_notifier, | ||
&Map.update!(&1, error_hash_key, fn error_storage_item -> | ||
clear_values(error_storage_item) | ||
|> Map.update!(:__max_storage_capacity__, fn current -> current * 2 end) | ||
end) | ||
) | ||
def reset(error_info, :exponential) do | ||
reset_state(error_info, fn value -> value * 2 end) | ||
end | ||
|
||
def reset_accumulated_errors([exponential: [limit: limit]], error_info) do | ||
%{key: error_hash_key} = error_info | ||
def reset(error_info, exponential: [limit: limit]) do | ||
reset_state(error_info, fn value -> min(value * 2, limit) end) | ||
end | ||
|
||
Agent.update( | ||
:boom_notifier, | ||
&Map.update!(&1, error_hash_key, fn error_storage_item -> | ||
clear_values(error_storage_item) | ||
|> Map.update!(:__max_storage_capacity__, fn current -> min(current * 2, limit) end) | ||
end) | ||
) | ||
def reset(error_info, strategy) when strategy in [:always, nil] do | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe we can remove this guard so it always fallbacks here if the strategy doesn't need to update the |
||
reset_state(error_info, nil) | ||
end | ||
|
||
def reset_accumulated_errors(:always, error_info) do | ||
defp reset_state(error_info, nil) do | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. NIT: |
||
reset_state(error_info, fn _ -> 1 end) | ||
end | ||
|
||
defp reset_state(error_info, limit_updater_function) do | ||
%{key: error_hash_key} = error_info | ||
|
||
Agent.update( | ||
Agent.get_and_update( | ||
:boom_notifier, | ||
&Map.update!(&1, error_hash_key, fn error_storage_item -> | ||
clear_values(error_storage_item) | ||
|> Map.replace!(:__max_storage_capacity__, 1) | ||
end) | ||
fn state -> | ||
error_storage_item = Map.get(state, error_hash_key) | ||
|
||
state = | ||
Map.update( | ||
state, | ||
error_hash_key, | ||
default_error_storage(), | ||
fn error_storage_item -> | ||
error_storage_item | ||
|> clear_values() | ||
|> Map.update!(:__max_storage_capacity__, limit_updater_function) | ||
end | ||
) | ||
|
||
{error_storage_item, state} | ||
end | ||
) | ||
end | ||
|
||
|
@@ -138,7 +138,7 @@ defmodule BoomNotifier.ErrorStorage do | |
|> Map.replace!(:last_occurrence, nil) | ||
end | ||
|
||
@spec do_send_notification?(ErrorInfo.t() | nil) :: boolean() | ||
@spec do_send_notification?(nil | __MODULE__.t()) :: boolean() | ||
defp do_send_notification?(nil), do: false | ||
|
||
defp do_send_notification?(error_storage_item) do | ||
|
@@ -147,4 +147,13 @@ defmodule BoomNotifier.ErrorStorage do | |
|
||
accumulated_occurrences >= max_storage_capacity | ||
end | ||
|
||
defp default_error_storage(timestamp \\ nil) do | ||
%__MODULE__{ | ||
accumulated_occurrences: 0, | ||
first_occurrence: timestamp, | ||
last_occurrence: timestamp, | ||
__max_storage_capacity__: 1 | ||
} | ||
end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we can move this to the top (in line
39
) so it's more clear this is the initial value for the Agent.Something like
Or instead of calling that function
default_error_storage
rename it tobuild_error_storage
and have something like thisThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good idea!