// SPDX-FileCopyrightText: © 2026 Francesc Muñoz // SPDX-FileCopyrightText: © 2026 Jeffrey C. Ollie // SPDX-License-Identifier: MIT //! What the collectors measure and the panels draw. A sample owns none of its //! memory: everything in one is allocated from the arena of the snapshot it //! belongs to, and goes when that snapshot is replaced. const std = @import("std"); /// Bytes per second in each direction. pub const Rates = struct { rx: f64 = 0, tx: f64 = 0, pub fn sum(self: Rates) f64 { return self.rx + self.tx; } }; pub const InterfaceRate = struct { name: []const u8, rx_rate: f64, tx_rate: f64, }; /// The whole machine's traffic, from the interface counters. pub const Throughput = struct { rx_rate: f64 = 0, tx_rate: f64 = 0, rx_total: f64 = 0, tx_total: f64 = 0, interfaces: []const InterfaceRate = &.{}, }; /// A socket, as `ss` or `lsof` describe it. `state` uses the BSD names -- /// `ESTABLISHED`, `LISTEN`, `SYN_SENT` -- whichever tool it came from, and is /// empty for a UDP socket that has no peer. pub const Connection = struct { command: []const u8, /// Zero when the socket belongs to a process this user cannot see. pid: u32, /// `TCP` or `UDP`. protocol: []const u8, local: []const u8, /// Empty for a socket with no peer. remote: []const u8, /// `remote` with the address replaced by its name, once one is known. remote_display: []const u8, state: []const u8, }; pub const ProcessRate = struct { name: []const u8, pid: u32, rx_rate: f64, tx_rate: f64, rx_total: f64, tx_total: f64, }; pub const RemoteHost = struct { ip: []const u8, /// The name the address resolves to, or the address itself until then. host: []const u8, /// ISO 3166-1 alpha-2, or empty while unknown. country: []const u8, org: []const u8, lat: ?f64, lon: ?f64, rx_rate: f64, tx_rate: f64, }; pub const ProcessConnection = struct { local: []const u8, remote: []const u8, remote_display: []const u8, country: []const u8, rx_rate: f64, tx_rate: f64, }; pub const History = struct { rx: []const f64 = &.{}, tx: []const f64 = &.{}, }; /// The per-process and per-host side of the traffic: who is talking, and to /// whom. pub const Traffic = struct { processes: []const ProcessRate = &.{}, remotes: []const RemoteHost = &.{}, /// Keyed by `local|remote`, for joining with the connection list. connection_rates: std.StringHashMapUnmanaged(Rates) = .empty, process_connections: std.AutoHashMapUnmanaged(u32, []const ProcessConnection) = .empty, histories: std.AutoHashMapUnmanaged(u32, History) = .empty, pub fn rateOf(self: *const Traffic, local: []const u8, remote: []const u8) ?Rates { var key: [256]u8 = undefined; const k = std.fmt.bufPrint(&key, "{s}|{s}", .{ local, remote }) catch return null; return self.connection_rates.get(k); } }; pub const System = struct { host: []const u8 = "", local_ip: []const u8 = "", gateway: []const u8 = "", public_ip: []const u8 = "", }; pub const Latency = struct { gateway_ms: ?f64 = null, internet_ms: ?f64 = null, dns_ms: ?f64 = null, /// The fraction of a burst's probes that got no reply, or null where that /// target was not probed. gateway_loss: ?f64 = null, internet_loss: ?f64 = null, dns_loss: ?f64 = null, dns_server: []const u8 = "", }; /// Where an address is, as ip-api.com answers it. pub const Geo = struct { country: []const u8 = "", org: []const u8 = "", lat: ?f64 = null, lon: ?f64 = null, };