Expose outbound traffic totals and simplify Direct chart breakdown
Build and Deploy Gateway / build-and-push (push) Successful in 20s
Build and Deploy Gateway / deploy (push) Successful in 13s

This commit is contained in:
2026-08-12 22:43:40 +03:00
parent 9d43e74d97
commit 72c085a5b8
10 changed files with 173 additions and 69 deletions
@@ -149,6 +149,11 @@ interface OutboundTrafficSample {
unknownBytes: string;
}
interface OutboundTrafficTotal extends OutboundTrafficSample {
singboxObservedAt: string | null;
directIpv4ObservedAt: string | null;
}
interface OutboundTrafficCursor {
signature: string;
routeEpoch: string;
@@ -709,6 +714,7 @@ export function createDeviceInventoryService({
const trafficCursorByMac = new Map<string, TrafficCursor>();
const outboundTrafficHistoryByDeviceId = new Map<string, OutboundTrafficSample[]>();
const outboundTrafficCursorByDeviceId = new Map<string, OutboundTrafficCursor>();
const outboundTrafficByDeviceId = new Map<string, OutboundTrafficTotal>();
let globalTrafficHistory: TrafficSample[] = [];
let globalTrafficCursor: TrafficCursor | null = null;
const hostnameAttempts = new Map<string, number>();
@@ -832,6 +838,15 @@ export function createDeviceInventoryService({
const current: OutboundTrafficCursor = { signature, routeEpoch, directEpoch, ...total };
const previous = outboundTrafficCursorByDeviceId.get(device.id);
outboundTrafficCursorByDeviceId.set(device.id, current);
if (observedAt) outboundTrafficByDeviceId.set(device.id, {
observedAt,
singboxObservedAt: routeObservedAt || null,
directIpv4ObservedAt: directObservedAt || null,
vpnBytes: total.vpn.toString(),
directTrackedBytes: total.directTracked.toString(),
directIpv4Bytes: total.directIpv4.toString(),
unknownBytes: total.unknown.toString(),
});
if (!previous || previous.signature === signature || !observedAt) continue;
const routeDelta = (value: bigint, before: bigint) => (
routeEpoch && routeEpoch === previous.routeEpoch && value > before ? value - before : 0n
@@ -852,6 +867,7 @@ export function createDeviceInventoryService({
if (!knownIds.has(deviceId)) {
outboundTrafficCursorByDeviceId.delete(deviceId);
outboundTrafficHistoryByDeviceId.delete(deviceId);
outboundTrafficByDeviceId.delete(deviceId);
}
}
}
@@ -919,6 +935,7 @@ export function createDeviceInventoryService({
proxyDownloadBytes: proxyTraffic?.downloadBytes || '0',
proxyTrafficObservedAt: proxyTraffic?.observedAt || null,
trafficHistory: trafficHistoryByMac.get(device.mac) || [],
outboundTraffic: outboundTrafficByDeviceId.get(device.id) || null,
outboundTrafficHistory: outboundTrafficHistoryByDeviceId.get(device.id) || [],
desiredPolicy: policy.desired,
appliedPolicy: policy.applied,