Req plugin to instrument requests using Telemetry - request for feedback!

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

2 Likes