feat(monitoring): improve network activity metrics with live domain request rates and backend identifiers
This commit is contained in:
@@ -3,6 +3,6 @@
|
||||
*/
|
||||
export const commitinfo = {
|
||||
name: '@serve.zone/dcrouter',
|
||||
version: '13.20.2',
|
||||
version: '13.21.0',
|
||||
description: 'A multifaceted routing service handling mail and SMS delivery functions.'
|
||||
}
|
||||
|
||||
+23
-18
@@ -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({
|
||||
|
||||
@@ -79,7 +79,6 @@ export class OpsViewNetworkActivity extends DeesElement {
|
||||
// Subscribe and track unsubscribe functions
|
||||
const statsUnsubscribe = appstate.statsStatePart.select().subscribe((state) => {
|
||||
this.statsState = state;
|
||||
this.updateNetworkData();
|
||||
});
|
||||
this.rxSubscriptions.push(statsUnsubscribe);
|
||||
|
||||
@@ -560,6 +559,8 @@ export class OpsViewNetworkActivity extends DeesElement {
|
||||
'Throughput Out': this.formatBitsPerSecond(item.bytesOutPerSecond),
|
||||
'Transferred / min': this.formatBytes(totalBytesPerMin),
|
||||
'Connections': item.activeConnections,
|
||||
'Req/s': item.requestsPerSecond != null ? item.requestsPerSecond.toFixed(1) : '-',
|
||||
'Req/min': item.requestsLastMinute != null ? item.requestsLastMinute.toFixed(0) : '-',
|
||||
'Requests': item.requestCount?.toLocaleString() ?? '0',
|
||||
'Routes': item.routeCount,
|
||||
};
|
||||
@@ -583,7 +584,7 @@ export class OpsViewNetworkActivity extends DeesElement {
|
||||
return html`
|
||||
<dees-table
|
||||
.data=${backends}
|
||||
.rowKey=${'backend'}
|
||||
.rowKey=${'id'}
|
||||
.highlightUpdates=${'flash'}
|
||||
.displayFunction=${(item: interfaces.data.IBackendInfo) => {
|
||||
const totalErrors = item.connectErrors + item.handshakeErrors + item.requestErrors;
|
||||
@@ -707,6 +708,9 @@ export class OpsViewNetworkActivity extends DeesElement {
|
||||
}
|
||||
|
||||
const throughput = this.calculateThroughput();
|
||||
if (this.networkState.lastUpdated && now - this.networkState.lastUpdated > 3000) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Convert to Mbps (bytes * 8 / 1,000,000)
|
||||
const throughputInMbps = (throughput.in * 8) / 1000000;
|
||||
|
||||
Reference in New Issue
Block a user