PropertyDamage.EventLog.Entry (PropertyDamage v0.1.0)
View SourceRepresents a single entry in the event log.
The event log records all events that occur during test execution, wrapping each event with metadata for debugging and analysis.
Event Sources
Events can come from seven sources:
Command events (
:commandsource) - Events produced by executing commands against the SUT. These have acommand_indexindicating which command produced them.Injector events (
:injectorsource) - Events received from the SUT via injector adapters (webhooks, callbacks, etc.). These havecommand_index: nilsince they're not triggered by a specific command, and include theinjector_adaptermodule that received them.Nemesis events (
:nemesissource) - Events produced by fault injection commands. These have acommand_indexlike command events, plus thenemesis_modulethat produced them.Telemetry events (
:telemetrysource) - Events derived from OpenTelemetry spans received from the SUT. These include thetelemetry_receivermodule and optionaltrace_id/span_id.Stutter events (
:stuttersource) - Events from retry executions during idempotency testing. These are captured but NOT applied to projections. They includestutter_attemptandstutter_comparison.Mock events (
:mocksource) - Events injected by mock service adapters when the SUT calls them. These have acommand_indexindicating which command triggered the mock call.Injected events (
:injectedsource) - Events emitted mid-execution by adapters with:asyncsemantics usingctx.inject.(event). These update projections immediately when injected, unlike command events which batch all events at the end. They have acommand_indexindicating which command's adapter injected them.
Example Event Log
[
%Entry{timestamp: 1, command_index: 0, event: %OrderCreated{...}, source: :command},
%Entry{timestamp: 15, command_index: nil, event: %PaymentConfirmed{...}, source: :injector, injector_adapter: PaymentWebhook},
%Entry{timestamp: 20, command_index: 1, event: %OrderCancelled{...}, source: :command}
]Timestamp
The timestamp is monotonic time in milliseconds (via System.monotonic_time/1),
ensuring consistent ordering even if system clock changes.
System Events
System events (like CommandSequenceTerminated) are also recorded in the
event log but are metadata-only - projections do not receive them. They
exist for debugging and visualization purposes.
Summary
Functions
Check if an entry is from a command.
Create a new entry for a command event.
Create a new entry for an injected event.
Create a new entry for an injector event.
Create a new entry for a mock-injected event.
Create a new entry for a nemesis event.
Create a new entry for a stutter (retry) event.
Create a new entry for a telemetry event.
Check if an entry was injected mid-execution by an adapter.
Check if an entry is from an injector.
Check if an entry is from a mock service adapter.
Check if an entry is from a nemesis.
Check if an entry is from stutter (retry) testing.
Check if an entry is from telemetry.
Types
@type t() :: %PropertyDamage.EventLog.Entry{ branch_id: non_neg_integer() | nil, command_index: non_neg_integer() | nil, event: struct(), injector_adapter: module() | nil, nemesis_module: module() | nil, source: :command | :injector | :nemesis | :telemetry | :stutter | :mock | :injected, span_id: String.t() | nil, stutter_attempt: pos_integer() | nil, stutter_comparison: :match | {:mismatch, map()} | nil, telemetry_receiver: module() | nil, timestamp: integer(), trace_id: String.t() | nil }
An event log entry.
timestamp- Monotonic time in milliseconds when event was recordedcommand_index- Index of command that produced this event (nil for injected/telemetry events)event- The actual event structsource- One of:command,:injector,:nemesis,:telemetry,:stutter,:mock, or:injectedinjector_adapter- Module that received the event (only for:injectorsource)nemesis_module- Module that produced the event (only for:nemesissource)telemetry_receiver- Module that received the span (only for:telemetrysource)trace_id- Distributed trace ID (only for:telemetrysource)span_id- Span ID within the trace (only for:telemetrysource)branch_id- Branch identifier for parallel execution (nil for linear sequences)stutter_attempt- Attempt number for stutter retries (only for:stuttersource)stutter_comparison- Comparison result with original events (only for:stuttersource)
Functions
Check if an entry is from a command.
Examples
iex> entry = PropertyDamage.EventLog.Entry.from_command(%SomeEvent{}, 0)
iex> PropertyDamage.EventLog.Entry.command?(entry)
true
@spec from_command(struct(), non_neg_integer(), keyword()) :: t()
Create a new entry for a command event.
Parameters
event- The event structcommand_index- Index of the command that produced this event
Options
:timestamp- Override timestamp (default: current monotonic time)
Examples
iex> entry = PropertyDamage.EventLog.Entry.from_command(%SomeEvent{}, 0)
iex> entry.source
:command
iex> entry.command_index
0
@spec from_injected(struct(), non_neg_integer(), keyword()) :: t()
Create a new entry for an injected event.
Injected events are emitted mid-execution by adapters using ctx.inject.(event).
Unlike command events which are batched at the end of execution, injected events
update projections immediately when they're emitted. This is useful for adapters
with :async semantics that need to emit events as they happen (e.g., emit
AuthorizationCreated immediately when the resource is created, rather than
waiting until polling completes).
Parameters
event- The event structcommand_index- Index of the command whose adapter is injecting the event
Options
:timestamp- Override timestamp (default: current monotonic time):branch_id- Branch identifier for parallel execution
Examples
iex> entry = PropertyDamage.EventLog.Entry.from_injected(%AuthCreated{}, 3)
iex> entry.source
:injected
iex> entry.command_index
3
Create a new entry for an injector event.
Parameters
event- The event structinjector_adapter- Module that received the event
Options
:timestamp- Override timestamp (default: current monotonic time)
Examples
iex> entry = PropertyDamage.EventLog.Entry.from_injector(%PaymentEvent{}, PaymentWebhook)
iex> entry.source
:injector
iex> entry.command_index
nil
@spec from_mock(struct(), non_neg_integer(), keyword()) :: t()
Create a new entry for a mock-injected event.
Mock events are injected by mock service adapters when the SUT calls them. They are applied to projections like command events.
Parameters
event- The event struct injected by the mockcommand_index- Index of the command that triggered the mock call
Options
:timestamp- Override timestamp (default: current monotonic time):branch_id- Branch identifier for parallel execution
Examples
iex> entry = PropertyDamage.EventLog.Entry.from_mock(%PaymentProcessed{}, 3)
iex> entry.source
:mock
iex> entry.command_index
3
@spec from_nemesis(struct(), non_neg_integer(), module(), keyword()) :: t()
Create a new entry for a nemesis event.
Parameters
event- The event structcommand_index- Index of the nemesis command that produced this eventnemesis_module- Module that produced the event
Options
:timestamp- Override timestamp (default: current monotonic time):branch_id- Branch identifier for parallel execution
Examples
iex> entry = PropertyDamage.EventLog.Entry.from_nemesis(%PartitionEvent{}, 3, MyNemesis)
iex> entry.source
:nemesis
iex> entry.nemesis_module
MyNemesis
@spec from_stutter(struct(), non_neg_integer(), pos_integer(), term(), keyword()) :: t()
Create a new entry for a stutter (retry) event.
Stutter events are captured during idempotency testing but NOT applied to projections. They record the result of retry executions for comparison.
Parameters
event- The event struct from retry executioncommand_index- Index of the command being retriedattempt- Attempt number (2, 3, etc. - first execution is attempt 1)comparison- Result of comparing with original events
Options
:timestamp- Override timestamp (default: current monotonic time):branch_id- Branch identifier for parallel execution
Examples
iex> entry = PropertyDamage.EventLog.Entry.from_stutter(%OrderCreated{}, 5, 2, :match)
iex> entry.source
:stutter
iex> entry.stutter_attempt
2
Create a new entry for a telemetry event.
Parameters
event- The event struct (derived from a telemetry span)telemetry_receiver- Module that received and converted the span
Options
:timestamp- Override timestamp (default: current monotonic time):trace_id- Distributed trace ID:span_id- Span ID within the trace:branch_id- Branch identifier for parallel execution
Examples
iex> entry = PropertyDamage.EventLog.Entry.from_telemetry(%SlowQuery{}, MyReceiver, trace_id: "abc123")
iex> entry.source
:telemetry
iex> entry.trace_id
"abc123"
Check if an entry was injected mid-execution by an adapter.
Examples
iex> entry = PropertyDamage.EventLog.Entry.from_injected(%SomeEvent{}, 0)
iex> PropertyDamage.EventLog.Entry.injected?(entry)
true
Check if an entry is from an injector.
Examples
iex> entry = PropertyDamage.EventLog.Entry.from_injector(%SomeEvent{}, SomeInjector)
iex> PropertyDamage.EventLog.Entry.injector?(entry)
true
Check if an entry is from a mock service adapter.
Examples
iex> entry = PropertyDamage.EventLog.Entry.from_mock(%SomeEvent{}, 0)
iex> PropertyDamage.EventLog.Entry.mock?(entry)
true
Check if an entry is from a nemesis.
Examples
iex> entry = PropertyDamage.EventLog.Entry.from_nemesis(%SomeEvent{}, 0, MyNemesis)
iex> PropertyDamage.EventLog.Entry.nemesis?(entry)
true
Check if an entry is from stutter (retry) testing.
Examples
iex> entry = PropertyDamage.EventLog.Entry.from_stutter(%SomeEvent{}, 0, 2, :match)
iex> PropertyDamage.EventLog.Entry.stutter?(entry)
true
Check if an entry is from telemetry.
Examples
iex> entry = PropertyDamage.EventLog.Entry.from_telemetry(%SomeEvent{}, MyReceiver)
iex> PropertyDamage.EventLog.Entry.telemetry?(entry)
true