diff --git a/config/config.exs b/config/config.exs index 15f93c26e..177bcc9bf 100644 --- a/config/config.exs +++ b/config/config.exs @@ -113,7 +113,7 @@ config :mobilizon, Mobilizon.Web.Email.Mailer, # Configures Elixir's Logger config :logger, :console, - backends: [:console, Sentry.LoggerBackend], + backends: [:console], format: "$time $metadata[$level] $message\n", metadata: [:request_id] diff --git a/lib/federation/activity_pub/fetcher.ex b/lib/federation/activity_pub/fetcher.ex index 019e0237e..7bac0fee3 100644 --- a/lib/federation/activity_pub/fetcher.ex +++ b/lib/federation/activity_pub/fetcher.ex @@ -9,6 +9,7 @@ defmodule Mobilizon.Federation.ActivityPub.Fetcher do alias Mobilizon.Federation.HTTPSignatures.Signature alias Mobilizon.Federation.ActivityPub.{Relay, Transmogrifier} alias Mobilizon.Federation.ActivityStream.Converter.Actor, as: ActorConverter + alias Mobilizon.Service.ErrorReporting.Sentry alias Mobilizon.Service.HTTP.ActivityPub, as: ActivityPubClient import Mobilizon.Federation.ActivityPub.Utils, diff --git a/lib/federation/activity_pub/refresher.ex b/lib/federation/activity_pub/refresher.ex index 57399a69a..7385da96e 100644 --- a/lib/federation/activity_pub/refresher.ex +++ b/lib/federation/activity_pub/refresher.ex @@ -8,6 +8,7 @@ defmodule Mobilizon.Federation.ActivityPub.Refresher do alias Mobilizon.Federation.ActivityPub alias Mobilizon.Federation.ActivityPub.Actor, as: ActivityPubActor alias Mobilizon.Federation.ActivityPub.{Fetcher, Relay, Transmogrifier, Utils} + alias Mobilizon.Service.ErrorReporting.Sentry require Logger @doc """ diff --git a/lib/federation/activity_pub/transmogrifier.ex b/lib/federation/activity_pub/transmogrifier.ex index b2430899f..172673e0c 100644 --- a/lib/federation/activity_pub/transmogrifier.ex +++ b/lib/federation/activity_pub/transmogrifier.ex @@ -21,6 +21,7 @@ defmodule Mobilizon.Federation.ActivityPub.Transmogrifier do alias Mobilizon.Federation.ActivityPub.Actor, as: ActivityPubActor alias Mobilizon.Federation.ActivityPub.Types.Ownable alias Mobilizon.Federation.ActivityStream.{Converter, Convertible} + alias Mobilizon.Service.ErrorReporting.Sentry alias Mobilizon.Service.Workers.Background alias Mobilizon.Tombstone alias Mobilizon.Web.Email.Participation diff --git a/lib/federation/http_signatures/signature.ex b/lib/federation/http_signatures/signature.ex index ff703a3ed..e68251d3b 100644 --- a/lib/federation/http_signatures/signature.ex +++ b/lib/federation/http_signatures/signature.ex @@ -13,6 +13,7 @@ defmodule Mobilizon.Federation.HTTPSignatures.Signature do alias Mobilizon.Actors.Actor alias Mobilizon.Federation.ActivityPub.Actor, as: ActivityPubActor + alias Mobilizon.Service.ErrorReporting.Sentry require Logger diff --git a/lib/mobilizon.ex b/lib/mobilizon.ex index c754964ac..9734d802b 100644 --- a/lib/mobilizon.ex +++ b/lib/mobilizon.ex @@ -16,7 +16,7 @@ defmodule Mobilizon do alias Mobilizon.{Config, Storage, Web} alias Mobilizon.Federation.ActivityPub - alias Mobilizon.Service.{ErrorPage, ErrorReporter} + alias Mobilizon.Service.{ErrorPage, ErrorReporting} alias Mobilizon.Service.Export.{Feed, ICalendar} @name Mix.Project.config()[:name] @@ -66,13 +66,14 @@ defmodule Mobilizon do ] ++ task_children(@env) - Logger.add_backend(Sentry.LoggerBackend) + ErrorReporting.configure() + :ok = Oban.Telemetry.attach_default_logger() :telemetry.attach_many( "oban-errors", [[:oban, :job, :exception], [:oban, :circuit, :trip]], - &ErrorReporter.handle_event/4, + &ErrorReporting.handle_event/4, %{} ) diff --git a/lib/mobilizon/actors/actors.ex b/lib/mobilizon/actors/actors.ex index a86e25b58..5b1466f45 100644 --- a/lib/mobilizon/actors/actors.ex +++ b/lib/mobilizon/actors/actors.ex @@ -16,6 +16,7 @@ defmodule Mobilizon.Actors do alias Mobilizon.Events.FeedToken alias Mobilizon.Federation.ActivityPub alias Mobilizon.Medias.File + alias Mobilizon.Service.ErrorReporting.Sentry alias Mobilizon.Service.Workers alias Mobilizon.Storage.{Page, Repo} alias Mobilizon.Users diff --git a/lib/service/error_reporter.ex b/lib/service/error_reporter.ex deleted file mode 100644 index 46900d945..000000000 --- a/lib/service/error_reporter.ex +++ /dev/null @@ -1,17 +0,0 @@ -defmodule Mobilizon.Service.ErrorReporter do - @moduledoc """ - Module to delegate all exceptions to Sentry - """ - def handle_event([:oban, :job, :exception], measure, %{job: job} = meta, _) do - extra = - job - |> Map.take([:id, :args, :meta, :queue, :worker]) - |> Map.merge(measure) - - Sentry.capture_exception(meta.error, stacktrace: meta.stacktrace, extra: extra) - end - - def handle_event([:oban, :circuit, :trip], _measure, meta, _) do - Sentry.capture_exception(meta.error, stacktrace: meta.stacktrace, extra: meta) - end -end diff --git a/lib/service/error_reporting/error_reporting.ex b/lib/service/error_reporting/error_reporting.ex new file mode 100644 index 000000000..6f9dd53db --- /dev/null +++ b/lib/service/error_reporting/error_reporting.ex @@ -0,0 +1,35 @@ +defmodule Mobilizon.Service.ErrorReporting do + @moduledoc """ + Mpdule to load and configure error reporting adapters + """ + + @callback enabled? :: boolean() + + @callback configure :: any() + + @callback handle_event(list(atom()), map(), map(), any()) :: any() + + @spec adapter :: module() | nil + def adapter do + adapter = Mobilizon.Config.get([__MODULE__, :adapter]) + if adapter && adapter.enabled?(), do: adapter, else: nil + end + + @spec handle_event(list(atom()), map(), map(), any()) :: any() + def handle_event(event_name, event_measurements, event_metadata, handler_config) do + adapter = adapter() + + if adapter do + adapter.handle_event(event_name, event_measurements, event_metadata, handler_config) + end + end + + @spec configure :: any() + def configure do + adapter = adapter() + + if adapter do + adapter.configure() + end + end +end diff --git a/lib/service/error_reporting/sentry.ex b/lib/service/error_reporting/sentry.ex new file mode 100644 index 000000000..d5aff6c5d --- /dev/null +++ b/lib/service/error_reporting/sentry.ex @@ -0,0 +1,45 @@ +defmodule Mobilizon.Service.ErrorReporting.Sentry do + @moduledoc """ + Sentry adapter for error reporting + """ + + alias Mobilizon.Service.ErrorReporting + @behaviour ErrorReporting + + @impl ErrorReporting + def enabled? do + !is_nil(Application.get_env(:sentry, :dsn)) + end + + @impl ErrorReporting + def configure do + Logger.add_backend(Sentry.LoggerBackend) + end + + def capture_message(message, opts \\ []) when is_binary(message) do + if enabled?() do + Sentry.capture_message(message, opts) + end + end + + def capture_exception(exception, opts \\ []) do + if enabled?() do + Sentry.capture_exception(exception, opts) + end + end + + @impl ErrorReporting + def handle_event([:oban, :job, :exception], measure, %{job: job} = meta, _) do + extra = + job + |> Map.take([:id, :args, :meta, :queue, :worker]) + |> Map.merge(measure) + + Sentry.capture_exception(meta.error, stacktrace: meta.stacktrace, extra: extra) + end + + @impl ErrorReporting + def handle_event([:oban, :circuit, :trip], _measure, meta, _) do + Sentry.capture_exception(meta.error, stacktrace: meta.stacktrace, extra: meta) + end +end diff --git a/lib/web/auth/context.ex b/lib/web/auth/context.ex index aaa16e25a..468a0d692 100644 --- a/lib/web/auth/context.ex +++ b/lib/web/auth/context.ex @@ -6,6 +6,7 @@ defmodule Mobilizon.Web.Auth.Context do import Plug.Conn + alias Mobilizon.Service.ErrorReporting.Sentry, as: SentryAdapter alias Mobilizon.Users.User def init(opts) do @@ -24,7 +25,10 @@ defmodule Mobilizon.Web.Auth.Context do context = case Guardian.Plug.current_resource(conn) do %User{id: user_id, email: user_email} = user -> - Sentry.Context.set_user_context(%{id: user_id, name: user_email}) + if SentryAdapter.enabled?() do + Sentry.Context.set_user_context(%{id: user_id, name: user_email}) + end + Map.put(context, :current_user, user) nil -> diff --git a/lib/web/email/mailer.ex b/lib/web/email/mailer.ex index 4996f7696..6f4693746 100644 --- a/lib/web/email/mailer.ex +++ b/lib/web/email/mailer.ex @@ -3,6 +3,7 @@ defmodule Mobilizon.Web.Email.Mailer do Mobilizon Mailer. """ use Bamboo.Mailer, otp_app: :mobilizon + alias Mobilizon.Service.ErrorReporting.Sentry def send_email_later(email) do Mobilizon.Web.Email.Mailer.deliver_later!(email) diff --git a/lib/web/endpoint.ex b/lib/web/endpoint.ex index 5d062f6a5..286ab9778 100644 --- a/lib/web/endpoint.ex +++ b/lib/web/endpoint.ex @@ -2,7 +2,10 @@ defmodule Mobilizon.Web.Endpoint do @moduledoc """ Endpoint for Mobilizon app """ - if Application.fetch_env!(:mobilizon, :env) !== :test do + alias Mobilizon.Service.ErrorReporting.Sentry, as: SentryAdapter + + if Application.fetch_env!(:mobilizon, :env) !== :test && + SentryAdapter.enabled?() do use Sentry.PlugCapture end @@ -92,7 +95,8 @@ defmodule Mobilizon.Web.Endpoint do String.replace_leading(url(), "http", "ws") end - if Application.fetch_env!(:mobilizon, :env) !== :test do + if Application.fetch_env!(:mobilizon, :env) !== :test && + SentryAdapter.enabled?() do plug(Sentry.PlugContext) end end