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:
As with other Req plugins, it is implemented using request/response/error steps and is set up with an
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
@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.