Skip to content

Commit 2733e70

Browse files
Merge pull request #214 from getsentry/mfa-fix
Fix Culprit ambiguity
2 parents 9cdfaac + 92cd150 commit 2733e70

File tree

8 files changed

+61
-29
lines changed

8 files changed

+61
-29
lines changed

lib/sentry/event.ex

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ defmodule Sentry.Event do
9999
server_name: server_name,
100100
exception: exception,
101101
stacktrace: %{
102-
frames: stacktrace_to_frames(stacktrace)
102+
frames: stacktrace_to_frames(stacktrace),
103103
},
104104
release: release,
105105
extra: extra,
@@ -170,8 +170,9 @@ defmodule Sentry.Event do
170170
in_app_module_whitelist = Config.in_app_module_whitelist()
171171
stacktrace
172172
|> Enum.map(fn(line) ->
173-
{mod, function, arity, location} = line
174-
arity = arity_to_integer(arity)
173+
{mod, function, arity_or_args, location} = line
174+
f_args = args_from_stacktrace([line])
175+
arity = arity_to_integer(arity_or_args)
175176
file = Keyword.get(location, :file)
176177
file = if(file, do: String.Chars.to_string(file), else: file)
177178
line_number = Keyword.get(location, :line)
@@ -182,6 +183,7 @@ defmodule Sentry.Event do
182183
module: mod,
183184
lineno: line_number,
184185
in_app: is_in_app?(mod, in_app_module_whitelist),
186+
vars: f_args,
185187
}
186188
|> put_source_context(file, line_number)
187189
end)
@@ -202,7 +204,24 @@ defmodule Sentry.Event do
202204

203205
@spec culprit_from_stacktrace(Exception.stacktrace) :: String.t | nil
204206
def culprit_from_stacktrace([]), do: nil
205-
def culprit_from_stacktrace([{m, f, a, _} | _]), do: Exception.format_mfa(m, f, a)
207+
def culprit_from_stacktrace([{m, f, a, _} | _]) do
208+
Exception.format_mfa(m, f, arity_to_integer(a))
209+
end
210+
211+
@doc """
212+
Builds a map from argument value list. For Sentry, typically the
213+
key in the map would be the name of the variable, but we don't have that
214+
available.
215+
"""
216+
@spec args_from_stacktrace(Exception.stacktrace) :: String.t | nil
217+
def args_from_stacktrace([{_m, _f, a, _} | _]) when is_list(a) do
218+
Enum.with_index(a)
219+
|> Enum.map(fn({arg, index}) ->
220+
{"arg#{index}", inspect(arg)}
221+
end)
222+
|> Enum.into(%{})
223+
end
224+
def args_from_stacktrace(_), do: %{}
206225

207226
defp arity_to_integer(arity) when is_list(arity), do: Enum.count(arity)
208227
defp arity_to_integer(arity) when is_integer(arity), do: arity

mix.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ defmodule Sentry.Mixfile do
3232
{:dialyxir, "> 0.0.0", only: :dev},
3333
{:ex_doc, "~> 0.16.0", only: :dev},
3434
{:credo, "~> 0.8", only: [:dev, :test], runtime: false},
35-
{:bypass, "~> 0.7.0", only: [:test]}
35+
{:bypass, "~> 0.8.0", only: [:test]}
3636
]
3737
end
3838

mix.lock

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
%{"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], []},
2-
"bypass": {:hex, :bypass, "0.7.0", "591d2ac1d87ba1bb84f62656a79de2fe3909993a211021a881825b59c9f7f58f", [:mix], [{:cowboy, "~> 1.0", [hex: :cowboy, optional: false]}, {:plug, "~> 1.0", [hex: :plug, optional: false]}]},
2+
"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"},
33
"certifi": {:hex, :certifi, "1.1.0", "c9b71a547016c2528a590ccfc28de786c7edb74aafa17446b84f54e04efc00ee", [:rebar3], []},
44
"cowboy": {:hex, :cowboy, "1.1.2", "61ac29ea970389a88eca5a65601460162d370a70018afe6f949a29dca91f3bb0", [:rebar3], [{:cowlib, "~> 1.0.2", [hex: :cowlib, optional: false]}, {:ranch, "~> 1.3.2", [hex: :ranch, optional: false]}]},
55
"cowlib": {:hex, :cowlib, "1.0.2", "9d769a1d062c9c3ac753096f868ca121e2730b9a377de23dec0f7e08b1df84ee", [:make], []},
@@ -12,7 +12,7 @@
1212
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], []},
1313
"mime": {:hex, :mime, "1.1.0", "01c1d6f4083d8aa5c7b8c246ade95139620ef8effb009edde934e0ec3b28090a", [:mix], []},
1414
"mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [:rebar3], []},
15-
"plug": {:hex, :plug, "1.3.5", "7503bfcd7091df2a9761ef8cecea666d1f2cc454cbbaf0afa0b6e259203b7031", [:mix], [{:cowboy, "~> 1.0.1 or ~> 1.1", [hex: :cowboy, optional: true]}, {:mime, "~> 1.0", [hex: :mime, optional: false]}]},
15+
"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"},
1616
"poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], []},
1717
"ranch": {:hex, :ranch, "1.3.2", "e4965a144dc9fbe70e5c077c65e73c57165416a901bd02ea899cfd95aa890986", [:rebar3], []},
1818
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.1", "28a4d65b7f59893bc2c7de786dec1e1555bd742d336043fe644ae956c3497fbe", [:make, :rebar], []},

test/client_test.exs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,10 @@ defmodule Sentry.ClientTest do
5050
test "errors when attempting to report invalid JSON" do
5151
modify_env(:sentry, dsn: "http://public:secret@localhost:3000/1")
5252
unencodable_tuple = {:a, :b, :c}
53-
assert :error = Sentry.capture_message(unencodable_tuple)
53+
54+
capture_log(fn ->
55+
assert :error = Sentry.capture_message(unencodable_tuple)
56+
end)
5457
end
5558

5659
test "calls anonymous before_send_event" do

test/event_test.exs

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ defmodule Sentry.EventTest do
55

66
def event_generated_by_exception(extra \\ %{}) do
77
try do
8-
Event.not_a_function
8+
Event.not_a_function(1, 2, 3)
99
rescue
1010
e -> Event.transform_exception(e, [stacktrace: System.stacktrace, extra: extra])
1111
end
@@ -15,23 +15,24 @@ defmodule Sentry.EventTest do
1515
event = event_generated_by_exception()
1616

1717
assert event.platform == "elixir"
18-
assert event.culprit == "Sentry.Event.not_a_function()"
18+
assert event.culprit == "Sentry.Event.not_a_function/3"
1919
assert event.extra == %{}
2020
assert event.exception == [
2121
%{type: UndefinedFunctionError,
22-
value: "function Sentry.Event.not_a_function/0 is undefined or private",
22+
value: "function Sentry.Event.not_a_function/3 is undefined or private",
2323
module: nil}
2424
]
2525
assert event.level == "error"
26-
assert event.message == "(UndefinedFunctionError) function Sentry.Event.not_a_function/0 is undefined or private"
26+
assert event.message == "(UndefinedFunctionError) function Sentry.Event.not_a_function/3 is undefined or private"
2727
assert is_binary(event.server_name)
28-
assert event.stacktrace == %{frames: Enum.reverse([
29-
%{filename: nil, function: "Sentry.Event.not_a_function/0", lineno: nil, module: Sentry.Event, context_line: nil, post_context: [], pre_context: [], in_app: false},
30-
%{filename: "test/event_test.exs", function: "Sentry.EventTest.event_generated_by_exception/1", lineno: 8, module: Sentry.EventTest, context_line: nil, post_context: [], pre_context: [], in_app: false},
31-
%{filename: "test/event_test.exs", function: "Sentry.EventTest.\"test parses error exception\"/1", lineno: 15, module: Sentry.EventTest, context_line: nil, post_context: [], pre_context: [], in_app: false},
32-
%{filename: "lib/ex_unit/runner.ex", function: "ExUnit.Runner.exec_test/1", lineno: 302, module: ExUnit.Runner, context_line: nil, post_context: [], pre_context: [], in_app: false},
33-
%{filename: "timer.erl", function: ":timer.tc/1", lineno: 166, module: :timer, context_line: nil, post_context: [], pre_context: [], in_app: false},
34-
%{filename: "lib/ex_unit/runner.ex", function: "anonymous fn/3 in ExUnit.Runner.spawn_test/3", lineno: 250, module: ExUnit.Runner, context_line: nil, post_context: [], pre_context: [], in_app: false}])
28+
assert event.stacktrace == %{
29+
frames: Enum.reverse([
30+
%{filename: nil, function: "Sentry.Event.not_a_function/3", lineno: nil, module: Sentry.Event, context_line: nil, post_context: [], pre_context: [], in_app: false, vars: %{"arg0" => "1", "arg1" => "2", "arg2" => "3"}},
31+
%{filename: "test/event_test.exs", function: "Sentry.EventTest.event_generated_by_exception/1", lineno: 8, module: Sentry.EventTest, context_line: nil, post_context: [], pre_context: [], in_app: false, vars: %{}},
32+
%{filename: "test/event_test.exs", function: "Sentry.EventTest.\"test parses error exception\"/1", lineno: 15, module: Sentry.EventTest, context_line: nil, post_context: [], pre_context: [], in_app: false, vars: %{}},
33+
%{filename: "lib/ex_unit/runner.ex", function: "ExUnit.Runner.exec_test/1", lineno: 302, module: ExUnit.Runner, context_line: nil, post_context: [], pre_context: [], in_app: false, vars: %{}},
34+
%{filename: "timer.erl", function: ":timer.tc/1", lineno: 166, module: :timer, context_line: nil, post_context: [], pre_context: [], in_app: false, vars: %{}},
35+
%{filename: "lib/ex_unit/runner.ex", function: "anonymous fn/3 in ExUnit.Runner.spawn_test/3", lineno: 250, module: ExUnit.Runner, context_line: nil, post_context: [], pre_context: [], in_app: false, vars: %{}}])
3536
}
3637
assert event.tags == %{}
3738
assert event.timestamp =~ ~r/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/
@@ -83,34 +84,39 @@ defmodule Sentry.EventTest do
8384
event = Sentry.Event.transform_exception(exception, [stacktrace: [{Elixir.Sentry.Fun, :method, 2, []}, {Elixir.Sentry, :other_method, 4, []},
8485
{:other_module, :a_method, 8, []}, {:random, :uniform, 0, []},
8586
{Sentry.Submodule.Fun, :this_method, 0, []}]])
86-
assert %{frames: [
87+
assert %{
88+
frames: [
8789
%{
8890
module: Sentry.Submodule.Fun,
8991
function: "Sentry.Submodule.Fun.this_method/0",
9092
in_app: true,
9193
filename: nil, lineno: nil,
92-
context_line: nil, post_context: [], pre_context: []
94+
context_line: nil, post_context: [], pre_context: [],
95+
vars: %{},
9396
},
9497
%{
9598
module: :random,
9699
function: ":random.uniform/0",
97100
in_app: true,
98101
filename: nil, lineno: nil,
99-
context_line: nil, post_context: [], pre_context: []
102+
context_line: nil, post_context: [], pre_context: [],
103+
vars: %{},
100104
},
101105
%{
102106
module: :other_module,
103107
function: ":other_module.a_method/8",
104108
in_app: false,
105109
filename: nil, lineno: nil,
106-
context_line: nil, post_context: [], pre_context: []
110+
context_line: nil, post_context: [], pre_context: [],
111+
vars: %{},
107112
},
108113
%{
109114
module: Sentry,
110115
function: "Sentry.other_method/4",
111116
in_app: true,
112117
filename: nil, lineno: nil,
113-
context_line: nil, post_context: [], pre_context: []
118+
context_line: nil, post_context: [], pre_context: [],
119+
vars: %{},
114120
},
115121
%{
116122
filename: nil,
@@ -120,7 +126,8 @@ defmodule Sentry.EventTest do
120126
in_app: true,
121127
context_line: nil,
122128
post_context: [],
123-
pre_context: []
129+
pre_context: [],
130+
vars: %{},
124131
},
125132
]} == event.stacktrace
126133
end
@@ -129,9 +136,9 @@ defmodule Sentry.EventTest do
129136
exception = RuntimeError.exception("error")
130137
event = Sentry.Event.transform_exception(exception, [])
131138

132-
assert event.modules == %{bunt: "0.2.0", bypass: "0.7.0", certifi: "1.1.0", cowboy: "1.1.2",
139+
assert event.modules == %{bunt: "0.2.0", bypass: "0.8.1", certifi: "1.1.0", cowboy: "1.1.2",
133140
cowlib: "1.0.2", credo: "0.8.6", hackney: "1.8.0", idna: "4.0.0",
134-
metrics: "1.0.1", mime: "1.1.0", mimerl: "1.0.2", plug: "1.3.5",
141+
metrics: "1.0.1", mime: "1.1.0", mimerl: "1.0.2", plug: "1.4.3",
135142
poison: "3.1.0", ranch: "1.3.2", ssl_verify_fun: "1.1.1",
136143
uuid: "1.1.7"}
137144
end

test/logger_test.exs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ defmodule Sentry.LoggerTest do
9494
"context_line" => nil,
9595
"pre_context" => [],
9696
"post_context" => [],
97+
"vars" => %{"arg0" => "{}", "arg1" => "{0, 0}"}
9798
}
9899
assert conn.request_path == "/api/1/store/"
99100
assert conn.method == "POST"

test/plug_test.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ defmodule Sentry.PlugTest do
7575
request_data = Sentry.Plug.build_request_interface_data(conn, options)
7676
assert request_data[:method] == "POST"
7777
assert request_data[:data] == %{"hello" => "world"}
78-
assert request_data[:headers] == %{"cookie" => "cookie_key=cookie_value", "accept-language" => "en-US", "content-type" => "multipart/mixed; charset: utf-8"}
78+
assert request_data[:headers] == %{"cookie" => "cookie_key=cookie_value", "accept-language" => "en-US", "content-type" => "multipart/mixed; boundary=plug_conn_test"}
7979
assert request_data[:cookies] == %{"cookie_key" => "cookie_value"}
8080
end
8181

test/support/test_client.exs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
defmodule Sentry.TestClient do
22
@behaviour Sentry.HTTPClient
3+
require Logger
34

45
def send_event(%Sentry.Event{} = event, _opts \\ []) do
56
{endpoint, _public_key, _secret_key} = Sentry.Client.get_dsn!
67
event = Sentry.Client.maybe_call_before_send_event(event)
78
case Poison.encode(event) do
89
{:ok, body} ->
910
Sentry.Client.request(:post, endpoint, [], body)
10-
{:error, _error} ->
11+
{:error, error} ->
12+
Logger.error("Error sending in Sentry.TestClient: #{inspect(error)}")
1113
:error
1214
end
1315
end

0 commit comments

Comments
 (0)