feat(monitoring): improve network activity metrics with live domain request rates and backend identifiers

This commit is contained in:
2026-04-25 20:37:28 +00:00
parent 97017ede98
commit b3751abd17
18 changed files with 318 additions and 93 deletions
+23 -18
View File
@@ -512,15 +512,6 @@ export const fetchNetworkStatsAction = networkStatePart.createAction(async (stat
if (!context.identity) return currentState;
try {
// Fetch active connections using the existing endpoint
const connectionsRequest = new plugins.domtools.plugins.typedrequest.TypedRequest<
interfaces.requests.IReq_GetActiveConnections
>('/typedrequest', 'getActiveConnections');
const connectionsResponse = await connectionsRequest.fire({
identity: context.identity,
});
// Get network stats for throughput and IP data
const networkStatsRequest = new plugins.domtools.plugins.typedrequest.TypedRequest<
interfaces.requests.IReq_GetNetworkStats
@@ -533,22 +524,35 @@ export const fetchNetworkStatsAction = networkStatePart.createAction(async (stat
// Use the connections data for the connection list
// and network stats for throughput and IP analytics
const connectionsByIP: { [ip: string]: number } = {};
const throughputByIP = new Map<string, { in: number; out: number }>();
for (const item of networkStatsResponse.throughputByIP || []) {
throughputByIP.set(item.ip, { in: item.in, out: item.out });
}
// Build connectionsByIP from network stats if available
if (networkStatsResponse.connectionsByIP && Array.isArray(networkStatsResponse.connectionsByIP)) {
networkStatsResponse.connectionsByIP.forEach((item: { ip: string; count: number }) => {
connectionsByIP[item.ip] = item.count;
});
} else {
// Fallback: calculate from connections
connectionsResponse.connections.forEach(conn => {
const ip = conn.remoteAddress;
connectionsByIP[ip] = (connectionsByIP[ip] || 0) + 1;
});
}
const connections: interfaces.data.IConnectionInfo[] = Object.entries(connectionsByIP).map(([ip, count]) => {
const tp = throughputByIP.get(ip);
return {
id: `ip-${ip}`,
remoteAddress: ip,
localAddress: 'server',
startTime: 0,
protocol: 'https',
state: 'connected',
bytesReceived: tp?.in || 0,
bytesSent: tp?.out || 0,
connectionCount: count,
};
});
return {
connections: connectionsResponse.connections,
connections,
connectionsByIP,
throughputRate: networkStatsResponse.throughputRate || { bytesInPerSecond: 0, bytesOutPerSecond: 0 },
totalBytes: networkStatsResponse.totalDataTransferred
@@ -2589,7 +2593,7 @@ async function dispatchCombinedRefreshActionInner() {
email: true,
dns: true,
security: true,
network: currentView === 'network', // Only fetch network if on network view
network: currentView === 'network' && currentSubview === 'activity',
radius: true,
vpn: true,
},
@@ -2617,7 +2621,7 @@ async function dispatchCombinedRefreshActionInner() {
// Build connectionsByIP from connectionDetails (now populated with real per-IP data)
network.connectionDetails.forEach(conn => {
connectionsByIP[conn.remoteAddress] = (connectionsByIP[conn.remoteAddress] || 0) + 1;
connectionsByIP[conn.remoteAddress] = (connectionsByIP[conn.remoteAddress] || 0) + (conn.connectionCount || 1);
});
// Build connections from connectionDetails (real per-IP aggregates)
@@ -2630,6 +2634,7 @@ async function dispatchCombinedRefreshActionInner() {
state: conn.state as any,
bytesReceived: conn.bytesIn,
bytesSent: conn.bytesOut,
connectionCount: conn.connectionCount,
}));
networkStatePart.setState({