Skip to content

Commit 57000ff

Browse files
authored
feat: improve observability (#3)
Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
1 parent 5f360ca commit 57000ff

8 files changed

Lines changed: 951 additions & 91 deletions

File tree

‎guides/Usage.md‎

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,3 +217,78 @@ Hard delete a stream that should exist:
217217
```elixir
218218
:ok = MyApp.EventStore.delete_stream("stream2", :stream_exists, :hard)
219219
```
220+
221+
## Telemetry
222+
223+
EventStore emits `:telemetry` events for public operations. Each instrumented
224+
operation publishes `:start`, `:stop`, and `:exception` events under the
225+
`[:eventstore, operation, suffix]` namespace.
226+
227+
The first pass covers these operations:
228+
229+
- `:append_to_stream`
230+
- `:link_to_stream`
231+
- `:read_stream_forward`
232+
- `:read_stream_backward`
233+
- `:delete_stream`
234+
- `:paginate_streams`
235+
- `:subscribe_to_stream`
236+
- `:delete_subscription`
237+
- `:read_snapshot`
238+
- `:record_snapshot`
239+
- `:delete_snapshot`
240+
- `:stream_batch_read`
241+
242+
Alias operations reuse the same event names. For example,
243+
`read_all_streams_forward/3` emits `[:eventstore, :read_stream_forward, ...]`
244+
with `stream_uuid: "$all"` in the metadata, and
245+
`subscribe_to_all_streams/3` emits `[:eventstore, :subscribe_to_stream, ...]`
246+
with the same stream identifier.
247+
248+
Stop metadata includes a normalized `:result` for all instrumented operations.
249+
Operations that return `:ok` emit `result: :ok`. Operations that return
250+
`{:ok, value}` also emit `result: :ok` so telemetry does not copy returned
251+
payloads such as event lists or subscription structs into metadata. When an
252+
operation returns `{:error, reason}`, stop metadata includes
253+
`result: {:error, reason}`.
254+
255+
Lazy stream APIs do not emit `:stream_forward` or `:stream_backward` spans.
256+
Instead, `stream_forward/3`, `stream_backward/3`, `stream_all_forward/2`, and
257+
`stream_all_backward/2` emit `[:eventstore, :stream_batch_read, ...]` once per
258+
batch read performed during enumeration. These events include `:direction`,
259+
`:start_version`, and `:requested_batch_size` in start metadata, and add
260+
`:event_count` plus `:result` in stop metadata. Forward streaming may emit a
261+
final batch read with `event_count: 0` to detect completion.
262+
263+
Measurements:
264+
265+
- `:start` includes `%{system_time: System.system_time(), monotonic_time: native_time}`
266+
- `:stop` includes `%{duration: native_time, monotonic_time: native_time}`
267+
- `:exception` includes `%{duration: native_time, monotonic_time: native_time}`
268+
269+
Metadata always includes `:event_store`. Depending on the operation it may also
270+
include fields such as `:name`, `:stream_uuid`, `:expected_version`,
271+
`:event_count`, `:count`, `:start_version`, `:delete_type`, `:result`,
272+
`:subscription_name`, `:source_uuid`, and pagination options. Because
273+
EventStore now uses `:telemetry.span/3`, emitted metadata also includes a
274+
`telemetry_span_context` key so handlers can correlate start/stop/exception
275+
events for the same operation execution.
276+
277+
Example handler:
278+
279+
```elixir
280+
events = [
281+
[:eventstore, :append_to_stream, :start],
282+
[:eventstore, :append_to_stream, :stop],
283+
[:eventstore, :append_to_stream, :exception]
284+
]
285+
286+
:telemetry.attach_many(
287+
"my-app-eventstore",
288+
events,
289+
fn event_name, measurements, metadata, _config ->
290+
IO.inspect({event_name, measurements, metadata}, label: "eventstore.telemetry")
291+
end,
292+
nil
293+
)
294+
```

0 commit comments

Comments
 (0)