Plug Integration
View SourcePlug
integration is the most common "addon" for
logging
libraries
by
far.
There are two reasons for this.
1. Metadata
Plug.Conn
is a treasure trove of useful metadata that makes understanding
errors much easier. Even basic information like request path and user-agent can
make a huge difference in debugging. To take advantage of this rich context and
save developers effort, logging libraries typically provide a plug module that
you can drop into your router. This plug automatically extracts relevant
connection data and adds it to logger metadata. Any errors logged later in the
same process will inherit this context.
2. Error Handling
Setting metadata from conn
is straightforward, why do a lot of Plug
integration modules consist largely of macros?
For a long time, Cowboy
was the web server for Elixir applications, and it
has one significant quirk: Cowboy logs errors from a different process than the
one that actually handled the request. Remember our earlier point?
Any errors logged later in the same process will inherit this context.
Well, for Cowboy errors, all the lovely metadata will be gone. That's why Plug
integration modules use macros: they wrap plug execution in a way that allows
them to log the error themselves while in the process with access to metadata.
And this is also the reason why virtually every library excludes logs coming
from the :cowboy
domain - that is, to avoid duplicates.
These days, custom error handling is hardly necessary. Bandit
web server is
the new default and it executes requests and logs errors in the same process.
But the Cowboy situation is better too. Plug.Cowboy
adapter comes with a
translator that ensures the conn
struct is available in the log metadata, so a
logger handler can extract all the metadata from it again.
Testing
LoggerHandlerKit comes with a LoggerHandlerKit.Act.plug_error/3
test case to
help you check how plug errors will look when logged by your handler.