Welcome to error-context! This is a library providing context-aware
error and exception handling for Haskell. It has built-in support for
the Katip logging
package. This means that
in combination with Katip, error-context can transparently use the
context (key-value pairs and namespace hierarchy) maintained by
KatipContext
monads.
Good error handling is hard. In the case of failures it is important to keep as much context as necessary for a proper problem analysis. Call traces sometimes help, but the current solutions in Haskell-land for accessing call traces are rather limited.
The error-context library allows you to easily attach call traces
('error contexts') to errors, in particular to exceptions. Special
catch
- and try
-functions are provided for accessing these
contexts.
Add an ErrorContextT
layer to your monad transformer stack by adding
runErrorContextT
to the transformer unwrapping code.
The ErrorContextT
transformer provides the context-enriching logic
via special implementations of MonadThrow
, MonadCatch
and
MonadIO
.
Consider this IO action:
testExample :: IO ()
testExample = do
Left errWithCtx :: Either (ErrorWithContext SomeException) () <- try . runErrorContextT $
withErrorNamespace "middle-earth" $
withErrorNamespace "mordor" $
withErrorContext "ring-carrier" ("Frodo" :: Text) $
throwM TestException
putStrLn . displayException $ errWithCtx
When run, it produces the following output:
Exception: TestException
ring-carrier: "Frodo"
caused by: mordor
caused by: middle-earth
For more examples, see https://github.com/mtesseract/error-context/blob/master/test/Control/Error/Context/Test.hs.
The ErrorContextT
transformer implements MonadThrow
and MonadIO
,
therefore exceptions thrown by throwM
and via liftIO
are
automatically context-enriched. On the other hand, exceptional values
created via
throw :: Exception e => e -> a
are not context-enriched per se. But there is a workaround for this use-case:
ensureExceptionContext :: (MonadCatch m, MonadErrorContext m) => m a -> m a
This function provides context-aware enriching for any exceptions
thrown within some monadic value, including those thrown by evaluating
values created by throw
.