Skip to content

Commit 4d159eb

Browse files
Merge pull request #218 from getsentry/avoid-raising-on-bad-dsn
avoid raising on bad dsn
2 parents c3ace17 + e95a163 commit 4d159eb

File tree

9 files changed

+109
-52
lines changed

9 files changed

+109
-52
lines changed

.travis.yml

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,18 @@ otp_release:
99
- 19.3
1010
- 20.2
1111
env:
12-
- MIX_FORMAT=true
13-
- MIX_FORMAT=false
12+
- STRICT=true
13+
- STRICT=false
1414
matrix:
1515
exclude:
1616
- elixir: 1.6
17-
env: MIX_FORMAT=false
17+
env: STRICT=false
1818
- elixir: 1.3.4
19-
env: MIX_FORMAT=true
19+
env: STRICT=true
2020
- elixir: 1.4
21-
env: MIX_FORMAT=true
21+
env: STRICT=true
2222
- elixir: 1.5
23-
env: MIX_FORMAT=true
23+
env: STRICT=true
2424
- elixir: 1.6
2525
otp_release: 18.3
2626
- elixir: 1.3.4
@@ -29,6 +29,12 @@ notifications:
2929
email:
3030
3131
script:
32+
- if [ "$STRICT" = "true" ]; then mix compile --warnings-as-errors; fi
3233
- mix test
3334
- mix credo
34-
- if [ "$MIX_FORMAT" = "true" ]; then mix format --dry-run --check-formatted; fi
35+
- if [ "$STRICT" = "true" ]; then mix dialyzer; fi
36+
- if [ "$STRICT" = "true" ]; then mix format --dry-run --check-formatted; fi
37+
cache:
38+
directories:
39+
- .mix
40+
- _build

lib/mix/tasks/sentry.send_test_event.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ defmodule Mix.Tasks.Sentry.SendTestEvent do
1414

1515
Application.ensure_all_started(:sentry)
1616

17-
Sentry.Client.get_dsn!()
17+
Sentry.Client.get_dsn()
1818
|> print_environment_info()
1919

2020
maybe_send_event()

lib/sentry.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ defmodule Sentry do
9191
See `Sentry.Logger`
9292
"""
9393

94-
@type send_result :: Sentry.Client.send_result() | :excluded | :ignored
94+
@type send_result :: Sentry.Client.send_event_result() | :excluded | :ignored
9595

9696
def start(_type, _opts) do
9797
children = [

lib/sentry/client.ex

Lines changed: 57 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ defmodule Sentry.Client do
3838

3939
require Logger
4040

41-
@type dsn :: {String.t(), String.t(), String.t()}
4241
@type send_event_result :: {:ok, Task.t() | String.t() | pid()} | :error | :unsampled
42+
@type dsn :: {String.t(), String.t(), String.t()} | :error
4343
@sentry_version 5
4444
@max_attempts 4
4545
@hackney_pool_name :sentry_pool
@@ -85,34 +85,43 @@ defmodule Sentry.Client do
8585
end
8686

8787
defp do_send_event(event, body, :async) do
88-
{endpoint, public_key, secret_key} = get_dsn!()
89-
auth_headers = authorization_headers(public_key, secret_key)
90-
91-
{:ok,
92-
Task.Supervisor.async_nolink(Sentry.TaskSupervisor, fn ->
93-
try_request(:post, endpoint, auth_headers, body)
94-
|> maybe_call_after_send_event(event)
95-
end)}
88+
case get_headers_and_endpoint() do
89+
{endpoint, auth_headers} ->
90+
{:ok,
91+
Task.Supervisor.async_nolink(Sentry.TaskSupervisor, fn ->
92+
try_request(:post, endpoint, auth_headers, body)
93+
|> maybe_call_after_send_event(event)
94+
end)}
95+
96+
_ ->
97+
:error
98+
end
9699
end
97100

98101
defp do_send_event(event, body, :sync) do
99-
{endpoint, public_key, secret_key} = get_dsn!()
100-
auth_headers = authorization_headers(public_key, secret_key)
102+
case get_headers_and_endpoint() do
103+
{endpoint, auth_headers} ->
104+
try_request(:post, endpoint, auth_headers, body)
105+
|> maybe_call_after_send_event(event)
101106

102-
try_request(:post, endpoint, auth_headers, body)
103-
|> maybe_call_after_send_event(event)
107+
_ ->
108+
:error
109+
end
104110
end
105111

106112
defp do_send_event(event, body, :none) do
107-
{endpoint, public_key, secret_key} = get_dsn!()
108-
auth_headers = authorization_headers(public_key, secret_key)
113+
case get_headers_and_endpoint() do
114+
{endpoint, auth_headers} ->
115+
Task.Supervisor.start_child(Sentry.TaskSupervisor, fn ->
116+
try_request(:post, endpoint, auth_headers, body)
117+
|> maybe_call_after_send_event(event)
118+
end)
109119

110-
Task.Supervisor.start_child(Sentry.TaskSupervisor, fn ->
111-
try_request(:post, endpoint, auth_headers, body)
112-
|> maybe_call_after_send_event(event)
113-
end)
120+
{:ok, ""}
114121

115-
{:ok, ""}
122+
_ ->
123+
:error
124+
end
116125
end
117126

118127
defp try_request(method, url, headers, body, current_attempt \\ 1)
@@ -193,19 +202,25 @@ defmodule Sentry.Client do
193202

194203
@doc """
195204
Get a Sentry DSN which is simply a URI.
205+
206+
{PROTOCOL}://{PUBLIC_KEY}:{SECRET_KEY}@{HOST}/{PATH}{PROJECT_ID}
196207
"""
197-
@spec get_dsn! :: dsn
198-
def get_dsn! do
199-
# {PROTOCOL}://{PUBLIC_KEY}:{SECRET_KEY}@{HOST}/{PATH}{PROJECT_ID}
200-
%URI{userinfo: userinfo, host: host, port: port, path: path, scheme: protocol} =
201-
URI.parse(Config.dsn())
202-
203-
[public_key, secret_key] = String.split(userinfo, ":", parts: 2)
204-
[_, binary_project_id] = String.split(path, "/")
205-
project_id = String.to_integer(binary_project_id)
206-
endpoint = "#{protocol}://#{host}:#{port}/api/#{project_id}/store/"
207-
208-
{endpoint, public_key, secret_key}
208+
@spec get_dsn :: dsn
209+
def get_dsn do
210+
dsn = Config.dsn()
211+
212+
with %URI{userinfo: userinfo, host: host, port: port, path: path, scheme: protocol}
213+
when is_binary(path) <- URI.parse(dsn),
214+
[public_key, secret_key] <- String.split(userinfo, ":", parts: 2),
215+
[_, binary_project_id] <- String.split(path, "/"),
216+
{project_id, ""} <- Integer.parse(binary_project_id),
217+
endpoint <- "#{protocol}://#{host}:#{port}/api/#{project_id}/store/" do
218+
{endpoint, public_key, secret_key}
219+
else
220+
_ ->
221+
log_api_error("Cannot send event because of invalid DSN")
222+
:error
223+
end
209224
end
210225

211226
@spec maybe_call_after_send_event(send_event_result, Event.t()) :: Event.t()
@@ -289,6 +304,16 @@ defmodule Sentry.Client do
289304
end
290305
end
291306

307+
defp get_headers_and_endpoint do
308+
case get_dsn() do
309+
{endpoint, public_key, secret_key} ->
310+
{endpoint, authorization_headers(public_key, secret_key)}
311+
312+
_ ->
313+
:error
314+
end
315+
end
316+
292317
defp log_api_error(body) do
293318
Logger.warn(fn ->
294319
["Failed to send Sentry event.", ?\n, body]

mix.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ defmodule Sentry.Mixfile do
1010
package: package(),
1111
deps: deps(),
1212
elixirc_paths: elixirc_paths(Mix.env()),
13-
dialyzer: [plt_add_deps: :transitive],
13+
dialyzer: [plt_add_deps: :transitive, plt_add_apps: [:mix]],
1414
docs: [extras: ["README.md"], main: "readme"]
1515
]
1616
end

mix.lock

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,23 @@
1-
%{"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm"},
1+
%{
2+
"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm"},
23
"bypass": {:hex, :bypass, "0.8.1", "16d409e05530ece4a72fabcf021a3e5c7e15dcc77f911423196a0c551f2a15ca", [:mix], [{:cowboy, "~> 1.0", [hex: :cowboy, repo: "hexpm", optional: false]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
34
"certifi": {:hex, :certifi, "1.2.1", "c3904f192bd5284e5b13f20db3ceac9626e14eeacfbb492e19583cf0e37b22be", [:rebar3], [], "hexpm"},
45
"cowboy": {:hex, :cowboy, "1.1.2", "61ac29ea970389a88eca5a65601460162d370a70018afe6f949a29dca91f3bb0", [:rebar3], [{:cowlib, "~> 1.0.2", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.3.2", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm"},
56
"cowlib": {:hex, :cowlib, "1.0.2", "9d769a1d062c9c3ac753096f868ca121e2730b9a377de23dec0f7e08b1df84ee", [:make], [], "hexpm"},
67
"credo": {:hex, :credo, "0.8.10", "261862bb7363247762e1063713bb85df2bbd84af8d8610d1272cd9c1943bba63", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}], "hexpm"},
78
"dialyxir": {:hex, :dialyxir, "0.5.1", "b331b091720fd93e878137add264bac4f644e1ddae07a70bf7062c7862c4b952", [:mix], [], "hexpm"},
8-
"earmark": {:hex, :earmark, "1.2.3", "206eb2e2ac1a794aa5256f3982de7a76bf4579ff91cb28d0e17ea2c9491e46a4", [:mix], [], "hexpm"},
9-
"ex_doc": {:hex, :ex_doc, "0.18.1", "37c69d2ef62f24928c1f4fdc7c724ea04aecfdf500c4329185f8e3649c915baf", [:mix], [{:earmark, "~> 1.1", [hex: :earmark, repo: "hexpm", optional: false]}], "hexpm"},
9+
"earmark": {:hex, :earmark, "1.2.4", "99b637c62a4d65a20a9fb674b8cffb8baa771c04605a80c911c4418c69b75439", [:mix], [], "hexpm"},
10+
"ex_doc": {:hex, :ex_doc, "0.18.3", "f4b0e4a2ec6f333dccf761838a4b253d75e11f714b85ae271c9ae361367897b7", [:mix], [{:earmark, "~> 1.1", [hex: :earmark, repo: "hexpm", optional: false]}], "hexpm"},
1011
"hackney": {:hex, :hackney, "1.8.6", "21a725db3569b3fb11a6af17d5c5f654052ce9624219f1317e8639183de4a423", [:rebar3], [{:certifi, "1.2.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "5.0.2", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.1", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"},
1112
"idna": {:hex, :idna, "5.0.2", "ac203208ada855d95dc591a764b6e87259cb0e2a364218f215ad662daa8cd6b4", [:rebar3], [{:unicode_util_compat, "0.2.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"},
1213
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm"},
13-
"mime": {:hex, :mime, "1.1.0", "01c1d6f4083d8aa5c7b8c246ade95139620ef8effb009edde934e0ec3b28090a", [:mix], [], "hexpm"},
14+
"mime": {:hex, :mime, "1.2.0", "78adaa84832b3680de06f88f0997e3ead3b451a440d183d688085be2d709b534", [:mix], [], "hexpm"},
1415
"mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [:rebar3], [], "hexpm"},
1516
"plug": {:hex, :plug, "1.4.3", "236d77ce7bf3e3a2668dc0d32a9b6f1f9b1f05361019946aae49874904be4aed", [:mix], [{:cowboy, "~> 1.0.1 or ~> 1.1", [hex: :cowboy, repo: "hexpm", optional: true]}, {:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}], "hexpm"},
1617
"poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], [], "hexpm"},
1718
"ranch": {:hex, :ranch, "1.3.2", "e4965a144dc9fbe70e5c077c65e73c57165416a901bd02ea899cfd95aa890986", [:rebar3], [], "hexpm"},
1819
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.1", "28a4d65b7f59893bc2c7de786dec1e1555bd742d336043fe644ae956c3497fbe", [:make, :rebar], [], "hexpm"},
1920
"ssl_verify_hostname": {:hex, :ssl_verify_hostname, "1.0.5", "2e73e068cd6393526f9fa6d399353d7c9477d6886ba005f323b592d389fb47be", [:make], []},
2021
"unicode_util_compat": {:hex, :unicode_util_compat, "0.2.0", "dbbccf6781821b1c0701845eaf966c9b6d83d7c3bfc65ca2b78b88b8678bfa35", [:rebar3], [], "hexpm"},
21-
"uuid": {:hex, :uuid, "1.1.8", "e22fc04499de0de3ed1116b770c7737779f226ceefa0badb3592e64d5cfb4eb9", [:mix], [], "hexpm"}}
22+
"uuid": {:hex, :uuid, "1.1.8", "e22fc04499de0de3ed1116b770c7737779f226ceefa0badb3592e64d5cfb4eb9", [:mix], [], "hexpm"},
23+
}

test/client_test.exs

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ defmodule Sentry.ClientTest do
88

99
test "authorization" do
1010
modify_env(:sentry, dsn: "https://public:[email protected]/1")
11-
{_endpoint, public_key, private_key} = Client.get_dsn!()
11+
{_endpoint, public_key, private_key} = Client.get_dsn()
1212

1313
assert Client.authorization_header(public_key, private_key) =~
1414
~r/^Sentry sentry_version=5, sentry_client=sentry-elixir\/#{
@@ -20,15 +20,39 @@ defmodule Sentry.ClientTest do
2020
modify_env(:sentry, dsn: "https://public:[email protected]/1")
2121

2222
assert {"https://app.getsentry.com:443/api/1/store/", "public", "secret"} =
23-
Sentry.Client.get_dsn!()
23+
Sentry.Client.get_dsn()
2424
end
2525

2626
test "get dsn with system config" do
2727
modify_env(:sentry, dsn: {:system, "SYSTEM_KEY"})
2828
modify_system_env(%{"SYSTEM_KEY" => "https://public:[email protected]/1"})
2929

3030
assert {"https://app.getsentry.com:443/api/1/store/", "public", "secret"} =
31-
Sentry.Client.get_dsn!()
31+
Sentry.Client.get_dsn()
32+
end
33+
34+
test "errors on bad public/secret keys" do
35+
modify_env(:sentry, dsn: "https://[email protected]/1")
36+
37+
capture_log(fn ->
38+
assert :error = Sentry.Client.get_dsn()
39+
end)
40+
end
41+
42+
test "errors on non-integer project_id" do
43+
modify_env(:sentry, dsn: "https://public:[email protected]/Mitchell")
44+
45+
capture_log(fn ->
46+
assert :error = Sentry.Client.get_dsn()
47+
end)
48+
end
49+
50+
test "errors on no project_id" do
51+
modify_env(:sentry, dsn: "https://public:[email protected]")
52+
53+
capture_log(fn ->
54+
assert :error = Sentry.Client.get_dsn()
55+
end)
3256
end
3357

3458
test "logs api errors" do

test/event_test.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,7 @@ defmodule Sentry.EventTest do
457457
hackney: "1.8.6",
458458
idna: "5.0.2",
459459
metrics: "1.0.1",
460-
mime: "1.1.0",
460+
mime: "1.2.0",
461461
mimerl: "1.0.2",
462462
plug: "1.4.3",
463463
poison: "3.1.0",

test/support/test_client.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ defmodule Sentry.TestClient do
33
require Logger
44

55
def send_event(%Sentry.Event{} = event, _opts \\ []) do
6-
{endpoint, _public_key, _secret_key} = Sentry.Client.get_dsn!()
6+
{endpoint, _public_key, _secret_key} = Sentry.Client.get_dsn()
77
event = Sentry.Client.maybe_call_before_send_event(event)
88

99
Sentry.Client.render_event(event)

0 commit comments

Comments
 (0)