# `Cauldron2D.Trace`
[🔗](https://github.com/jaman/cauldron/blob/v0.1.3/cauldron_2d/lib/cauldron_2d/trace.ex#L1)

A trace of what happened and when, written as one line per event, and read back for
`mix cauldron.report`.

    Cauldron2D.Trace.start()
    Cauldron2D.Trace.write(:mouse, x: 37, tile: 13.25)
    Cauldron2D.Trace.stop()

`start/0` opens the file `CAULDRON_TRACE` names — `1` for `cauldron_trace.log` in the
current directory — and does nothing when it is unset; every `write/2` is then a
no-op. A line is `t=<ms since start> kind=<kind> key=value ...`; floats are written
to two places.

`read!/1`, `at/1`, `summary/1` and `latency/3` are what a report is made from.

# `event`

```elixir
@type event() :: %{required(String.t()) =&gt; String.t()}
```

# `at`

```elixir
@spec at(event()) :: float()
```

An event's time in milliseconds.

# `latency`

```elixir
@spec latency([event()], String.t(), String.t()) :: map()
```

The time from each `from` event to the next `to` event after it, as median, p90, max and count.

# `on?`

```elixir
@spec on?() :: boolean()
```

Whether a trace is open.

# `read!`

```elixir
@spec read!(Path.t()) :: [event()]
```

The events in a trace file, each a map of its fields as strings; lines with no fields are dropped.

# `start`

```elixir
@spec start() :: boolean()
```

Open the trace and write a `start` event, if `CAULDRON_TRACE` is set. Returns whether tracing is on.

# `stats`

```elixir
@spec stats([number()]) :: %{
  median: float(),
  p90: float(),
  max: float(),
  count: non_neg_integer()
}
```

Median, p90, max and count of a list of numbers; zeros for none.

# `stop`

```elixir
@spec stop() :: :ok
```

Write a `stop` event, flush and close. A no-op when no trace is open, or when the process that opened it has already gone and closed it with it.

# `summary`

```elixir
@spec summary([event()]) :: %{
  counts: %{required(String.t()) =&gt; non_neg_integer()},
  gaps: %{required(String.t()) =&gt; map()}
}
```

How many events of each kind, and for each kind the gaps between one and the next as median, p90, max and count.

# `write`

```elixir
@spec write(atom(), keyword()) :: :ok
```

Append one event: `kind` names it, `fields` become `key=value` pairs. A no-op when no trace is open.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
