PropertyDamage.Telemetry (PropertyDamage v0.2.0)
View SourceTelemetry events for PropertyDamage test runs.
PropertyDamage emits telemetry events during test execution that can be used for monitoring, dashboards, and observability.
Events
All events are prefixed with [:property_damage, ...].
Run Lifecycle
[:property_damage, :run, :start]- Test run started- Measurements:
%{system_time: integer()} - Metadata:
%{model: module(), adapter: module(), max_runs: integer(), max_commands: integer(), seed: integer()}
- Measurements:
[:property_damage, :run, :stop]- Test run completed- Measurements:
%{duration: integer(), total_commands: integer()} Metadata:
%{model: module(), adapter: module(), result: :ok | :error, runs_completed: integer()}
- Measurements:
[:property_damage, :run, :exception]- Test run crashed- Measurements:
%{duration: integer()} - Metadata:
%{model: module(), adapter: module(), kind: atom(), reason: term(), stacktrace: list()}
- Measurements:
Sequence Execution
[:property_damage, :sequence, :start]- Sequence execution started- Measurements:
%{system_time: integer()} - Metadata:
%{run_number: integer(), command_count: integer(), branching: boolean()}
- Measurements:
[:property_damage, :sequence, :stop]- Sequence execution completed- Measurements:
%{duration: integer()} - Metadata:
%{run_number: integer(), success: boolean(), commands_executed: integer()}
- Measurements:
Command Execution
[:property_damage, :command, :start]- Command execution started- Measurements:
%{system_time: integer()} - Metadata:
%{command: module(), index: integer(), run_number: integer()}
- Measurements:
[:property_damage, :command, :stop]- Command execution completed- Measurements:
%{duration: integer()} - Metadata:
%{command: module(), index: integer(), success: boolean(), events_count: integer()}
- Measurements:
Check Execution
[:property_damage, :check, :start]- Check evaluation started- Measurements:
%{system_time: integer()} - Metadata:
%{check_name: atom(), projection: module()}
- Measurements:
[:property_damage, :check, :stop]- Check evaluation completed- Measurements:
%{duration: integer()} Metadata:
%{check_name: atom(), passed: boolean(), message: String.t() | nil}
- Measurements:
Shrinking
[:property_damage, :shrink, :start]- Shrinking started- Measurements:
%{system_time: integer()} - Metadata:
%{original_length: integer()}
- Measurements:
[:property_damage, :shrink, :iteration]- Shrink iteration completed- Measurements:
%{iteration: integer()} - Metadata:
%{current_length: integer(), success: boolean()}
- Measurements:
[:property_damage, :shrink, :stop]- Shrinking completed- Measurements:
%{duration: integer(), iterations: integer()} - Metadata:
%{original_length: integer(), shrunk_length: integer()}
- Measurements:
Progress (DR-022)
In addition to the fine-grained spans above, every long-running operation emits
a coarse progress/result heartbeat derived from the unified
PropertyDamage.Progress projection. For run/1 these are distinct from and
additional to the per-unit sequence/command/check/shrink spans: the
spans instrument each unit of work, the progress events are a campaign-level
heartbeat.
[:property_damage, :test_run, :progress]- An intermediate run update- Measurements:
%{at: integer(), elapsed_ms: non_neg_integer()} - Metadata:
%{data: PropertyDamage.Progress.RunUpdate.t(), run_id: term()}
- Measurements:
[:property_damage, :test_run, :result]- The terminal run result- Measurements:
%{at: integer(), elapsed_ms: non_neg_integer()} - Metadata:
%{data: PropertyDamage.Progress.RunResult.t(), run_id: term()}
- Measurements:
[:property_damage, :load_test, :progress]- A load-test metrics snapshot- Measurements:
%{at: integer(), elapsed_ms: non_neg_integer()} - Metadata:
%{data: PropertyDamage.Progress.LoadUpdate.t(), run_id: term()}
- Measurements:
[:property_damage, :load_test, :result]- The terminal load-test report- Measurements:
%{at: integer(), elapsed_ms: non_neg_integer()} - Metadata:
%{data: PropertyDamage.Progress.LoadResult.t(), run_id: term()}
- Measurements:
[:property_damage, :mutation, :progress]- A per-mutation update- Measurements:
%{at: integer(), elapsed_ms: non_neg_integer()} - Metadata:
%{data: PropertyDamage.Progress.MutationUpdate.t(), run_id: term()}
- Measurements:
[:property_damage, :mutation, :result]- The terminal mutation report- Measurements:
%{at: integer(), elapsed_ms: non_neg_integer()} - Metadata:
%{data: PropertyDamage.Progress.MutationResult.t(), run_id: term()}
- Measurements:
[:property_damage, :differential, :progress]- A differential run update- Measurements:
%{at: integer(), elapsed_ms: non_neg_integer()} - Metadata:
%{data: PropertyDamage.Progress.DifferentialUpdate.t(), run_id: term()}
- Measurements:
[:property_damage, :differential, :result]- The terminal differential result- Measurements:
%{at: integer(), elapsed_ms: non_neg_integer()} - Metadata:
%{data: PropertyDamage.Progress.DifferentialResult.t(), run_id: term()}
- Measurements:
These events fire only when a handler is attached for them, preserving the zero-cost-when-unobserved guarantee on the hot loop.
Usage
Attach handlers using :telemetry.attach/4:
:telemetry.attach(
"my-handler",
[:property_damage, :run, :stop],
&MyModule.handle_event/4,
nil
)Or use PropertyDamage.Telemetry.Dashboard for a pre-built LiveView dashboard.
Summary
Functions
Emit a check start event.
Emit a check stop event.
Emit a command start event.
Emit a command stop event.
Build a telemetry consumer for the unified progress projection (DR-022), or
nil when nothing is listening.
Emit a run exception event.
Emit a run start event.
Emit a run stop event.
Emit a sequence start event.
Emit a sequence stop event.
Emit a shrink iteration event.
Emit a shrink start event.
Emit a shrink stop event.
Execute a function with telemetry span instrumentation.
Functions
@spec check_start(map()) :: :ok
Emit a check start event.
Emit a check stop event.
@spec command_start(map()) :: :ok
Emit a command start event.
Emit a command stop event.
@spec progress_consumer([atom()]) :: (PropertyDamage.Progress.t() -> :ok) | nil
Build a telemetry consumer for the unified progress projection (DR-022), or
nil when nothing is listening.
Given the operations to cover (e.g. [:test_run]), it checks whether a handler
is attached for any of their :progress/:result events. If so it returns a
(PropertyDamage.Progress.t -> :ok) that emits the corresponding coarse event;
otherwise it returns nil so the reporter stays inert and the hot loop builds
no %Progress{} (the zero-cost guarantee).
Emit a run exception event.
@spec run_start(map()) :: :ok
Emit a run start event.
Emit a run stop event.
@spec sequence_start(map()) :: :ok
Emit a sequence start event.
Emit a sequence stop event.
Emit a shrink iteration event.
@spec shrink_start(map()) :: :ok
Emit a shrink start event.
Emit a shrink stop event.
Execute a function with telemetry span instrumentation.
Emits start and stop (or exception) events around the function.
Examples
Telemetry.span(:run, %{model: MyModel}, fn ->
# run logic
{:ok, result}
end)