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

Ignore Errors #79

Merged
merged 5 commits into from
Sep 8, 2024
Merged
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
11 changes: 9 additions & 2 deletions guides/Getting Started.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,9 +136,9 @@ This is completely optional, and you can find more information about it in the `

## Notifications

We currently do not support notifications out of the box.
Currently ErrorTracker does not support notifications out of the box.

However, we provideo some detailed Telemetry events that you may use to implement your own notifications following your custom rules and notification channels.
However, it provides some detailed Telemetry events that you may use to implement your own notifications following your custom rules and notification channels.

If you want to take a look at the events you can attach to, take a look at `ErrorTracker.Telemetry` module documentation.

Expand All @@ -149,3 +149,10 @@ environments where you may want to prune old errors that have been resolved.

The `ErrorTracker.Plugins.Pruner` module provides automatic pruning functionality with a configurable
interval and error age.

## Ignoring errors

ErrorTracker tracks every error by default. In certain cases some errors may be expected or just not interesting to track.
ErrorTracker provides functionality that allows you to ignore errors based on their attributes and context.

Take a look at the `ErrorTracker.Ignorer` behaviour for more information about how to implement your own ignorer.
9 changes: 7 additions & 2 deletions lib/error_tracker.ex
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,9 @@ defmodule ErrorTracker do
{kind, reason} = normalize_exception(exception, stacktrace)
{:ok, stacktrace} = ErrorTracker.Stacktrace.new(stacktrace)
{:ok, error} = Error.new(kind, reason, stacktrace)

context = Map.merge(get_context(), given_context)

if enabled?() do
if enabled?() && !ignored?(error, context) do
{_error, occurrence} = upsert_error!(error, stacktrace, context, reason)
occurrence
else
Expand Down Expand Up @@ -195,6 +194,12 @@ defmodule ErrorTracker do
!!Application.get_env(:error_tracker, :enabled, true)
end

defp ignored?(error, context) do
ignorer = Application.get_env(:error_tracker, :ignorer)

ignorer && ignorer.ignore?(error, context)
end

defp normalize_exception(%struct{} = ex, _stacktrace) when is_exception(ex) do
{to_string(struct), Exception.message(ex)}
end
Expand Down
39 changes: 39 additions & 0 deletions lib/error_tracker/ignorer.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
defmodule ErrorTracker.Ignorer do
@moduledoc """
Behaviour for ignoring errors.
The ErrorTracker tracks every error that happens in your application. In certain cases you may
want to ignore some errors and don't track them. To do so you can implement this behaviour.
defmodule MyApp.ErrorIgnorer do
@behaviour ErrorTracker.Ignorer
@impl true
def ignore?(error = %ErrorTracker.Error{}, context) do
# return true if the error should be ignored
end
end
Once implemented, include it in the ErrorTracker configuration:
config :error_tracker, ignorer: MyApp.ErrorIgnorer
With this configuration in place, the ErrorTracker will call `MyApp.ErrorIgnorer.ignore?/2` before
tracking errors. If the function returns `true` the error will be ignored and won't be tracked.
> #### A note on performance {: .warning}
>
> Keep in mind that the `ignore?/2` will be called in the context of the ErrorTracker itself.
> Slow code will have a significant impact in the ErrorTracker performance. Buggy code can bring
> the ErrorTracker process down.
"""

@doc """
Decide wether the given error should be ignored or not.
This function receives both the current Error and context and should return a boolean indicating
if it should be ignored or not. If the function returns true the error will be ignored, otherwise
it will be tracked.
"""
@callback ignore?(error :: ErrorTracker.Error.t(), context :: map()) :: boolean
end
35 changes: 35 additions & 0 deletions test/error_tracker/ignorer_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
defmodule ErrorTracker.IgnorerTest do
use ErrorTracker.Test.Case

setup context do
if ignorer = context[:ignorer] do
previous_setting = Application.get_env(:error_tracker, :ignorer)
Application.put_env(:error_tracker, :ignorer, ignorer)
# Ensure that the application env is restored after each test
on_exit(fn -> Application.put_env(:error_tracker, :ignorer, previous_setting) end)
end

[]
end

@tag ignorer: ErrorTracker.EveryErrorIgnorer
test "with an ignorer ignores errors" do
assert :noop = report_error(fn -> raise "[IGNORE] Sample error" end)
assert %ErrorTracker.Occurrence{} = report_error(fn -> raise "Sample error" end)
end

@tag ignorer: false
test "without an ignorer does not ignore errors" do
assert %ErrorTracker.Occurrence{} = report_error(fn -> raise "[IGNORE] Sample error" end)
assert %ErrorTracker.Occurrence{} = report_error(fn -> raise "Sample error" end)
end
end

defmodule ErrorTracker.EveryErrorIgnorer do
@behaviour ErrorTracker.Ignorer

@impl true
def ignore?(error, _context) do
String.contains?(error.reason, "[IGNORE]")
end
end