Skip to content
Merged
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ ADD apps apps
ADD config config
ADD mix.* /root/

RUN mix do deps.get --only prod, phx.swagger.generate, compile, phx.digest
RUN mix do deps.get --only prod, phx.swagger.generate, compile, phx.digest, sentry.package_source_code
RUN mix eval "Application.ensure_all_started(:tzdata); Tzdata.DataBuilder.load_and_save_table()"

ADD rel/ rel/
Expand Down
4 changes: 4 additions & 0 deletions apps/api_web/config/test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ config :api_web, RateLimiter.Memcache,

config :api_web, ApiWeb.Plugs.ModifiedSinceHandler, check_caller: true

config :sentry,
test_mode: true,
before_send: {ApiWeb.SentryEventFilter, :filter_event}

# Credentials that always show widget and pass backend validation:
config :recaptcha,
enabled: true,
Expand Down
21 changes: 16 additions & 5 deletions apps/api_web/lib/api_web/sentry_event_filter.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,23 @@ defmodule ApiWeb.SentryEventFilter do
@moduledoc """
Provides a filter for exceptions coming from 404 errors
"""
@behaviour Sentry.EventFilter

def exclude_exception?(%Phoenix.Router.NoRouteError{}, :plug), do: true
# Sentry allows this callback to both modify events before they get sent,
# and filter events to prevent them from being sent at all.
# We only do the latter. Returning false prevents sending.
@spec filter_event(Sentry.Event.t()) :: Sentry.Event.t() | false
def filter_event(%Sentry.Event{
source: :plug,
original_exception: %Phoenix.Router.NoRouteError{}
}) do
false
end

def exclude_exception?(%Sentry.CrashError{} = error, :logger),
do: String.contains?(error.message, "{{{%Phoenix.Router.NoRouteError")
def filter_event(%Sentry.Event{message: %Sentry.Interfaces.Message{}} = event) do
if String.contains?(event.message.formatted, "{{{%Phoenix.Router.NoRouteError"),
do: false,
else: event
end

def exclude_exception?(_exception, _source), do: false
def filter_event(event), do: event
end
2 changes: 1 addition & 1 deletion apps/api_web/mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ defmodule ApiWeb.Mixfile do
{:stream_data, "~> 1.2", only: :test},
{:sobelow, "~> 0.11", only: :dev, runtime: false},
{:recaptcha, git: "https://github.com/samueljseay/recaptcha.git", ref: "71cd746be987f6834c1a933f5d2f934350e55060"},
{:sentry, "~> 8.0"},
{:sentry, "~> 11.0"},
{:qr_code, "~> 3.0"},
{:nimble_totp, "~> 1.0"}
]
Expand Down
34 changes: 34 additions & 0 deletions apps/api_web/test/api_web/sentry_event_filter_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
defmodule ApiWeb.SentryEventFilterTest do
use ApiWeb.ConnCase, async: true

describe "filter_event/1" do
setup do
Sentry.Test.start_collecting_sentry_reports()
end

test "filters out `NoRouteError`s rescued by plugs", %{conn: conn} do
conn = get(conn, "/a_nonexistent_route")
assert response(conn, 404)

assert [] = Sentry.Test.pop_sentry_reports()
end

test "filters out `NoRouteError`s surfaced as messages via crashes" do
Sentry.capture_message("Something something {{{%Phoenix.Router.NoRouteError}}}")
assert [] = Sentry.Test.pop_sentry_reports()

Sentry.capture_message("Something something {{{%SomeOtherError}}}")
assert [%Sentry.Event{} = err] = Sentry.Test.pop_sentry_reports()
assert err.message.formatted =~ "SomeOtherError"
end

test "does not filter out other exceptions" do
err = RuntimeError.exception("An error other than NoRouteError")

Sentry.capture_exception(err)

assert [%Sentry.Event{} = event] = Sentry.Test.pop_sentry_reports()
assert ^err = event.original_exception
end
end
end
21 changes: 16 additions & 5 deletions config/runtime.exs
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,27 @@ if is_prod? and is_release? do

if not is_nil(sentry_env) do
config :sentry,
filter: ApiWeb.SentryEventFilter,
before_send: {ApiWeb.SentryEventFilter, :filter_event},
dsn: System.fetch_env!("SENTRY_DSN"),
environment_name: sentry_env,
enable_source_code_context: true,
root_source_code_path: File.cwd!(),
root_source_code_paths:
[
"api_web",
"health",
"parse",
"alb_monitor",
"state",
"fetch",
"model",
"events",
"api_accounts",
"state_mediator"
]
|> Enum.map(&Path.join([File.cwd!(), "apps", &1])),
tags: %{
env: sentry_env
},
included_environments: [sentry_env]
}

config :logger, Sentry.LoggerBackend, level: :error
end
Expand All @@ -31,7 +43,6 @@ if is_prod? and is_release? do
],
json_codec: Jason


config :alb_monitor,
ecs_metadata_uri: System.fetch_env!("ECS_CONTAINER_METADATA_URI"),
target_group_arn: System.fetch_env!("ALB_TARGET_GROUP_ARN")
Expand Down
3 changes: 2 additions & 1 deletion mix.lock
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
"mox": {:hex, :mox, "1.0.2", "dc2057289ac478b35760ba74165b4b3f402f68803dd5aecd3bfd19c183815d64", [:mix], [], "hexpm", "f9864921b3aaf763c8741b5b8e6f908f44566f1e427b2630e89e9a73b981fef2"},
"nimble_csv": {:hex, :nimble_csv, "1.3.0", "b7f998dc62b222bce9596e46f028c7a5af04cb5dde6df2ea197c583227c54971", [:mix], [], "hexpm", "41ccdc18f7c8f8bb06e84164fc51635321e80d5a3b450761c4997d620925d619"},
"nimble_options": {:hex, :nimble_options, "1.1.1", "e3a492d54d85fc3fd7c5baf411d9d2852922f66e69476317787a7b2bb000a61b", [:mix], [], "hexpm", "821b2470ca9442c4b6984882fe9bb0389371b8ddec4d45a9504f00a66f650b44"},
"nimble_ownership": {:hex, :nimble_ownership, "1.0.1", "f69fae0cdd451b1614364013544e66e4f5d25f36a2056a9698b793305c5aa3a6", [:mix], [], "hexpm", "3825e461025464f519f3f3e4a1f9b68c47dc151369611629ad08b636b73bb22d"},
"nimble_parsec": {:hex, :nimble_parsec, "1.4.2", "8efba0122db06df95bfaa78f791344a89352ba04baedd3849593bfce4d0dc1c6", [:mix], [], "hexpm", "4b21398942dda052b403bbe1da991ccd03a053668d147d53fb8c4e0efe09c973"},
"nimble_pool": {:hex, :nimble_pool, "1.1.0", "bf9c29fbdcba3564a8b800d1eeb5a3c58f36e1e11d7b7fb2e084a643f645f06b", [:mix], [], "hexpm", "af2e4e6b34197db81f7aad230c1118eac993acc0dae6bc83bac0126d4ae0813a"},
"nimble_totp": {:hex, :nimble_totp, "1.0.0", "79753bae6ce59fd7cacdb21501a1dbac249e53a51c4cd22b34fa8438ee067283", [:mix], [], "hexpm", "6ce5e4c068feecdb782e85b18237f86f66541523e6bad123e02ee1adbe48eda9"},
Expand All @@ -83,7 +84,7 @@
"recaptcha": {:git, "https://github.com/samueljseay/recaptcha.git", "71cd746be987f6834c1a933f5d2f934350e55060", [ref: "71cd746be987f6834c1a933f5d2f934350e55060"]},
"result": {:hex, :result, "1.7.2", "a57c569f7cf5c158d2299d3b5624a48b69bd1520d0771dc711bcf9f3916e8ab6", [:mix], [], "hexpm", "89f98e98cfbf64237ecf4913aa36b76b80463e087775d19953dc4b435a35f087"},
"rstar": {:git, "https://github.com/armon/erl-rstar.git", "a406b2cce609029bf65b9ccfbe93a0416c0ee0cd", []},
"sentry": {:hex, :sentry, "8.1.0", "8d235b62fce5f8e067ea1644e30939405b71a5e1599d9529ff82899d11d03f2b", [:mix], [{:hackney, "~> 1.8", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:plug, "~> 1.6", [hex: :plug, repo: "hexpm", optional: true]}, {:plug_cowboy, "~> 2.3", [hex: :plug_cowboy, repo: "hexpm", optional: true]}], "hexpm", "f9fc7641ef61e885510f5e5963c2948b9de1de597c63f781e9d3d6c9c8681ab4"},
"sentry": {:hex, :sentry, "11.0.4", "60371c96cefd247e0fc98840bba2648f64f19aa0b8db8e938f5a98421f55b619", [:mix], [{:hackney, "~> 1.8", [hex: :hackney, repo: "hexpm", optional: true]}, {:igniter, "~> 0.5", [hex: :igniter, 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 or ~> 1.0", [hex: :nimble_ownership, repo: "hexpm", optional: false]}, {:opentelemetry, ">= 0.0.0", [hex: :opentelemetry, repo: "hexpm", optional: true]}, {:opentelemetry_api, ">= 0.0.0", [hex: :opentelemetry_api, repo: "hexpm", optional: true]}, {:opentelemetry_exporter, ">= 0.0.0", [hex: :opentelemetry_exporter, repo: "hexpm", optional: true]}, {:opentelemetry_semantic_conventions, ">= 0.0.0", [hex: :opentelemetry_semantic_conventions, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6", [hex: :phoenix, repo: "hexpm", optional: true]}, {:phoenix_live_view, "~> 0.20 or ~> 1.0", [hex: :phoenix_live_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.6", [hex: :plug, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "feaafc284dc204c82aadaddc884227aeaa3480decb274d30e184b9d41a700c66"},
"sobelow": {:hex, :sobelow, "0.14.1", "2f81e8632f15574cba2402bcddff5497b413c01e6f094bc0ab94e83c2f74db81", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "8fac9a2bd90fdc4b15d6fca6e1608efb7f7c600fa75800813b794ee9364c87f2"},
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.7", "354c321cf377240c7b8716899e182ce4890c5938111a1296add3ec74cf1715df", [:make, :mix, :rebar3], [], "hexpm", "fe4c190e8f37401d30167c8c405eda19469f34577987c76dde613e838bbc67f8"},
"stream_data": {:hex, :stream_data, "1.2.0", "58dd3f9e88afe27dc38bef26fce0c84a9e7a96772b2925c7b32cd2435697a52b", [:mix], [], "hexpm", "eb5c546ee3466920314643edf68943a5b14b32d1da9fe01698dc92b73f89a9ed"},
Expand Down
Loading