-
-
Notifications
You must be signed in to change notification settings - Fork 424
Expand file tree
/
Copy pathfallback_controller.ex
More file actions
114 lines (93 loc) · 3.31 KB
/
fallback_controller.ex
File metadata and controls
114 lines (93 loc) · 3.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
defmodule RealtimeWeb.FallbackController do
@moduledoc """
Translates controller action results into valid `Plug.Conn` responses.
See `Phoenix.Controller.action_fallback/1` for more details.
"""
use RealtimeWeb, :controller
use Realtime.Logs
import RealtimeWeb.ErrorHelpers
require Logger
def call(conn, {:error, :not_found}) do
log_error("TenantNotFound", "Tenant not found")
maybe_capture_sentry_error(conn, "TenantNotFound", "Tenant not found")
conn
|> put_status(:not_found)
|> put_view(RealtimeWeb.ErrorView)
|> render("error.json", message: "not found")
end
def call(conn, {:error, %Ecto.Changeset{} = changeset}) do
details = Ecto.Changeset.traverse_errors(changeset, &translate_error/1)
log_error(
"UnprocessableEntity",
details
)
maybe_capture_sentry_error(conn, "UnprocessableEntity", details)
conn
|> put_status(:unprocessable_entity)
|> put_view(RealtimeWeb.ChangesetView)
|> render("error.json", changeset: changeset)
end
def call(conn, {:error, status, message}) when is_atom(status) and is_binary(message) do
log_error("UnprocessableEntity", message)
maybe_capture_sentry_error(conn, "UnprocessableEntity", message)
conn
|> put_status(status)
|> put_view(RealtimeWeb.ErrorView)
|> render("error.json", message: message)
end
def call(conn, {:error, %Ecto.Changeset{valid?: false} = changeset}) do
details = Ecto.Changeset.traverse_errors(changeset, &translate_error/1)
log_error(
"UnprocessableEntity",
details
)
maybe_capture_sentry_error(conn, "UnprocessableEntity", details)
conn
|> put_status(:unprocessable_entity)
|> put_view(RealtimeWeb.ChangesetView)
|> render("error.json", changeset: changeset)
end
def call(conn, {:error, _}) do
conn
|> put_status(:unauthorized)
|> put_view(RealtimeWeb.ErrorView)
|> render("error.json", message: "Unauthorized")
end
def call(conn, %Ecto.Changeset{valid?: false} = changeset) do
details = Ecto.Changeset.traverse_errors(changeset, &translate_error/1)
log_error(
"UnprocessableEntity",
details
)
maybe_capture_sentry_error(conn, "UnprocessableEntity", details)
conn
|> put_status(:unprocessable_entity)
|> put_view(RealtimeWeb.ChangesetView)
|> render("error.json", changeset: changeset)
end
def call(conn, response) do
log_error("UnknownErrorOnController", response)
maybe_capture_sentry_error(conn, "UnknownErrorOnController", response)
conn
|> put_status(:unprocessable_entity)
|> put_view(RealtimeWeb.ErrorView)
|> render("error.json", message: "Unknown error")
end
defp maybe_capture_sentry_error(conn, code, details) do
if sampled?(Application.get_env(:realtime, :sentry_controller_error_sample_rate, 1.0)) do
Sentry.capture_message("#{code}: controller error",
level: :error,
tags: %{error_code: code, source: "controller"},
extra: %{
method: conn.method,
path: conn.request_path,
request_id: Logger.metadata()[:request_id],
details: details
}
)
end
end
defp sampled?(rate) when is_float(rate), do: rate >= 1.0 or :rand.uniform() <= rate
defp sampled?(rate) when is_integer(rate), do: sampled?(rate / 1)
defp sampled?(_), do: false
end