diff --git a/config/config.exs b/config/config.exs index 7a3f5d7..a317aea 100644 --- a/config/config.exs +++ b/config/config.exs @@ -29,6 +29,12 @@ config :logger, :console, # Use Jason for JSON parsing in Phoenix config :phoenix, :json_library, Jason +config :sentry, + environment_name: Mix.env(), + enable_source_code_context: true, + root_source_code_paths: [File.cwd!()], + client: TuskerPush.SentryFinchClient + # Import environment specific config. This must remain at the bottom # of this file so it overrides the configuration defined above. import_config "#{config_env()}.exs" diff --git a/config/runtime.exs b/config/runtime.exs index b6d955a..c7809a6 100644 --- a/config/runtime.exs +++ b/config/runtime.exs @@ -81,4 +81,6 @@ if config_env() == :prod do # force_ssl: [hsts: true] # # Check `Plug.SSL` for all available options in `force_ssl`. + + config :sentry, dsn: System.fetch_env!("SENTRY_DSN") end diff --git a/lib/tusker_push/application.ex b/lib/tusker_push/application.ex index f13686c..68abd0e 100644 --- a/lib/tusker_push/application.ex +++ b/lib/tusker_push/application.ex @@ -7,6 +7,10 @@ defmodule TuskerPush.Application do @impl true def start(_type, _args) do + :logger.add_handler(:tusker_push_sentry_handler, Sentry.LoggerHandler, %{ + config: %{metadata: [:file, :line]} + }) + children = [ TuskerPushWeb.Telemetry, {DNSCluster, query: Application.get_env(:tusker_push, :dns_cluster_query) || :ignore}, diff --git a/lib/tusker_push/sentry_finch_client.ex b/lib/tusker_push/sentry_finch_client.ex new file mode 100644 index 0000000..9dfe53c --- /dev/null +++ b/lib/tusker_push/sentry_finch_client.ex @@ -0,0 +1,21 @@ +defmodule TuskerPush.SentryFinchClient do + @behaviour Sentry.HTTPClient + + @impl true + def child_spec do + Supervisor.child_spec({Finch, name: __MODULE__}, id: __MODULE__) + end + + @impl true + def post(url, headers, body) do + request = Finch.build(:post, url, headers, body) + + case Finch.request(request, __MODULE__) do + {:ok, %Finch.Response{status: status, headers: resp_headers, body: resp_body}} -> + {:ok, status, resp_headers, resp_body} + + {:error, error} -> + {:error, error} + end + end +end diff --git a/lib/tusker_push_web/endpoint.ex b/lib/tusker_push_web/endpoint.ex index 8556790..dd59921 100644 --- a/lib/tusker_push_web/endpoint.ex +++ b/lib/tusker_push_web/endpoint.ex @@ -1,4 +1,5 @@ defmodule TuskerPushWeb.Endpoint do + use Sentry.PlugCapture use Phoenix.Endpoint, otp_app: :tusker_push # The session will be stored in the cookie and signed, @@ -39,6 +40,8 @@ defmodule TuskerPushWeb.Endpoint do pass: ["*/*"], json_decoder: Phoenix.json_library() + plug Sentry.PlugContext + plug Plug.MethodOverride plug Plug.Head plug Plug.Session, @session_options diff --git a/mix.exs b/mix.exs index bf1f3f1..a946ee7 100644 --- a/mix.exs +++ b/mix.exs @@ -40,7 +40,8 @@ defmodule TuskerPush.MixProject do {:bandit, "~> 1.2"}, {:dialyxir, "~> 1.4", only: [:dev, :test], runtime: false}, {:finch, "~> 0.18"}, - {:jose, "~> 1.11"} + {:jose, "~> 1.11"}, + {:sentry, "~> 10.3.0"} ] end @@ -52,7 +53,8 @@ defmodule TuskerPush.MixProject do # See the documentation for `Mix` for more info on aliases. defp aliases do [ - setup: ["deps.get"] + setup: ["deps.get"], + release: ["sentry.package_source_code", "release"] ] end end diff --git a/mix.lock b/mix.lock index 55e3e29..ecbf52d 100644 --- a/mix.lock +++ b/mix.lock @@ -11,12 +11,14 @@ "mime": {:hex, :mime, "2.0.5", "dc34c8efd439abe6ae0343edbb8556f4d63f178594894720607772a041b04b02", [:mix], [], "hexpm", "da0d64a365c45bc9935cc5c8a7fc5e49a0e0f9932a761c55d6c52b142780a05c"}, "mint": {:hex, :mint, "1.5.2", "4805e059f96028948870d23d7783613b7e6b0e2fb4e98d720383852a760067fd", [:mix], [{:castore, "~> 0.1.0 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:hpax, "~> 0.1.1", [hex: :hpax, repo: "hexpm", optional: false]}], "hexpm", "d77d9e9ce4eb35941907f1d3df38d8f750c357865353e21d335bdcdf6d892a02"}, "nimble_options": {:hex, :nimble_options, "1.1.0", "3b31a57ede9cb1502071fade751ab0c7b8dbe75a9a4c2b5bbb0943a690b63172", [:mix], [], "hexpm", "8bbbb3941af3ca9acc7835f5655ea062111c9c27bcac53e004460dfd19008a99"}, + "nimble_ownership": {:hex, :nimble_ownership, "0.3.1", "99d5244672fafdfac89bfad3d3ab8f0d367603ce1dc4855f86a1c75008bce56f", [:mix], [], "hexpm", "4bf510adedff0449a1d6e200e43e57a814794c8b5b6439071274d248d272a549"}, "nimble_pool": {:hex, :nimble_pool, "1.1.0", "bf9c29fbdcba3564a8b800d1eeb5a3c58f36e1e11d7b7fb2e084a643f645f06b", [:mix], [], "hexpm", "af2e4e6b34197db81f7aad230c1118eac993acc0dae6bc83bac0126d4ae0813a"}, "phoenix": {:hex, :phoenix, "1.7.11", "1d88fc6b05ab0c735b250932c4e6e33bfa1c186f76dcf623d8dd52f07d6379c7", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.7", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:websock_adapter, "~> 0.5.3", [hex: :websock_adapter, repo: "hexpm", optional: false]}], "hexpm", "b1ec57f2e40316b306708fe59b92a16b9f6f4bf50ccfa41aa8c7feb79e0ec02a"}, "phoenix_pubsub": {:hex, :phoenix_pubsub, "2.1.3", "3168d78ba41835aecad272d5e8cd51aa87a7ac9eb836eabc42f6e57538e3731d", [:mix], [], "hexpm", "bba06bc1dcfd8cb086759f0edc94a8ba2bc8896d5331a1e2c2902bf8e36ee502"}, "phoenix_template": {:hex, :phoenix_template, "1.0.4", "e2092c132f3b5e5b2d49c96695342eb36d0ed514c5b252a77048d5969330d639", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "2c0c81f0e5c6753faf5cca2f229c9709919aba34fab866d3bc05060c9c444206"}, "plug": {:hex, :plug, "1.15.3", "712976f504418f6dff0a3e554c40d705a9bcf89a7ccef92fc6a5ef8f16a30a97", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "cc4365a3c010a56af402e0809208873d113e9c38c401cabd88027ef4f5c01fd2"}, "plug_crypto": {:hex, :plug_crypto, "2.0.0", "77515cc10af06645abbfb5e6ad7a3e9714f805ae118fa1a70205f80d2d70fe73", [:mix], [], "hexpm", "53695bae57cc4e54566d993eb01074e4d894b65a3766f1c43e2c61a1b0f45ea9"}, + "sentry": {:hex, :sentry, "10.3.0", "4b7543dfea5e59f3be6db28a032427884d55fbc828173b23115064e75dcb1eed", [:mix], [{:hackney, "~> 1.8", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:nimble_options, "~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_ownership, "~> 0.3.0", [hex: :nimble_ownership, repo: "hexpm", optional: false]}, {:plug, "~> 1.6", [hex: :plug, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "c1c08ba57f0634b7fda92adb0818ea0677e043e2d28ea4464351a0e4e8e142e5"}, "telemetry": {:hex, :telemetry, "1.2.1", "68fdfe8d8f05a8428483a97d7aab2f268aaff24b49e0f599faa091f1d4e7f61c", [:rebar3], [], "hexpm", "dad9ce9d8effc621708f99eac538ef1cbe05d6a874dd741de2e689c47feafed5"}, "telemetry_metrics": {:hex, :telemetry_metrics, "0.6.2", "2caabe9344ec17eafe5403304771c3539f3b6e2f7fb6a6f602558c825d0d0bfb", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "9b43db0dc33863930b9ef9d27137e78974756f5f198cae18409970ed6fa5b561"}, "telemetry_poller": {:hex, :telemetry_poller, "1.0.0", "db91bb424e07f2bb6e73926fcafbfcbcb295f0193e0a00e825e589a0a47e8453", [:rebar3], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "b3a24eafd66c3f42da30fc3ca7dda1e9d546c12250a2d60d7b81d264fbec4f6e"},