Skip to content

Commit cc61afd

Browse files
committed
Clean up Sentry.ClientError
1 parent 50fcdbc commit cc61afd

File tree

2 files changed

+80
-75
lines changed

2 files changed

+80
-75
lines changed

lib/sentry/client_error.ex

Lines changed: 39 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ defmodule Sentry.ClientError do
44
reporting an error or a message.
55
66
This struct is designed to manage and handle errors originating from operations
7-
in the Sentry client. The `:reason` field signifies the cause of the error
8-
as an atom or tuple.
7+
in the Sentry client. The `:reason` field contains the cause of the error
8+
as an atom or tuple (see `t:reason/0`).
99
10-
To raise instances of this exception, you can use `Kernel.raise/1`. When crafting
10+
To raise instances of this exception, you can use `raise/1`. When crafting
1111
formatted error messages for purposes such as logging or presentation, consider
1212
leveraging `Exception.message/1`.
1313
"""
@@ -28,14 +28,15 @@ defmodule Sentry.ClientError do
2828
nil | {status :: 100..599, headers :: [{String.t(), String.t()}], body :: binary()}
2929
}
3030

31+
@typedoc """
32+
The reason for a Sentry error exception.
33+
"""
3134
@type reason() ::
3235
:too_many_retries
3336
| :server_error
3437
| {:invalid_json, Exception.t()}
35-
| {:request_failure, String.t()}
36-
| {:request_failure, atom}
37-
| {:request_failure, term()}
38-
| {atom(), term(), [term()]}
38+
| {:request_failure, reason :: :inet.posix() | term()}
39+
| {Exception.kind(), reason :: term(), Exception.stacktrace()}
3940

4041
@doc false
4142
@spec new(reason()) :: t
@@ -44,63 +45,62 @@ defmodule Sentry.ClientError do
4445
end
4546

4647
@doc false
47-
@spec server_error(
48-
status :: 100..599,
49-
headers ::
50-
[{String.t(), String.t()}],
51-
body :: binary()
52-
) :: t
48+
@spec server_error(status :: 100..599, headers :: [{String.t(), String.t()}], body :: binary()) ::
49+
t
5350
def server_error(status, headers, body) do
5451
%__MODULE__{reason: :server_error, http_response: {status, headers, body}}
5552
end
5653

5754
@impl true
58-
def message(%__MODULE__{reason: reason, http_response: http_response})
59-
when is_nil(http_response) do
60-
"request failure reason: #{format(reason)}"
61-
end
62-
6355
def message(%__MODULE__{reason: reason, http_response: http_response}) do
64-
"request failure reason: #{format(reason, http_response)}"
56+
"Sentry failed to report event: #{format(reason, http_response)}"
6557
end
6658

67-
defp format(:too_many_retries) do
68-
"Sentry responded with status 429 - Too Many Requests"
59+
defp format(:server_error, {status, headers, body}) do
60+
"""
61+
the Sentry server responded with an error, the details are below.
62+
HTTP Status: #{status}
63+
Response Headers: #{inspect(headers)}
64+
Response Body: #{inspect(body)}
65+
"""
6966
end
7067

71-
defp format({:invalid_json, reason}) do
72-
"Invalid JSON -> #{Exception.message(reason)}"
68+
defp format(reason, nil) do
69+
format(reason)
7370
end
7471

75-
defp format({:request_failure, reason}) when is_binary(reason) do
76-
"#{reason}"
72+
defp format(:too_many_retries) do
73+
"Sentry responded with status 429 - Too Many Requests"
7774
end
7875

79-
defp format({:request_failure, reason}) when is_atom(reason) do
80-
case :inet.format_error(reason) do
81-
~c"unknown POSIX error" -> inspect(reason)
82-
formatted -> List.to_string(formatted)
83-
end
76+
defp format({:invalid_json, reason}) do
77+
"the Sentry SDK could not encode the event to JSON: #{Exception.message(reason)}"
8478
end
8579

8680
defp format({:request_failure, reason}) do
87-
inspect(reason)
81+
"there was a request failure: #{format_request_failure(reason)}"
8882
end
8983

9084
defp format({kind, data, stacktrace}) do
9185
"""
92-
Sentry failed to report event due to an unexpected error:
86+
there was an unexpected error:
9387
9488
#{Exception.format(kind, data, stacktrace)}\
9589
"""
9690
end
9791

98-
defp format(:server_error, {status, headers, body}) do
99-
"""
100-
Sentry failed to report the event due to a server error.
101-
HTTP Status: #{status}
102-
Response Headers: #{inspect(headers)}
103-
Response Body: #{inspect(body)}
104-
"""
92+
defp format_request_failure(reason) when is_binary(reason) do
93+
reason
94+
end
95+
96+
defp format_request_failure(reason) when is_atom(reason) do
97+
case :inet.format_error(reason) do
98+
~c"unknown POSIX error" -> inspect(reason)
99+
formatted -> List.to_string(formatted)
100+
end
101+
end
102+
103+
defp format_request_failure(reason) do
104+
inspect(reason)
105105
end
106106
end

test/sentry/client_error_test.exs

Lines changed: 41 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2,56 +2,61 @@ defmodule Sentry.ClientErrorTest do
22
use Sentry.Case
33
alias Sentry.ClientError
44

5-
describe "message/1" do
6-
test "with atom - returns message" do
7-
assert "request failure reason: Sentry responded with status 429 - Too Many Requests" =
8-
result_msg(:too_many_retries)
5+
describe "c:Exception.message/1" do
6+
test "with an atom reason" do
7+
assert message_for_reason(:too_many_retries) ==
8+
"Sentry responded with status 429 - Too Many Requests"
99
end
1010

11-
test "with tuple {:invalid_json, _} - returns message" do
12-
assert "request failure reason: Invalid JSON -> unexpected byte at position 0: 0x69 (\"i\")" =
13-
result_msg(
14-
{:invalid_json,
15-
%Jason.DecodeError{position: 0, token: nil, data: "invalid JSON"}}
16-
)
11+
test "with {:invalid_json, _} reason" do
12+
assert message_for_reason(
13+
{:invalid_json, %Jason.DecodeError{position: 0, token: nil, data: "invalid JSON"}}
14+
) ==
15+
"the Sentry SDK could not encode the event to JSON: unexpected byte at position 0: 0x69 (\"i\")"
1716
end
1817

19-
test "with tuple {:request_failure, _} and binary - returns message" do
20-
assert "request failure reason: Received 400 from Sentry server: some error" =
21-
result_msg({:request_failure, "Received 400 from Sentry server: some error"})
22-
end
18+
test "with {:request_failure, reason} reason" do
19+
assert message_for_reason({:request_failure, "some error"}) ==
20+
"there was a request failure: some error"
2321

24-
test "with tuple {:request_failure, _} and atom - returns message" do
25-
assert "request failure reason: connection refused" =
26-
result_msg({:request_failure, :econnrefused})
27-
end
22+
assert message_for_reason({:request_failure, :econnrefused}) ==
23+
"there was a request failure: connection refused"
24+
25+
assert message_for_reason({:request_failure, :whatever}) ==
26+
"there was a request failure: unknown POSIX error: whatever"
2827

29-
test "with tuple {:request_failure, _} and anything else - returns message" do
30-
assert "request failure reason: {:error, %RuntimeError{message: \"I'm a really bad HTTP client\"}}" =
31-
result_msg(
32-
{:request_failure,
33-
{:error, %RuntimeError{message: "I'm a really bad HTTP client"}}}
34-
)
28+
assert message_for_reason({:request_failure, 123}) == "there was a request failure: 123"
3529
end
3630

37-
test "with Exception- returns message" do
38-
{kind, data, stacktrace} =
39-
{:error, %RuntimeError{message: "I'm a really bad HTTP client"}, []}
31+
test "with {kind, reason, stacktrace} reason" do
32+
{:current_stacktrace, stacktrace} = Process.info(self(), :current_stacktrace)
4033

41-
assert "request failure reason: Sentry failed to report event due to an unexpected error:\n\n** (RuntimeError) I'm a really bad HTTP client" =
42-
result_msg({kind, data, stacktrace})
34+
assert message_for_reason(
35+
{:error, %RuntimeError{message: "I'm a really bad HTTP client"}, stacktrace}
36+
) =~ """
37+
there was an unexpected error:
38+
39+
** (RuntimeError) I'm a really bad HTTP client
40+
(elixir\
41+
"""
4342
end
4443

45-
test "with server_error- returns message" do
46-
{status, headers, body} =
47-
{400, "Rate limiting.", "{}"}
44+
test "with :server_error and HTTP response as the reason" do
45+
exception = ClientError.server_error(400, [{"X-Foo", "true"}], "{}")
4846

49-
assert "request failure reason: Sentry failed to report the event due to a server error.\nHTTP Status: 400\nResponse Headers: \"Rate limiting.\"\nResponse Body: \"{}\"\n" =
50-
ClientError.server_error(status, headers, body) |> ClientError.message()
47+
assert Exception.message(exception) == """
48+
Sentry failed to report event: the Sentry server responded with an error, the details are below.
49+
HTTP Status: 400
50+
Response Headers: [{"X-Foo", "true"}]
51+
Response Body: "{}"
52+
"""
5153
end
5254
end
5355

54-
defp result_msg(reason) do
55-
reason |> ClientError.new() |> ClientError.message()
56+
defp message_for_reason(reason) do
57+
assert "Sentry failed to report event: " <> rest =
58+
reason |> ClientError.new() |> Exception.message()
59+
60+
rest
5661
end
5762
end

0 commit comments

Comments
 (0)