Initial commit: NetworkCity — network traffic as a neon city
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>
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
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("")
|
||||
}
|
||||
Reference in New Issue
Block a user