Every wait performed by WaitForIt is instrumented with :telemetry
events, so you can observe waiting in production: how long waits take, how many evaluations they
need, and how often they time out.
Events
WaitForIt emits a standard telemetry span under the [:wait_for_it, :wait] prefix.
[:wait_for_it, :wait, :start]
Emitted when a wait begins.
- Measurements:
%{system_time, monotonic_time} - Metadata:
%{wait_type, timeout, interval, signal, env}
[:wait_for_it, :wait, :stop]
Emitted when a wait finishes — whether the waiting condition was met or the wait timed out.
- Measurements:
%{duration, evaluations}durationis in native time units (useSystem.convert_time_unit/3to convert).evaluationsis the number of times the waitable expression was evaluated.
- Metadata:
%{wait_type, timeout, interval, signal, env, result, last_value}resultis:matched(the condition was met) or:timeout.
[:wait_for_it, :wait, :exception]
Emitted only if evaluating the waitable expression raises, throws, or exits unexpectedly. A
timeout is not an exception: it is reported as a :stop event with result: :timeout.
- Measurements:
%{duration} - Metadata:
%{wait_type, timeout, interval, signal, env, kind, reason, stacktrace}
Attaching a handler
:telemetry.attach_many(
"wait-for-it-logger",
[
[:wait_for_it, :wait, :stop],
[:wait_for_it, :wait, :exception]
],
&MyApp.WaitForItHandler.handle_event/4,
nil
)defmodule MyApp.WaitForItHandler do
require Logger
def handle_event([:wait_for_it, :wait, :stop], measurements, metadata, _config) do
ms = System.convert_time_unit(measurements.duration, :native, :millisecond)
Logger.info(
"WaitForIt #{metadata.wait_type} #{metadata.result} after #{ms}ms " <>
"(#{measurements.evaluations} evaluations)"
)
end
def handle_event([:wait_for_it, :wait, :exception], _measurements, metadata, _config) do
Logger.error("WaitForIt #{metadata.wait_type} crashed: #{inspect(metadata.reason)}")
end
endUsing Telemetry.Metrics
The events compose with Telemetry.Metrics for
dashboards and reporters. For example:
import Telemetry.Metrics
[
# Distribution of wait durations, tagged by the form of waiting and the outcome.
distribution("wait_for_it.wait.stop.duration",
unit: {:native, :millisecond},
tags: [:wait_type, :result]
),
# How many evaluations waits needed — useful for tuning :interval.
summary("wait_for_it.wait.stop.evaluations", tags: [:wait_type]),
# Count of timeouts vs matches.
counter("wait_for_it.wait.stop.duration", tags: [:wait_type, :result])
]Because metadata includes result, you can alert on a rising rate of result: :timeout for a
given wait_type — an early signal that a dependency is getting slow.
Previous: Recipes
That's the end of the guides. See the WaitForIt module for the complete API reference.