Skip to content

Commit 48e6b63

Browse files
authored
Ignore Errors (#79)
This pull request adds the new `ErrorTracker.Ignorer` behaviour that can be used by clients to ignore errors based on their attributes and context. I've added a test to verify that it works as expected and also updated the docs and getting started guide.
1 parent cdf8cde commit 48e6b63

File tree

4 files changed

+90
-4
lines changed

4 files changed

+90
-4
lines changed

guides/Getting Started.md

+9-2
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,9 @@ This is completely optional, and you can find more information about it in the `
136136

137137
## Notifications
138138

139-
We currently do not support notifications out of the box.
139+
Currently ErrorTracker does not support notifications out of the box.
140140

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

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

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

150150
The `ErrorTracker.Plugins.Pruner` module provides automatic pruning functionality with a configurable
151151
interval and error age.
152+
153+
## Ignoring errors
154+
155+
ErrorTracker tracks every error by default. In certain cases some errors may be expected or just not interesting to track.
156+
ErrorTracker provides functionality that allows you to ignore errors based on their attributes and context.
157+
158+
Take a look at the `ErrorTracker.Ignorer` behaviour for more information about how to implement your own ignorer.

lib/error_tracker.ex

+7-2
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,9 @@ defmodule ErrorTracker do
111111
{kind, reason} = normalize_exception(exception, stacktrace)
112112
{:ok, stacktrace} = ErrorTracker.Stacktrace.new(stacktrace)
113113
{:ok, error} = Error.new(kind, reason, stacktrace)
114-
115114
context = Map.merge(get_context(), given_context)
116115

117-
if enabled?() do
116+
if enabled?() && !ignored?(error, context) do
118117
{_error, occurrence} = upsert_error!(error, stacktrace, context, reason)
119118
occurrence
120119
else
@@ -195,6 +194,12 @@ defmodule ErrorTracker do
195194
!!Application.get_env(:error_tracker, :enabled, true)
196195
end
197196

197+
defp ignored?(error, context) do
198+
ignorer = Application.get_env(:error_tracker, :ignorer)
199+
200+
ignorer && ignorer.ignore?(error, context)
201+
end
202+
198203
defp normalize_exception(%struct{} = ex, _stacktrace) when is_exception(ex) do
199204
{to_string(struct), Exception.message(ex)}
200205
end

lib/error_tracker/ignorer.ex

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
defmodule ErrorTracker.Ignorer do
2+
@moduledoc """
3+
Behaviour for ignoring errors.
4+
5+
The ErrorTracker tracks every error that happens in your application. In certain cases you may
6+
want to ignore some errors and don't track them. To do so you can implement this behaviour.
7+
8+
defmodule MyApp.ErrorIgnorer do
9+
@behaviour ErrorTracker.Ignorer
10+
11+
@impl true
12+
def ignore?(error = %ErrorTracker.Error{}, context) do
13+
# return true if the error should be ignored
14+
end
15+
end
16+
17+
Once implemented, include it in the ErrorTracker configuration:
18+
19+
config :error_tracker, ignorer: MyApp.ErrorIgnorer
20+
21+
With this configuration in place, the ErrorTracker will call `MyApp.ErrorIgnorer.ignore?/2` before
22+
tracking errors. If the function returns `true` the error will be ignored and won't be tracked.
23+
24+
> #### A note on performance {: .warning}
25+
>
26+
> Keep in mind that the `ignore?/2` will be called in the context of the ErrorTracker itself.
27+
> Slow code will have a significant impact in the ErrorTracker performance. Buggy code can bring
28+
> the ErrorTracker process down.
29+
"""
30+
31+
@doc """
32+
Decide wether the given error should be ignored or not.
33+
34+
This function receives both the current Error and context and should return a boolean indicating
35+
if it should be ignored or not. If the function returns true the error will be ignored, otherwise
36+
it will be tracked.
37+
"""
38+
@callback ignore?(error :: ErrorTracker.Error.t(), context :: map()) :: boolean
39+
end

test/error_tracker/ignorer_test.exs

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
defmodule ErrorTracker.IgnorerTest do
2+
use ErrorTracker.Test.Case
3+
4+
setup context do
5+
if ignorer = context[:ignorer] do
6+
previous_setting = Application.get_env(:error_tracker, :ignorer)
7+
Application.put_env(:error_tracker, :ignorer, ignorer)
8+
# Ensure that the application env is restored after each test
9+
on_exit(fn -> Application.put_env(:error_tracker, :ignorer, previous_setting) end)
10+
end
11+
12+
[]
13+
end
14+
15+
@tag ignorer: ErrorTracker.EveryErrorIgnorer
16+
test "with an ignorer ignores errors" do
17+
assert :noop = report_error(fn -> raise "[IGNORE] Sample error" end)
18+
assert %ErrorTracker.Occurrence{} = report_error(fn -> raise "Sample error" end)
19+
end
20+
21+
@tag ignorer: false
22+
test "without an ignorer does not ignore errors" do
23+
assert %ErrorTracker.Occurrence{} = report_error(fn -> raise "[IGNORE] Sample error" end)
24+
assert %ErrorTracker.Occurrence{} = report_error(fn -> raise "Sample error" end)
25+
end
26+
end
27+
28+
defmodule ErrorTracker.EveryErrorIgnorer do
29+
@behaviour ErrorTracker.Ignorer
30+
31+
@impl true
32+
def ignore?(error, _context) do
33+
String.contains?(error.reason, "[IGNORE]")
34+
end
35+
end

0 commit comments

Comments
 (0)