stats

package
v0.6.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 31, 2026 License: Apache-2.0 Imports: 7 Imported by: 0

Documentation

Overview

Package stats collects Wireblast's traffic counters and turns them into periodic snapshots.

The split is deliberate: the transmit and receive loops touch nothing but a handful of per-queue atomic counters, and every bit of arithmetic, formatting and rate calculation happens in a separate collector goroutine. Nothing here is called from a packet hot path except Counters.AddTx and Counters.AddRx, which are a few atomic adds and no allocation.

The same Snapshot feeds the TUI dashboard and the --no-tui periodic output, so both report identical numbers.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Bits

func Bits(v float64) string

Bits renders a bit rate, e.g. "9.87 Gbit/s".

func Bytes

func Bytes(v uint64) string

Bytes renders a byte total, e.g. "3.21 GB".

func Count

func Count(v uint64) string

Count renders a packet or byte count compactly: 1234 -> "1.23 k", 14880000 -> "14.88 M". Small values are printed exactly, because "sent 7 packets" should say 7.

func Duration

func Duration(d time.Duration) string

Duration renders an elapsed or remaining time as m:ss or h:mm:ss.

func PPS

func PPS(v float64) string

PPS renders a packet rate, e.g. "1.49 Mpps".

Types

type Class

type Class uint8

Class is the protocol bucket a packet is counted under. Classification is done by the generator (which already knows) on transmit, and by a minimal header peek on receive.

const (
	ClassOther Class = iota
	ClassUDP
	ClassTCP
)

type Collector

type Collector struct {
	// contains filtered or unexported fields
}

Collector owns the per-queue counters and publishes snapshots.

func New

func New(numQueues int, limit time.Duration, kernel KernelFunc, opts ...Option) *Collector

New creates a collector for numQueues queues. kernel may be nil, in which case the kernel counters stay zero (useful in tests and before the fleet is open).

func (*Collector) MarkStart

func (c *Collector) MarkStart()

MarkStart restarts the run clock as of now.

The dataplane calls this once the link is up. Attaching native XDP bounces the link for several seconds on many drivers, and counting that wait as part of the run would understate every average rate and make a 30-second run report 40 seconds.

func (*Collector) NumQueues

func (c *Collector) NumQueues() int

NumQueues returns how many queues the collector tracks.

func (*Collector) Queue

func (c *Collector) Queue(i int) *Counters

Queue returns the counters for one queue. The dataplane hands each worker its own pointer at startup so the hot path never indexes a slice.

func (*Collector) ResetInterval

func (c *Collector) ResetInterval()

ResetInterval zeroes the visible counters while leaving the lifetime totals untouched. This is the `r` hotkey.

func (*Collector) Run

func (c *Collector) Run(ctx context.Context, interval time.Duration)

Run samples and publishes a snapshot every interval until ctx is cancelled. It publishes one final snapshot on the way out so the summary reflects the last packets sent.

func (*Collector) Sample

func (c *Collector) Sample() *Snapshot

Sample takes a reading now and publishes it. Run calls it on a ticker; the dataplane also calls it directly when it wants a fresh final snapshot.

func (*Collector) SetState

func (c *Collector) SetState(s State)

SetState records what the run is doing; it shows up in the next snapshot.

func (*Collector) Snapshot

func (c *Collector) Snapshot() *Snapshot

Snapshot returns the most recently published snapshot. It never blocks and never allocates, so the TUI can call it as often as it repaints.

func (*Collector) State

func (c *Collector) State() State

State returns the current run state.

type Counters

type Counters struct {
	TxPackets atomic.Uint64
	TxBytes   atomic.Uint64 // total Ethernet frame bytes, including the FCS
	TxUDP     atomic.Uint64
	TxTCP     atomic.Uint64
	TxOther   atomic.Uint64
	TxErrors  atomic.Uint64

	RxPackets atomic.Uint64
	RxBytes   atomic.Uint64
	RxUDP     atomic.Uint64
	RxTCP     atomic.Uint64
	RxOther   atomic.Uint64
	RxErrors  atomic.Uint64
	// contains filtered or unexported fields
}

Counters is one queue's counters. Each queue gets its own, so the transmit and receive loops never contend with each other.

The fields are atomic because the collector reads them concurrently, but they are only ever written by that queue's own goroutine.

func (*Counters) AddRx

func (c *Counters) AddRx(bytes uint64, class Class)

AddRx records one received packet and its protocol class.

func (*Counters) AddTx

func (c *Counters) AddTx(packets int, bytes uint64, class Class)

AddTx records a batch of transmitted packets of one protocol class. It is called once per batch, not once per packet.

type HistoryPoint

type HistoryPoint struct {
	At     time.Time
	TX, RX Rates
}

HistoryPoint is one second of the run, kept so the dashboard can show where the rate has been rather than only where it is.

type Kernel

type Kernel struct {
	Queues          int
	RxPackets       uint64
	TxPackets       uint64
	RxDropped       uint64
	RxRingFull      uint64
	RxFillRingEmpty uint64
	RxInvalidDescs  uint64
	TxInvalidDescs  uint64
	TxRingEmpty     uint64
	PerQueue        []KernelQueue
}

Kernel holds the counters the AF_XDP library reports, copied into a library-independent shape so this package does not depend on go-afxdp (and so tests need no AF_XDP at all).

type KernelFunc

type KernelFunc func() (Kernel, error)

KernelFunc reports the current kernel counters. It is injected so the collector can be tested without an AF_XDP fleet.

type KernelQueue

type KernelQueue struct {
	Queue      int
	RxPackets  uint64
	TxPackets  uint64
	RxDropped  uint64
	RxRingFull uint64
}

KernelQueue is one queue's slice of the kernel counters, used to point at a queue that is dropping or stalled.

type Option

type Option func(*Collector)

Option configures a Collector.

func WithClock

func WithClock(now func() time.Time) Option

WithClock replaces the time source, for tests.

func WithWindow

func WithWindow(n int) Option

WithWindow sets how many samples the rate average spans. With the default 250ms sampling interval, 4 samples means rates are averaged over a second and refreshed four times a second.

func WithoutTransmit

func WithoutTransmit() Option

WithoutTransmit marks the run as receive-only, so the status line does not carry a transmit half that will only ever read zero.

type Rates

type Rates struct {
	PPS float64

	// FrameBPS is **L2**: the Ethernet frame itself, including its 4-byte FCS.
	//
	// Note that the kernel's own netdev counters — what bwm-ng, iftop, nload
	// and `ip -s link` report — exclude the FCS by specification, so they read
	// 4 bytes per packet below this. That is about 6% at 64-byte frames and 1%
	// at IMIX, and it is a different measurement rather than a disagreement.
	FrameBPS float64

	// WireBPS is **L1**: the frame plus the 20 bytes of physical framing every
	// packet costs — 7-byte preamble, 1-byte start-frame delimiter and 12-byte
	// interframe gap. This is link utilisation, and it is the unit --bps is
	// measured in: 10G line rate means 10 Gbit/s of L1.
	WireBPS float64
}

Rates are the per-second figures computed over the sampling window.

The two bit rates are the same two T-Rex reports, and are shown under those names: FrameBPS is L2, WireBPS is L1.

type Snapshot

type Snapshot struct {
	At        time.Time
	Elapsed   time.Duration
	Remaining time.Duration // 0 when the run has no duration limit
	State     State

	// TX and RX are the visible counters, measured since the last interval
	// reset. TotalTX and TotalRX are the lifetime figures, which the final
	// summary reports and which an interval reset never disturbs.
	TX, RX           Totals
	TotalTX, TotalRX Totals
	TXRate, RXRate   Rates

	// IntervalSince is when the visible counters were last reset.
	IntervalSince time.Time

	Kernel Kernel

	// Problems names queues that are dropping or stalled, ready to display.
	Problems []string

	// Transmits is false for a receive-only run, so the status line can leave
	// out a transmit half that will only ever read zero.
	Transmits bool

	// History is one point per second, oldest first, for the dashboard's
	// sparklines. It spans at most historyLen seconds.
	History []HistoryPoint
}

Snapshot is an immutable view of the run, published by the collector and consumed by the TUI and the noninteractive printer.

func (*Snapshot) Line

func (s *Snapshot) Line() string

Line renders a snapshot as the single status line the --no-tui runner prints once a second. Both bit rates appear, named L1 and L2 as T-Rex names them: for small frames they differ by a third, and only L1 is link utilisation.

func (*Snapshot) Summary

func (s *Snapshot) Summary() string

Summary renders the final report printed when a run ends. It reports lifetime totals, which an interval reset never touches.

type State

type State int

State is what the run is currently doing.

const (
	StateStarting State = iota
	StateRunning
	StatePaused
	StateStopping
	StateComplete
)

func (State) String

func (s State) String() string

type Totals

type Totals struct {
	Packets uint64
	// Bytes is the total Ethernet frame size, including the 4-byte FCS — the
	// same definition as --packet-size, so a run of 64-byte frames reports an
	// average frame size of 64.
	Bytes  uint64
	UDP    uint64
	TCP    uint64
	Other  uint64
	Errors uint64
	Drops  uint64
}

Totals is one direction's counters at a point in time.

func (Totals) AvgFrame

func (t Totals) AvgFrame() float64

AvgFrame is the mean total frame size in bytes, including the FCS.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL