View Source ReqTelemetry (ReqTelemetry v0.0.4)

Req plugin to instrument requests with :telemetry events.

Usage

Preferably, ReqTelemetry should be the last plugin attached to your %Req.Request{}. This allows ReqTelemetry to emit events both at the very start and very end of the request and response pipelines. In this way, you can observe both the total time spent issuing and processing the request and response, as well as the time spent only with the request adapter.

req = Req.new() |> ReqTelemetry.attach()

req =
  Req.new(adapter: &my_adapter/1)
  |> ReqSomeOtherThing.attach()
  |> ReqTelemetry.attach()

Events

ReqTelemetry produces the following events (in order of event dispatch):

  • [:req, :request, :pipeline, :start]
  • [:req, :request, :adapter, :start]
  • [:req, :request, :adapter, :stop]
  • [:req, :request, :adapter, :error]
  • [:req, :request, :pipeline, :stop]
  • [:req, :request, :pipeline, :error]

You can configure ReqTelemetry to produce only :pipeline or :adapter events; see ReqTelemetry.attach/2 for options.

Logging

ReqTelemetry defines a a simple, default logger that logs basic request information and timing.

Here's how a successful request might be logged:

Req:479128347 - GET https://example.org (pipeline)
Req:479128347 - GET https://example.org (adapter)
Req:479128347 - 200 in 403ms (adapter)
Req:479128347 - 200 in 413ms (pipeline)

For usage and configuration, see ReqTelemetry.attach_default_logger/1.

Summary

Functions

Installs request, response, and error steps that emit :telemetry events.

Attach a basic telemetry event handler that logs ReqTelemetry events.

Returns a list of events emitted by ReqTelemetry.

Types

@type option() :: {:adapter, boolean()} | {:pipeline, boolean()} | {:metadata, map()}
@type options() :: boolean() | [option()]

Functions

@spec attach(Req.Request.t(), options()) :: Req.Request.t()

Installs request, response, and error steps that emit :telemetry events.

Options

  • :pipeline (default true) - emit pipeline telemetry events
  • :adapter (default true) - emit adapter telemetry events
  • :metadata (default nil) - map of user-supplied metadata available in telemetry handlers

As a shortcut, all events can be suppressed by passing false instead of an options list.

These same options can also be passed through Req options under the :telemetry key to change the behavior on a per-request basis. Maps of metadata will be merged. For example:

req = Req.new() |> ReqTelemetry.attach(metadata: %{api_version: 1})

Req.get!(req,
  url: "https://api.example.org/endpoint",
  telemetry: [metadata: %{endpoint: "endpoint"}]
)

# Your telemetry event handler will have access to the merged map
def handle_event(
  [:req, _, _, _],
  _measurements,
  %{metadata: %{api_version: v, endpoint: e}},
  _config
) do
  # ...
end

Examples

Emit all events by default, limiting them per-request as needed.

req = Req.new() |> ReqTelemetry.attach()

# Emits all events
Req.get!(req, url: "https://example.org")

# Do not emit events
Req.get!(req, url: "https://example.org", telemetry: false)

# Emit adapter events but not pipeline events
Req.get!(req, url: "https://example.org", telemetry: [pipeline: false])

Suppress all events by default, enabling them per-request as needed.

req = Req.new() |> ReqTelemetry.attach(false)

# Will not emit events
Req.get!(req, url: "https://example.org")

# Override to emit events
Req.get!(req, url: "https://example.org", telemetry: true)

# Override to emit only adapter events
Req.get!(req, url: "https://example.org", telemetry: [adapter: true])

Finally, suppress only a certain kind of event by default, overriding that default as needed.

req = Req.new() |> ReqTelemetry.attach(pipeline: false)

# Will only emit adapter events
Req.get!(req, url: "https://example.org")

# Override to emit only pipeline events
Req.get!(req, url: "https://example.org", telemetry: [pipeline: true, adapter: false])
Link to this function

attach_default_logger(kind_or_events \\ :all)

View Source
@spec attach_default_logger(
  :all
  | :adapter
  | :pipeline
  | [:telemetry.event_name(), ...]
) ::
  :ok | {:error, :already_exists}

Attach a basic telemetry event handler that logs ReqTelemetry events.

Usage

Telemetry event handlers can be attached in your application's start/2 callback:

@impl true
def start(_type, _args) do
  ReqTelemetry.attach_default_logger()

  children = [
    ...
  ]

  Supervisor.start_link(...)
end

All events are logged by default, but this can be overriden by passing in a keyword describing the kind of events to log or a list of specific events to log.

# Logs all events
:ok = ReqTelemetry.attach_default_logger()

# Logs only adapter events
:ok = ReqTelemetry.attach_default_logger(:adapter)

# Logs only pipeline errors
:ok = ReqTelemetry.attach_default_logger([[:req, :request, :pipeline, :error]])

Example

Here's what a successful request might 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)

And here's what an error might look like:

15:52:04.174 [error] Req:42446822 - ERROR in 2012ms (adapter)
%Finch.Error{reason: :request_timeout}
@spec events(:all | :pipeline | :adapter) :: [:telemetry.event_name(), ...]

Returns a list of events emitted by ReqTelemetry.