Hey gang,
I’ve been using Req as my primary client for a project I’ve been working on that interacts with a number of APIs, and I quickly found myself wanting some kind of sane, default request logging. At first, I defaulted to a handful of custom steps and a :log
option, but recently found myself wanting a bit more granularity.
So, this morning, I banged out a quick plugin to instrument Req requests using Telemetry: ReqTelemetry
As with other Req plugins, it is implemented using request/response/error steps and is set up with an attach
function:
Req.new() |> ReqTelemetry.attach() |> Req.get(url: "https://example.org")
I am very much not an expert Telemetry user, so this was developed using a handful of existing Telemetry integrations for reference.
For posterity, at the time of writing this post, the plugin emits the following events:
[:req, :request, :pipeline, :start]
[:req, :request, :adapter, :start]
[:req, :request, :adapter, :stop]
[:req, :request, :adapter, :error]
[:req, :request, :pipeline, :stop]
[:req, :request, :pipeline, :error]
and ships with a default logger that can be installed in your application’s start/2
callback:
@impl true
def start(_type, _args) do
:ok = ReqTelemetry.attach_default_logger()
children = [...]
Supervisor.start_link(children, ...)
end
and logs messages that look like:
15:52:01.462 [info] Req:479128347 - GET https://example.org (pipeline)
15:52:01.466 [info] Req:479128347 - GET https://example.org (adapter)
15:52:01.869 [info] Req:479128347 - 200 in 403ms (adapter)
15:52:01.875 [info] Req:479128347 - 200 in 413ms (pipeline)
Additional examples and information can be found in the docs. I’d very much appreciate any feedback on any aspect of the library.
Cheers,
Zach