c08fc277a9
A native macOS network monitor that renders live traffic as a top-down neon city: your Mac is downtown, remote orgs are glowing districts, and traffic is cars of light driving the roads. Architecture: - NetworkCityCore: swappable data layer behind a ConnectionSource protocol (nettop-backed today), plus pure/tested logic — traffic diffing, org classification (reverse-DNS + CIDR), traffic classes, hub-and-spoke expansion policy, label anti-overlap, and latency→distance layout. - NetworkCityApp: SwiftUI + SpriteKit city — auto-expanding districts, protocol-coloured cars, click-to-inspect panel, and latency-as-distance (districts glide to their measured RTT). - nettop-probe: CLI proof of the data layer. 44 tests passing. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
46 lines
1.8 KiB
Swift
46 lines
1.8 KiB
Swift
import Foundation
|
|
import NetworkCityCore
|
|
|
|
// Phase-1 proof of concept. Polls nettop, diffs successive snapshots, and prints
|
|
// the busiest external flows as live KB/s — i.e. the raw material that will
|
|
// become cars driving to buildings.
|
|
|
|
setvbuf(stdout, nil, _IONBF, 0) // unbuffered: see output live even when piped
|
|
|
|
let interval: TimeInterval = 2.0
|
|
let source = NettopSource()
|
|
let differ = TrafficDiffer()
|
|
var warmedUp = false
|
|
|
|
func pad(_ s: String, _ width: Int) -> String {
|
|
s.count >= width ? String(s.prefix(width)) : s + String(repeating: " ", count: width - s.count)
|
|
}
|
|
|
|
print("📡 NetworkCity probe — sampling every \(Int(interval))s. Ctrl-C to stop.\n")
|
|
|
|
for await snap in source.snapshots(every: interval) {
|
|
let deltas = differ.ingest(snap).filter { $0.connection.isExternal }
|
|
let external = snap.connections.filter(\.isExternal).count
|
|
|
|
if !warmedUp {
|
|
warmedUp = true
|
|
print("… warming up (need two samples to compute rates) …\n")
|
|
continue
|
|
}
|
|
|
|
let active = deltas.sorted { ($0.inBytesPerSec + $0.outBytesPerSec) > ($1.inBytesPerSec + $1.outBytesPerSec) }
|
|
let ts = DateFormatter.localizedString(from: snap.timestamp, dateStyle: .none, timeStyle: .medium)
|
|
|
|
print("─── \(ts) \(active.count) active / \(external) external connections ───")
|
|
print("\(pad("PROCESS", 18)) \(pad("DESTINATION", 24)) ↓ KB/s ↑ KB/s")
|
|
if active.isEmpty {
|
|
print(" (quiet — no measurable traffic this interval)")
|
|
}
|
|
for d in active.prefix(15) {
|
|
let dest = d.connection.remote.display
|
|
print("\(pad(d.connection.processName, 18)) \(pad(dest, 24)) "
|
|
+ "\(String(format: "%9.1f", d.inBytesPerSec / 1024)) \(String(format: "%9.1f", d.outBytesPerSec / 1024))")
|
|
}
|
|
print("")
|
|
}
|