Blunder.Absinthe
Package for simplifying error representation and handling in an Absinthe application using Blunder
Usage
Add Blunder to your Absinthe Middleware Stack
Add Blunder error handling to your resolvers by letting Blunder wrap your middleware. You can do this by implementing the middleware callback in your schema like this:
def middleware(middleware, _field, _object) do
Blunder.Absinthe.add_error_handling(middleware)
end
This will catch all exceptions as well as provide special handling for any %Blunder{}
errors returned from resolver functions.
Start returning Blunder Errors
Now that the middleware is installed you can return {:error, %Blunder{}}
from your resolvers when there is an error. This gives you a lot more expressiveness than {:error, "error string"}
. The %Blunder{}
struct has the following properties you can set.
code
- An atom describing the error in a machine-readable way. Defaults to:application_error
summary
- Displayed to the client in graphql errorsdetails
- Hidden from the client in graphql errors (by default), but can be logged, etcseverity
- Can be used to determine what to log or alert onstacktrace
- Allows you to attach a stacktrace to the error,nil
by defaultoriginal_error
- The original error if this Blunder error is wrapping a lower-level exception
In order to simplify the creation of these error structs you’re encouraged to create an Errors
module in your app that exports functions for creating Blunder errors. This serves as a conveniance as well as a central place to document error types. Blunder provides the deferror
macro in Blunder.Errors
to make this easier.
defmodule MyApp.Errors do
import Blunder.Errors
deferror :flagrant_system_error,
message: "MUCH ERRORZ!",
severity: :critical
deferror :boring_error, message: "whatevs"
end
defmodule MyApp.DoTheWork do
import MyApp.Errors
def add(x, y) do
case get_system_status do
:server_is_on_fire -> {:error, flagrant_system_error()},
:server_is_le_tired -> {:error, boring_error()},
:server_ready_to_work -> {:ok, x + y},
end
end
end
Handle Errors In Your Absinthe Schema
Now that you’ve got all of your errors normalized into a common format and being handled in a central place in the Absinthe middleware, you probably want to do something with them. This is where the ErrorHandler
comes in. You can create any number of ErrorHander
modules, register them with Blunder
in your config, and every error will get passed to every handler asynchonously.
Creating an error handler is as simple as this:
defmodule LogError do
use Blunder.Absinthe.ErrorHandler
require Logger
@impl Blunder.Absinthe.ErrorHandler
def call(blunder) do
Logger.error blunder.message
end
end
Then in your config…
config :blunder, error_handlers: [ LogError ]
Blunder ships with Error Handlers for BugSnag and logging that you can use right out of the box.