# `PtcRunner.TraceLog.Event`
[🔗](https://github.com/andreasronge/ptc_runner/blob/main/lib/ptc_runner/trace_log/event.ex#L1)

Builds v2 flat event envelopes for trace logging.

Transforms raw telemetry data into a flat, queryable JSON structure where
commonly-filtered fields (agent_name, turn, tool_name, tokens, duration)
are promoted to top level. Bulky payloads go into a `data` bag.

## V2 Event Shape

Every event has these top-level fields:

    schema_version, event, trace_id, timestamp, seq,
    span_id, parent_span_id,
    agent_name, agent_id, turn,
    duration_ms, input_tokens, output_tokens, total_tokens,
    cache_creation_tokens, cache_read_tokens,
    tool_name, model, status,
    data

## Configuration

Sanitization limits are runtime-configurable via application config:

- `:trace_max_string_size` - Maximum string size in bytes before truncation (default: `65_536`)
- `:trace_max_list_size` - Maximum list length before summarizing (default: `100`)
- `:trace_max_map_size` - Maximum map size (keys) before summarizing (default: `100`)
- `:trace_preserve_full_keys` - Map keys whose string values are never truncated (default: `["system_prompt"]`)

# `encode`

```elixir
@spec encode(map()) :: {:ok, String.t()} | {:error, term()}
```

Encodes an event map to a JSON string.

Returns `{:ok, json}` on success, `{:error, reason}` on failure.

# `encode!`

```elixir
@spec encode!(map()) :: String.t()
```

Encodes an event map to a JSON string, raising on failure.

# `from_telemetry`

```elixir
@spec from_telemetry(list(), map(), map(), String.t()) :: map()
```

Creates a v2 flat event map from telemetry data.

Promotes commonly-queried fields to top level and puts remaining
metadata into a `data` bag. The `agent_name` field is extracted from
either `metadata.agent_name` or `metadata.agent.name` (fallback).

## Examples

    iex> event = [:ptc_runner, :sub_agent, :run, :start]
    iex> measurements = %{system_time: 1000}
    iex> metadata = %{agent_name: "test", agent_id: "abc123"}
    iex> result = PtcRunner.TraceLog.Event.from_telemetry(event, measurements, metadata, "trace-123")
    iex> result["event"]
    "run.start"
    iex> result["schema_version"]
    2
    iex> result["agent_name"]
    "test"

# `sanitize`

```elixir
@spec sanitize(term()) :: term()
```

Sanitizes a value for safe JSON encoding.

Handles:
- PIDs, refs, ports, functions → `inspect/1` string
- Non-printable binaries → `%{"__binary__" => true, "size" => N}`
- Large strings (>64KB by default, configurable) → truncated with preview
- Large lists (>100 by default, configurable) → `"List(N items)"`
- Maps → recursively sanitized
- Structs → converted to maps and sanitized
- Tuples → converted to lists and sanitized

## Examples

    iex> result = PtcRunner.TraceLog.Event.sanitize(self())
    iex> String.starts_with?(result, "#PID<")
    true

    iex> PtcRunner.TraceLog.Event.sanitize(%{a: 1, b: 2})
    %{"a" => 1, "b" => 2}

    iex> PtcRunner.TraceLog.Event.sanitize({:ok, "result"})
    [:ok, "result"]

    iex> PtcRunner.TraceLog.Event.sanitize(<<0, 1, 2, 3>>)
    %{"__binary__" => true, "size" => 4}

# `schema_version`

```elixir
@spec schema_version() :: pos_integer()
```

Returns the current schema version.

## Examples

    iex> PtcRunner.TraceLog.Event.schema_version()
    2

---

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