Skip to content

Design: live state/metrics framework (connections, packets, bytes) for pcap + mitm #5

Description

@sunng87

Goal

Add a shared, queryable state framework that tracks live data and metrics
as traffic flows, for both traffic sources (--mode pcap and --mode mitm):

  • Live connections — currently-open connections (4-tuple / id, since-when, per-direction counters, cleartext/encrypted).
  • Packet count in/out — packets per direction.
  • Bytes in/out — bytes per direction.

The immediate consumer is the TUI (--tui) — a metrics bar + a connections
view — but the store should be source-agnostic so stdout mode / future exporters
can read it too.

Background (current architecture)

  • pcap: capture::run → net::parse_frame → flow::ConnTable::handle(seg, pg_port). ConnTable already keys connections by 4-tuple (ConnKey { client, server }), reassembles, and removes them on RST — but exposes nothing.
  • mitm: proxy::serve → per-connection handle_connection spawns two pump tasks (client→server, server→client) that read/write + decode. There is no central connection registry today; each connection is independent.
  • Output: decoded/status lines flow through a single crossbeam-channel (decode::OUTPUT_TX) to a consumer (stdout thread or TUI). The metrics store is orthogonal to that channel — it's shared state read on demand (e.g. per TUI frame).

Proposed design

A new state module holding an Arc<Metrics> shared between source threads and
the consumer/TUI.

pub struct Metrics {
    // aggregate (lock-free)
    conns_opened: AtomicU64,
    conns_live:   AtomicUsize,
    pkts_in:  AtomicU64,   // toward server  (client -> server)
    pkts_out: AtomicU64,   // toward client  (server -> client)
    bytes_in: AtomicU64,
    bytes_out:AtomicU64,
    // live connection registry
    conns: Mutex<HashMap<ConnId, ConnStats>>,
}
pub struct ConnStats {
    client: Endpoint, server: Endpoint,
    since: Instant,
    encrypted: bool,
    // per-connection atomics (so hot updates don't take the registry lock)
    pkts_in: AtomicU64, pkts_out: AtomicU64,
    bytes_in: AtomicU64, bytes_out: AtomicU64,
}
  • Counters as atomics (lock-free hot path); the registry behind a Mutex touched only on open/close.
  • Metrics::snapshot() reads atomics + clones registry entries for the TUI to render each frame (tearing across fields is fine for display).
  • Threaded into the sources at startup: capture::run(opts, metrics) / proxy::serve(opts, metrics).

Integration points

Source Where metrics update Notes
pcap flow::ConnTable::handle (already classifies direction + has payload.len()) register on new conn, deregister on RST/FIN; one segment = one packet
mitm proxy::handle_connection (open/close) + pump (per read) register a ConnStats on accept; client→server pump = in, server→client pump = out

decode::out already fires per decoded message — bytes/packets are best counted
at the transport edge (ConnTable / pump), not in the decoder.

TUI surfacing

  • Metrics bar in the title: conns 3 · in 1.2k/412p · out 8.4k/530p.
  • New connections panel (list of ConnStats, selectable/filterable) — natural follow-up to the current single log view.

Decisions needed

  1. in/out convention — propose in = toward server (client→server), out = toward client (server→client), from the server/tap viewpoint. Confirm.
  2. "packet" for mitm — the proxy layer sees TLS records / app reads, not IP packets. Options: (a) count logical reads per direction, (b) count pgwire messages (via decode), (c) bytes-only for mitm + true packet counts for pcap. Recommend (a) reads as the mitm analog, clearly labeled.
  3. Connection identity — unify pcap (4-tuple ConnKey) and mitm (proxy-local id) into one ConnId? Or keep separate views?
  4. stdout surfacing — metrics only in --tui, or an optional periodic status line / --metrics flag for stdout mode?
  5. Scope of "live" — drop connections on close only, or also expose conns_opened totals + rates (pkts/s) later?

Non-goals (for this issue)

  • Persistent storage / replay of metrics.
  • Export endpoints (Prometheus, OpenMetrics) — future, once the snapshot exists.
  • pcap byte/packet counts for the non-PG-direction traffic (we only see the filtered PG stream).

References

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions