CityBaseInc / airbrake_client

Airbrake client to report errors and exceptions to Airbrake.io.
Other
0 stars 1 forks source link

BUG: default stacktrace for Airbrake.report/2 is a tuple, not a list #14

Closed jdfrens closed 3 years ago

jdfrens commented 3 years ago

Making a simple call to Airbrake.report/2 without a stacktrace is broken. You can see an example of the failure below.

The problem is that the default stacktrace is created by Process.info(self(), :current_stacktrace) which returns a tuple {:current_stacktrace, stacktrace} where stacktrace is a list (as __STACKTRACE__ would evaluate to in a rescue clause).

The solution is simple: pattern match on the tuple and return just the stacktrace.

Failure Example

iex(2)> Airbrake.report(
...(1)>   [type: "TestingError", message: "Testing Airbrake.report/2"],
...(1)>   context: %{
...(1)>     foo: "bar",
...(1)>     now: "America/Chicago" |> DateTime.now!() |> inspect()
...(1)>   },
...(1)>   params: %{foo: 6},
...(1)>   session: %{foo: 9},
...(1)>   env: %{foo: 10}
)
14:30:02.011 [error] GenServer Airbrake.Worker terminating
** (Protocol.UndefinedError) protocol Enumerable not implemented for {:current_stacktrace, [{Process, :info, 2, [file: 'lib/process.ex', line: 766]}, {Airbrake.Worker, :report, 2, [file: 'lib/airbrake/worker.ex', line: 28]}, {:erl_eval, :do_apply, 6, [file: 'erl_eval.erl', line: 680]}, {:elixir, :recur_eval, 3, [file: 'src/elixir.erl', line: 280]}, {:elixir, :eval_forms, 3, [file: 'src/elixir.erl', line: 265]}, {IEx.Evaluator, :handle_eval, 5, [file: 'lib/iex/evaluator.ex', line: 261]}, {IEx.Evaluator, :do_eval, 3, [file: 'lib/iex/evaluator.ex', line: 242]}, {IEx.Evaluator, :eval, 3, [file: 'lib/iex/evaluator.ex', line: 220]}]} of type Tuple. This protocol is implemented for the following type(s): Ecto.Adapters.SQL.Stream, Postgrex.Stream, DBConnection.Stream, DBConnection.PrepareStream, Timex.Interval, StreamData, HashSet, Range, Map, Function, List, Stream, Date.Range, HashDict, GenEvent.Stream, MapSet, File.Stream, IO.Stream
    (elixir 1.11.4) lib/enum.ex:1: Enumerable.impl_for!/1
    (elixir 1.11.4) lib/enum.ex:141: Enumerable.reduce/3
    (elixir 1.11.4) lib/enum.ex:3473: Enum.map/2
    (airbrake_client 0.9.0) lib/airbrake/payload.ex:43: Airbrake.Payload.add_exception_info/3
    (airbrake_client 0.9.0) lib/airbrake/payload.ex:32: Airbrake.Payload.add_error/7
    (airbrake_client 0.9.0) lib/airbrake/worker.ex:104: Airbrake.Worker.send_report/3
    (airbrake_client 0.9.0) lib/airbrake/worker.ex:80: Airbrake.Worker.handle_cast/2
    (stdlib 3.14.1) gen_server.erl:689: :gen_server.try_dispatch/4
Last message: {:"$gen_cast", {:report, [type: "TestingError", message: "Testing Airbrake.report/2"], {:current_stacktrace, [{Process, :info, 2, [file: 'lib/process.ex', line: 766]}, {Airbrake.Worker, :report, 2, [file: 'lib/airbrake/worker.ex', line: 28]}, {:erl_eval, :do_apply, 6, [file: 'erl_eval.erl', line: 680]}, {:elixir, :recur_eval, 3, [file: 'src/elixir.erl', line: 280]}, {:elixir, :eval_forms, 3, [file: 'src/elixir.erl', line: 265]}, {IEx.Evaluator, :handle_eval, 5, [file: 'lib/iex/evaluator.ex', line: 261]}, {IEx.Evaluator, :do_eval, 3, [file: 'lib/iex/evaluator.ex', line: 242]}, {IEx.Evaluator, :eval, 3, [file: 'lib/iex/evaluator.ex', line: 220]}]}, [context: %{foo: "bar", now: "#DateTime<2021-06-04 14:30:02.010743-05:00 CDT America/Chicago>"}, params: %{foo: 6}, session: %{foo: 9}, env: %{foo: 10}]}}
State: %Airbrake.Worker.State{last_exception: nil, refs: %{}}