Skip to content

Commit 9d87140

Browse files
committed
check system and dsn query string
1 parent 74e9fba commit 9d87140

File tree

6 files changed

+136
-36
lines changed

6 files changed

+136
-36
lines changed

lib/sentry/client.ex

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ defmodule Sentry.Client do
175175
@spec get_dsn! :: get_dsn
176176
def get_dsn! do
177177
# {PROTOCOL}://{PUBLIC_KEY}:{SECRET_KEY}@{HOST}/{PATH}{PROJECT_ID}
178-
%URI{userinfo: userinfo, host: host, port: port, path: path, scheme: protocol} = URI.parse(fetch_dsn())
178+
%URI{userinfo: userinfo, host: host, port: port, path: path, scheme: protocol} = URI.parse(Config.dsn())
179179
[public_key, secret_key] = String.split(userinfo, ":", parts: 2)
180180
[_, binary_project_id] = String.split(path, "/")
181181
project_id = String.to_integer(binary_project_id)
@@ -216,13 +216,6 @@ defmodule Sentry.Client do
216216
@hackney_pool_name
217217
end
218218

219-
defp fetch_dsn do
220-
case Application.fetch_env!(:sentry, :dsn) do
221-
{:system, env_var} -> System.get_env(env_var)
222-
value -> value
223-
end
224-
end
225-
226219
defp log_api_error(body) do
227220
Logger.warn(fn ->
228221
["Failed to send Sentry event.", ?\n, body]

lib/sentry/config.ex

Lines changed: 92 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
defmodule Sentry.Config do
2-
32
@moduledoc """
43
This module provides the functionality for fetching configuration settings and their defaults.
54
"""
@@ -16,79 +15,149 @@ defmodule Sentry.Config do
1615
def validate_config! do
1716
end
1817

18+
def dsn do
19+
get_config(:dsn, check_dsn: false)
20+
end
21+
1922
def included_environments do
20-
Application.get_env(:sentry, :included_environments, @default_included_environments)
23+
get_config(:included_environments, default: @default_included_environments, check_dsn: false)
2124
end
2225

2326
def environment_name do
24-
Application.get_env(:sentry, :environment_name, @default_environment_name)
27+
get_config(:environment_name, default: @default_environment_name)
2528
end
2629

2730
def max_hackney_connections do
28-
Application.get_env(:sentry, :hackney_pool_max_connections, @default_max_hackney_connections)
31+
get_config(:hackney_pool_max_connections, default: @default_max_hackney_connections, check_dsn: false)
2932
end
3033

3134
def hackney_timeout do
32-
Application.get_env(:sentry, :hackney_pool_timeout, @default_hackney_timeout)
35+
get_config(:hackney_pool_timeout, default: @default_hackney_timeout, check_dsn: false)
3336
end
3437

3538
def tags do
36-
Application.get_env(:sentry, :tags, %{})
39+
get_config(:tags, default: %{}, check_dsn: false)
3740
end
3841

3942
def release do
40-
Application.get_env(:sentry, :release)
43+
get_config(:release)
4144
end
4245

4346
def server_name do
44-
Application.get_env(:sentry, :server_name)
47+
get_config(:server_name)
4548
end
4649

4750
def filter do
48-
Application.get_env(:sentry, :filter, Sentry.DefaultEventFilter)
51+
get_config(:filter, default: Sentry.DefaultEventFilter, check_dsn: false)
4952
end
5053

5154
def client do
52-
Application.get_env(:sentry, :client, Sentry.Client)
55+
get_config(:client, default: Sentry.Client, check_dsn: false)
5356
end
5457

5558
def use_error_logger do
56-
Application.get_env(:sentry, :use_error_logger, false)
59+
get_config(:use_error_logger, default: false, check_dsn: false)
5760
end
5861

59-
def root_path do
60-
Application.fetch_env!(:sentry, :root_source_code_path)
62+
def root_source_code_path do
63+
path = get_config(:root_source_code_path)
64+
65+
if path do
66+
path
67+
else
68+
raise ArgumentError.exception(":root_source_code_path must be configured")
69+
end
6170
end
6271

63-
def path_pattern do
64-
Application.get_env(:sentry, :source_code_path_pattern, @default_path_pattern)
72+
def source_code_path_pattern do
73+
get_config(:source_code_path_pattern, default: @default_path_pattern)
6574
end
6675

67-
def exclude_patterns do
68-
Application.get_env(:sentry, :source_code_exclude_patterns, @default_exclude_patterns)
76+
def source_code_exclude_patterns do
77+
get_config(:source_code_exclude_patterns, default: @default_exclude_patterns, check_dsn: false)
6978
end
7079

7180
def context_lines do
72-
Application.get_env(:sentry, :context_lines, @default_context_lines)
81+
get_config(:context_lines, default: @default_context_lines, check_dsn: false)
7382
end
7483

7584
def in_app_module_whitelist do
76-
Application.get_env(:sentry, :in_app_module_whitelist, [])
85+
get_config(:in_app_module_whitelist, default: [], check_dsn: false)
7786
end
7887

7988
def sample_rate do
80-
Application.get_env(:sentry, :sample_rate, @default_sample_rate)
89+
get_config(:sample_rate, default: @default_sample_rate, check_dsn: false)
8190
end
8291

8392
def hackney_opts do
84-
Application.get_env(:sentry, :hackney_opts, [])
93+
get_config(:hackney_opts, default: [], check_dsn: false)
8594
end
8695

8796
def before_send_event do
88-
Application.get_env(:sentry, :before_send_event)
97+
get_config(:before_send_event, check_dsn: false)
8998
end
9099

91100
def after_send_event do
92-
Application.get_env(:sentry, :after_send_event)
101+
get_config(:after_send_event, check_dsn: false)
102+
end
103+
104+
defp get_config(key, opts \\ []) when is_atom(key) do
105+
default = Keyword.get(opts, :default)
106+
check_dsn = Keyword.get(opts, :check_dsn, true)
107+
108+
environment_result = case get_from_application_environment(key) do
109+
{:ok, value} -> {:ok, value}
110+
:not_found -> get_from_system_environment(config_key_to_system_environment_key(key))
111+
end
112+
113+
result = case environment_result do
114+
{:ok, value} -> {:ok, value}
115+
:not_found -> if(check_dsn, do: get_from_dsn_query_string(Atom.to_string(key)), else: :not_found)
116+
end
117+
118+
case result do
119+
{:ok, value} -> value
120+
:not_found -> default
121+
end
122+
end
123+
124+
defp get_from_application_environment(key) when is_atom(key) do
125+
case Application.fetch_env(:sentry, key) do
126+
{:ok, {:system, env_var}} -> get_from_system_environment(env_var)
127+
{:ok, value} -> {:ok, value}
128+
:error -> :not_found
129+
end
130+
end
131+
132+
defp get_from_system_environment(key) when is_binary(key) do
133+
case System.get_env(key) do
134+
nil -> :not_found
135+
value -> {:ok, value}
136+
end
137+
end
138+
139+
defp get_from_dsn_query_string(key) when is_binary(key) do
140+
sentry_dsn = dsn()
141+
142+
if sentry_dsn do
143+
%URI{query: query} = URI.parse(sentry_dsn)
144+
query = query || ""
145+
result = URI.decode_query(query)
146+
|> Map.fetch(key)
147+
148+
case result do
149+
{:ok, value} -> {:ok, value}
150+
:error -> :not_found
151+
end
152+
else
153+
:not_found
154+
end
155+
end
156+
157+
defp config_key_to_system_environment_key(key) when is_atom(key) do
158+
string_key = Atom.to_string(key)
159+
|> String.upcase
160+
161+
"SENTRY_#{string_key}"
93162
end
94163
end

lib/sentry/sources.ex

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,9 @@ defmodule Sentry.Sources do
5151
@type source_map :: %{String.t => file_map}
5252

5353
def load_files do
54-
root_path = Config.root_path()
55-
path_pattern = Config.path_pattern()
56-
exclude_patterns = Config.exclude_patterns()
54+
root_path = Config.root_source_code_path()
55+
path_pattern = Config.source_code_path_pattern()
56+
exclude_patterns = Config.source_code_exclude_patterns()
5757

5858
Path.join(root_path, path_pattern)
5959
|> Path.wildcard()

test/client_test.exs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ defmodule Sentry.ClientTest do
1919

2020
test "get dsn with system config" do
2121
modify_env(:sentry, [dsn: {:system, "SYSTEM_KEY"}])
22-
System.put_env("SYSTEM_KEY", "https://public:[email protected]/1")
22+
modify_system_env(%{"SYSTEM_KEY" => "https://public:[email protected]/1"})
23+
2324
assert {"https://app.getsentry.com:443/api/1/store/", "public", "secret"} = Sentry.Client.get_dsn!
24-
System.delete_env("SYSTEM_KEY")
2525
end
2626

2727
test "logs api errors" do

test/config_test.exs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
defmodule Sentry.ConfigTest do
2+
use ExUnit.Case
3+
import Sentry.TestEnvironmentHelper
4+
alias Sentry.Config
5+
6+
test "retrieves from application environment" do
7+
modify_env(:sentry, dsn: "https://public:[email protected]/1")
8+
9+
assert "https://public:[email protected]/1" == Config.dsn()
10+
end
11+
12+
test "retrieves from system environment" do
13+
modify_system_env(%{"SENTRY_DSN" => "https://public:[email protected]/1"})
14+
15+
assert "https://public:[email protected]/1" == Config.dsn()
16+
end
17+
18+
test "retrieves from DSN query string" do
19+
modify_env(:sentry, dsn: "https://public:[email protected]/2?server_name=my_server")
20+
21+
assert "my_server" == Config.server_name()
22+
end
23+
end

test/support/test_environment_helper.ex

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,19 @@ defmodule Sentry.TestEnvironmentHelper do
1313
end
1414
end)
1515
end
16+
17+
def modify_system_env(overrides) when is_map(overrides) do
18+
original_env = System.get_env()
19+
System.put_env(overrides)
20+
21+
ExUnit.Callbacks.on_exit(fn ->
22+
Enum.each overrides, fn {key, _} ->
23+
if Map.has_key?(original_env, key) do
24+
System.put_env(key, Map.fetch!(original_env, key))
25+
else
26+
System.delete_env(key)
27+
end
28+
end
29+
end)
30+
end
1631
end

0 commit comments

Comments
 (0)