Repository: elixir-error-tracker/error-tracker
Pull request #82 (2024-09-08 07:55:05)

Flag to globally disable error tracking
This change adds a new global flag named `:enabled` that allows to disable the error tracking on certain environments.

This behaviour can be done also with a custom ignorer using the changes that we will introduce in #79 , but I felt like this use case will be quite common in dev environments and having a fast way to just disable every error is useful.

Test have been added and documentation updated.

It is related to #81 

odarriba: I felt like this would be useful, but some feedback will be appreciated @crbelaus as this can be done using ignorer functionality too. However, having to create a custom ignorer just for dev felt a bit too much for such a common use case.

Patch:
diff --git a/guides/Getting Started.md b/guides/Getting Started.md
index a8c462d..9bdf52e 100644
--- a/guides/Getting Started.md
+++ b/guides/Getting Started.md
@@ -32,13 +32,16 @@ ErrorTracker needs a few configuration options to work. This configuration shoul
 ```elixir
 config :error_tracker,
   repo: MyApp.Repo,
-  otp_app: :my_app
+  otp_app: :my_app,
+  enabled: true
 ```
 
 The `:repo` option specifies the repository that will be used by ErrorTracker. You can use your regular application repository or a different one if you prefer to keep errors in a different database.
 
 The `:otp_app` option specifies your application name. When an error occurs, ErrorTracker will use this information to understand which parts of the stack trace belong to your application and which parts belong to third-party dependencies. This allows you to filter in-app vs third-party frames when viewing errors.
 
+The `:enabled` option (defaults to `true` if not present) allows to disable the ErrorTracker on certain environments. This is useful to avoid filling your dev database with errors, for example.
+
 ## Setting up the database
 
 Since ErrorTracker stores errors in the database you must create a database migration to add the required tables:
diff --git a/lib/error_tracker.ex b/lib/error_tracker.ex
index 130f8c0..7477138 100644
--- a/lib/error_tracker.ex
+++ b/lib/error_tracker.ex
@@ -77,6 +77,9 @@ defmodule ErrorTracker do
   @doc """
   Report an exception to be stored.
 
+  Returns the occurrence stored or `:noop` if the ErrorTracker is disabled by
+  configuration the exception has not been stored.
+
   Aside from the exception, it is expected to receive the stack trace and,
   optionally, a context map which will be merged with the current process
   context.
@@ -111,9 +114,12 @@ defmodule ErrorTracker do
 
     context = Map.merge(get_context(), given_context)
 
-    {_error, occurrence} = upsert_error!(error, stacktrace, context, reason)
-
-    occurrence
+    if enabled?() do
+      {_error, occurrence} = upsert_error!(error, stacktrace, context, reason)
+      occurrence
+    else
+      :noop
+    end
   end
 
   @doc """
@@ -185,6 +191,10 @@ defmodule ErrorTracker do
     Process.get(:error_tracker_context, %{})
   end
 
+  defp enabled? do
+    !!Application.get_env(:error_tracker, :enabled, true)
+  end
+
   defp normalize_exception(%struct{} = ex, _stacktrace) when is_exception(ex) do
     {to_string(struct), Exception.message(ex)}
   end


Test patch:
diff --git a/test/error_tracker_test.exs b/test/error_tracker_test.exs
index 090880f..f8018b3 100644
--- a/test/error_tracker_test.exs
+++ b/test/error_tracker_test.exs
@@ -7,6 +7,16 @@ defmodule ErrorTrackerTest do
   @relative_file_path Path.relative_to(__ENV__.file, File.cwd!())
 
   describe inspect(&ErrorTracker.report/3) do
+    setup context do
+      if Map.has_key?(context, :enabled) do
+        Application.put_env(:error_tracker, :enabled, context[:enabled])
+        # Ensure that the application env is restored after each test
+        on_exit(fn -> Application.delete_env(:error_tracker, :enabled) end)
+      end
+
+      []
+    end
+
     test "reports exceptions" do
       %Occurrence{error: error = %Error{}} =
         report_error(fn -> raise "This is a test" end)
@@ -72,6 +82,23 @@ defmodule ErrorTrackerTest do
 
       assert %Occurrence{} = report_error(fn -> raise "test" end, invalid_context)
     end
+
+    test "without enabled flag it works as expected" do
+      # Ensure no value is set
+      Application.delete_env(:error_tracker, :enabled)
+
+      assert %Occurrence{} = report_error(fn -> raise "Sample error" end)
+    end
+
+    @tag enabled: true
+    test "with enabled flag to true it works as expected" do
+      assert %Occurrence{} = report_error(fn -> raise "Sample error" end)
+    end
+
+    @tag enabled: false
+    test "with enabled flag to false it does not store the exception" do
+      assert report_error(fn -> raise "Sample error" end) == :noop
+    end
   end
 
   describe inspect(&ErrorTracker.resolve/1) do
diff --git a/test/support/case.ex b/test/support/case.ex
index 2e35fa4..d23d451 100644
--- a/test/support/case.ex
+++ b/test/support/case.ex
@@ -28,7 +28,10 @@ defmodule ErrorTracker.Test.Case do
           ErrorTracker.report({kind, reason}, __STACKTRACE__, context)
       end
 
-    repo().preload(occurrence, :error)
+    case occurrence do
+      %ErrorTracker.Occurrence{} -> repo().preload(occurrence, :error)
+      other -> other
+    end
   end
 
   @doc """