Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 15 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Plugsnag
# Plugsnag
![Elixir CI](https://github.com/bugsnag-elixir/plugsnag/workflows/Elixir%20CI/badge.svg)
[![Plugsnag version](https://img.shields.io/hexpm/v/plugsnag.svg)](https://hex.pm/packages/plugsnag)
[![Hex.pm](https://img.shields.io/hexpm/dt/plugsnag.svg)](https://hex.pm/packages/plugsnag)
Expand All @@ -17,29 +17,30 @@ Just throw it in your deps in your `mix.exs`:
```

Then you'll need to configure it with your API key as
per [the bugsnag-elixir
docs](https://github.com/jarednorman/bugsnag-elixir).
per [the bugsnag-elixir docs](https://github.com/jarednorman/bugsnag-elixir).

If you're using Elixir < 1.4 make sure that `plugsnag` and `bugsnag` apps are started in your mix.exs. If you are using Elixir 1.4, the applications will be automatically started because they are dependencies.

For example:
To use the plug, `use` it in your router. For example in an Phoenix app:

```elixir
def application do
[mod: {MyApp, []},
applications: [:logger, :plugsnag, :bugsnag]
]
end
defmodule YourApp.Router do
use Phoenix.Router
use Plugsnag

# ...
end
```

To use the plug, `use` it in your router. For example in an Phoenix app:
If you want to define your own `handle_errors` functions using [Plug.ErrorHandler](https://hexdocs.pm/plug/Plug.ErrorHandler.html), then you can call `Plugsnag.handle_errors/{2,3}` directly.

```elixir
defmodule YourApp.Router do
use Phoenix.Router
use Plugsnag

use Plug.ErrorHandler
# ...
defp handle_errors(conn, assigns) do
Plugsnag.handle_errors(conn, assigns)
# do your own handling
end
end
```

Expand Down
52 changes: 26 additions & 26 deletions lib/plugsnag.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,36 @@ defmodule Plugsnag do
quote location: :keep do
use Plug.ErrorHandler

defp handle_errors(conn, %{reason: exception, kind: :error} = assigns) do
# Only handle exceptions that get rendered as an HTTP 5xx status
if Plug.Exception.status(exception) >= 500 do
do_handle_errors(conn, assigns)
end
defp handle_errors(conn, assigns) do
Plugsnag.handle_errors(conn, assigns, unquote(options))
end
end
end

defp handle_errors(conn, %{reason: _exception} = assigns) do
do_handle_errors(conn, assigns)
end
def handle_errors(conn, assigns, opts \\ [])

def handle_errors(conn, %{reason: exception, kind: :error} = assigns, opts) do
# Only handle exceptions that get rendered as an HTTP 5xx status
if Plug.Exception.status(exception) >= 500 do
report_error(conn, assigns, opts)
end
end

defp do_handle_errors(conn, %{reason: exception}) do
error_report_builder =
unquote(
Keyword.get(
options,
:error_report_builder,
Plugsnag.BasicErrorReportBuilder
)
)
def handle_errors(conn, %{reason: _exception} = assigns, opts) do
report_error(conn, assigns, opts)
end

options =
%Plugsnag.ErrorReport{}
|> error_report_builder.build_error_report(conn)
|> Map.from_struct()
|> Keyword.new()
defp report_error(conn, %{reason: exception}, opts) do
error_report_builder =
Keyword.get(opts, :error_report_builder, Plugsnag.BasicErrorReportBuilder)

reporter = Application.get_env(:plugsnag, :reporter, Bugsnag)
apply(reporter, :report, [exception | [options]])
end
end
options =
%Plugsnag.ErrorReport{}
|> error_report_builder.build_error_report(conn)
|> Map.from_struct()
|> Keyword.new()

reporter = Application.get_env(:plugsnag, :reporter, Bugsnag)
apply(reporter, :report, [exception | [options]])
end
end
29 changes: 27 additions & 2 deletions test/plugsnag_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@ defmodule PlugsnagTest do
defmacro __using__(_env) do
quote do
def call(conn, _opts) do
{:current_stacktrace, [_ | stacktrace]} = Process.info(self(), :current_stacktrace)

raise Plug.Conn.WrapperError,
conn: conn,
kind: :error,
stack: System.stacktrace(),
stack: stacktrace,
reason: TestException.exception([])
end
end
Expand All @@ -28,10 +30,12 @@ defmodule PlugsnagTest do
defmacro __using__(_env) do
quote do
def call(conn, _opts) do
{:current_stacktrace, [_ | stacktrace]} = Process.info(self(), :current_stacktrace)

raise Plug.Conn.WrapperError,
conn: conn,
kind: :error,
stack: System.stacktrace(),
stack: stacktrace,
reason: NotFoundException.exception([])
end
end
Expand Down Expand Up @@ -69,6 +73,27 @@ defmodule PlugsnagTest do
assert_received {:report, {%TestException{}, _}}
end

test "calling Plugsnag.handle_errors explicitly" do
defmodule ExtendedPlug do
use Plug.ErrorHandler
use ErrorRaisingPlug

defp handle_errors(conn, %{reason: _exception} = assigns) do
send(self(), :custom_handle)
Plugsnag.handle_errors(conn, assigns)
end
end

conn = conn(:get, "/")

assert_raise Plug.Conn.WrapperError, "** (PlugsnagTest.TestException) oops", fn ->
ExtendedPlug.call(conn, [])
end

assert_received :custom_handle
assert_received {:report, {%TestException{}, _}}
end

test "includes connection metadata in the report" do
conn = conn(:get, "/?hello=computer")

Expand Down