From cc3ee90551ac732e8b08cce9b0cb5ed8cf2a133b Mon Sep 17 00:00:00 2001 From: Rafael Jesus Date: Thu, 19 Jan 2017 11:33:17 -0200 Subject: [PATCH 1/4] Expose dsn_env function --- lib/sentry/client.ex | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/sentry/client.ex b/lib/sentry/client.ex index 1ee4055d..392ec8d6 100644 --- a/lib/sentry/client.ex +++ b/lib/sentry/client.ex @@ -21,7 +21,7 @@ defmodule Sentry.Client do """ @spec send_event(%Event{}) :: {:ok, String.t} | :error def send_event(%Event{} = event) do - {endpoint, public_key, secret_key} = parse_dsn!(Application.fetch_env!(:sentry, :dsn)) + {endpoint, public_key, secret_key} = dsn_env |> parse_dsn! auth_headers = authorization_headers(public_key, secret_key) body = Poison.encode!(event) @@ -31,6 +31,13 @@ defmodule Sentry.Client do end) end + def dsn_env do + case Application.get_env(:sentry, :dsn) do + {:system, env_var} -> System.get_env(env_var) + value -> value + end + end + defp try_request(method, url, headers, body) do do_try_request(method, url, headers, body, 1) end From 300c4f94ab424c846de7dcb77fcc27d38ef10d9c Mon Sep 17 00:00:00 2001 From: Rafael Jesus Date: Thu, 19 Jan 2017 11:34:11 -0200 Subject: [PATCH 2/4] Add tests --- test/client_test.exs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/client_test.exs b/test/client_test.exs index 8f52e1e7..a7a1211d 100644 --- a/test/client_test.exs +++ b/test/client_test.exs @@ -18,6 +18,17 @@ defmodule Sentry.ClientTest do Sentry.Client.parse_dsn!("http://public:secret@app.getsentry.com:9000/1") end + test "fetches default dsn_env" do + Application.put_env(:sentry, :dsn, @sentry_dsn) + assert @sentry_dsn == Sentry.Client.dsn_env + end + + test "fetches system dsn_env" do + System.put_env("SYSTEM_KEY", @sentry_dsn) + Application.put_env(:sentry, :dsn, {:system, "SYSTEM_KEY"}) + assert @sentry_dsn == Sentry.Client.dsn_env + end + test "logs api errors" do bypass = Bypass.open Bypass.expect bypass, fn conn -> From 131a2d8e43230184dbc5a129ca66689981784d98 Mon Sep 17 00:00:00 2001 From: Rafael Jesus Date: Thu, 19 Jan 2017 16:31:43 -0200 Subject: [PATCH 3/4] Use fetch_env instead of get_env --- lib/sentry/client.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/sentry/client.ex b/lib/sentry/client.ex index 392ec8d6..703ace05 100644 --- a/lib/sentry/client.ex +++ b/lib/sentry/client.ex @@ -32,7 +32,7 @@ defmodule Sentry.Client do end def dsn_env do - case Application.get_env(:sentry, :dsn) do + case Application.fetch_env!(:sentry, :dsn) do {:system, env_var} -> System.get_env(env_var) value -> value end From c2794cf38c063012e82e74d3992a583bee1d5d53 Mon Sep 17 00:00:00 2001 From: Rafael Jesus Date: Fri, 20 Jan 2017 10:02:57 -0200 Subject: [PATCH 4/4] Exposes get_dsn! function --- lib/mix/tasks/sentry.send_test_event.ex | 16 +++++++------- lib/sentry/client.ex | 26 +++++++++++------------ test/client_test.exs | 28 ++++++++++++------------- test/support/test_client.ex | 2 +- 4 files changed, 35 insertions(+), 37 deletions(-) diff --git a/lib/mix/tasks/sentry.send_test_event.ex b/lib/mix/tasks/sentry.send_test_event.ex index a32e28a5..355c70f9 100644 --- a/lib/mix/tasks/sentry.send_test_event.ex +++ b/lib/mix/tasks/sentry.send_test_event.ex @@ -5,11 +5,7 @@ defmodule Mix.Tasks.Sentry.SendTestEvent do def run(_args) do Application.ensure_all_started(:sentry) - {endpoint, public_key, secret_key} = case Application.fetch_env(:sentry, :dsn) do - {:ok, dsn} when is_binary(dsn) -> Sentry.Client.parse_dsn!(dsn) - _ -> - Mix.raise "Sentry DSN is not configured in :sentry, :dsn" - end + {endpoint, public_key, secret_key} = Sentry.Client.get_dsn! included_environments = case Application.fetch_env(:sentry, :included_environments) do {:ok, envs} when is_list(envs) -> envs @@ -30,11 +26,15 @@ defmodule Mix.Tasks.Sentry.SendTestEvent do maybe_send_event(environment_name, included_environments) end - def maybe_send_event(env_name, included_envs) do + defp maybe_send_event(env_name, included_envs) do if env_name in included_envs do Mix.shell.info "Sending test event..." - Sentry.capture_exception(RuntimeError.exception("Testing sending Sentry event")) - |> Task.await() + + "Testing sending Sentry event" + |> RuntimeError.exception + |> Sentry.capture_exception + |> Task.await + Mix.shell.info "Test event sent!" else Mix.shell.info "#{inspect env_name} is not in #{inspect included_envs} so no test event will be sent" diff --git a/lib/sentry/client.ex b/lib/sentry/client.ex index 703ace05..2957eca0 100644 --- a/lib/sentry/client.ex +++ b/lib/sentry/client.ex @@ -1,7 +1,7 @@ defmodule Sentry.Client do alias Sentry.{Event, Util} require Logger - @type parsed_dsn :: {String.t, String.t, Integer.t} + @type get_dsn :: {String.t, String.t, Integer.t} @sentry_version 5 @max_attempts 4 @@ -21,7 +21,7 @@ defmodule Sentry.Client do """ @spec send_event(%Event{}) :: {:ok, String.t} | :error def send_event(%Event{} = event) do - {endpoint, public_key, secret_key} = dsn_env |> parse_dsn! + {endpoint, public_key, secret_key} = get_dsn! auth_headers = authorization_headers(public_key, secret_key) body = Poison.encode!(event) @@ -31,13 +31,6 @@ defmodule Sentry.Client do end) end - def dsn_env do - case Application.fetch_env!(:sentry, :dsn) do - {:system, env_var} -> System.get_env(env_var) - value -> value - end - end - defp try_request(method, url, headers, body) do do_try_request(method, url, headers, body, 1) end @@ -101,12 +94,12 @@ defmodule Sentry.Client do end @doc """ - Parses a Sentry DSN which is simply a URI. + Get a Sentry DSN which is simply a URI. """ - @spec parse_dsn!(String.t) :: parsed_dsn - def parse_dsn!(dsn) do + @spec get_dsn! :: get_dsn + def get_dsn! do # {PROTOCOL}://{PUBLIC_KEY}:{SECRET_KEY}@{HOST}/{PATH}{PROJECT_ID} - %URI{userinfo: userinfo, host: host, port: port, path: path, scheme: protocol} = URI.parse(dsn) + %URI{userinfo: userinfo, host: host, port: port, path: path, scheme: protocol} = URI.parse(fetch_dsn) [public_key, secret_key] = String.split(userinfo, ":", parts: 2) [_, binary_project_id] = String.split(path, "/") project_id = String.to_integer(binary_project_id) @@ -115,6 +108,13 @@ defmodule Sentry.Client do {endpoint, public_key, secret_key} end + defp fetch_dsn do + case Application.fetch_env!(:sentry, :dsn) do + {:system, env_var} -> System.get_env(env_var) + value -> value + end + end + defp log_api_error(body) do Logger.warn(fn -> ["Failed to send sentry event.", ?\n, body] diff --git a/test/client_test.exs b/test/client_test.exs index a7a1211d..0a95daa5 100644 --- a/test/client_test.exs +++ b/test/client_test.exs @@ -5,28 +5,25 @@ defmodule Sentry.ClientTest do alias Sentry.Client @sentry_dsn "https://public:secret@app.getsentry.com/1" - test "authorization" do - {_endpoint, public_key, private_key} = Client.parse_dsn!("https://public:secret@app.getsentry.com/1") - assert Client.authorization_header(public_key, private_key) =~ ~r/Sentry sentry_version=5, sentry_client=sentry-elixir\/#{Application.spec(:sentry, :vsn)}, sentry_timestamp=\d{10}, sentry_key=public, sentry_secret=secret/ + setup do + Application.put_env(:sentry, :dsn, @sentry_dsn) end - test "parsing dsn" do - assert {"https://app.getsentry.com:443/api/1/store/", "public", "secret"} = - Sentry.Client.parse_dsn!("https://public:secret@app.getsentry.com/1") - - assert {"http://app.getsentry.com:9000/api/1/store/", "public", "secret"} = - Sentry.Client.parse_dsn!("http://public:secret@app.getsentry.com:9000/1") + test "authorization" do + {_endpoint, public_key, private_key} = Client.get_dsn! + assert Client.authorization_header(public_key, private_key) =~ ~r/Sentry sentry_version=5, sentry_client=sentry-elixir\/#{Application.spec(:sentry, :vsn)}, sentry_timestamp=\d{10}, sentry_key=public, sentry_secret=secret/ end - test "fetches default dsn_env" do - Application.put_env(:sentry, :dsn, @sentry_dsn) - assert @sentry_dsn == Sentry.Client.dsn_env + test "get dsn with default config" do + assert {"https://app.getsentry.com:443/api/1/store/", "public", "secret"} = Sentry.Client.get_dsn! end - test "fetches system dsn_env" do + test "get dsn with system config" do System.put_env("SYSTEM_KEY", @sentry_dsn) Application.put_env(:sentry, :dsn, {:system, "SYSTEM_KEY"}) - assert @sentry_dsn == Sentry.Client.dsn_env + assert {"https://app.getsentry.com:443/api/1/store/", "public", "secret"} = Sentry.Client.get_dsn! + + System.delete_env("SYSTEM_KEY") end test "logs api errors" do @@ -35,7 +32,8 @@ defmodule Sentry.ClientTest do {:ok, _body, conn} = Plug.Conn.read_body(conn) assert conn.request_path == "/api/1/store/" assert conn.method == "POST" - Plug.Conn.put_resp_header(conn, "X-Sentry-Error", "Creation of this event was denied due to rate limiting.") + conn + |> Plug.Conn.put_resp_header("X-Sentry-Error", "Creation of this event was denied due to rate limiting.") |> Plug.Conn.resp(400, "Something bad happened") end diff --git a/test/support/test_client.ex b/test/support/test_client.ex index bc24993e..99145b76 100644 --- a/test/support/test_client.ex +++ b/test/support/test_client.ex @@ -1,6 +1,6 @@ defmodule Sentry.TestClient do def send_event(%Sentry.Event{} = event) do - {endpoint, _public_key, _secret_key} = Sentry.Client.parse_dsn!(Application.fetch_env!(:sentry, :dsn)) + {endpoint, _public_key, _secret_key} = Sentry.Client.get_dsn! body = Poison.encode!(event) Sentry.Client.request(:post, endpoint, [], body) end