feat: Implement network metrics integration and UI updates for real-time data display
This commit is contained in:
@ -30,6 +30,9 @@ export class OpsViewNetwork extends DeesElement {
|
||||
@state()
|
||||
private statsState = appstate.statsStatePart.getState();
|
||||
|
||||
@state()
|
||||
private networkState = appstate.networkStatePart.getState();
|
||||
|
||||
@state()
|
||||
private selectedTimeRange: '1m' | '5m' | '15m' | '1h' | '24h' = '5m';
|
||||
|
||||
@ -48,7 +51,7 @@ export class OpsViewNetwork extends DeesElement {
|
||||
constructor() {
|
||||
super();
|
||||
this.subscribeToStateParts();
|
||||
this.generateMockData(); // TODO: Replace with real data from metrics
|
||||
this.updateNetworkData();
|
||||
}
|
||||
|
||||
private subscribeToStateParts() {
|
||||
@ -56,6 +59,11 @@ export class OpsViewNetwork extends DeesElement {
|
||||
this.statsState = state;
|
||||
this.updateNetworkData();
|
||||
});
|
||||
|
||||
appstate.networkStatePart.state.subscribe((state) => {
|
||||
this.networkState = state;
|
||||
this.updateNetworkData();
|
||||
});
|
||||
}
|
||||
|
||||
public static styles = [
|
||||
@ -221,6 +229,9 @@ export class OpsViewNetwork extends DeesElement {
|
||||
]}
|
||||
></dees-chart-area>
|
||||
|
||||
<!-- Top IPs Section -->
|
||||
${this.renderTopIPs()}
|
||||
|
||||
<!-- Requests Table -->
|
||||
<dees-table
|
||||
.data=${this.getFilteredRequests()}
|
||||
@ -290,7 +301,6 @@ export class OpsViewNetwork extends DeesElement {
|
||||
iconName: 'copy',
|
||||
action: async () => {
|
||||
await navigator.clipboard.writeText(request.id);
|
||||
// TODO: Implement toast notification when DeesToast.show is available
|
||||
console.log('Request ID copied to clipboard');
|
||||
}
|
||||
}
|
||||
@ -365,18 +375,17 @@ export class OpsViewNetwork extends DeesElement {
|
||||
}
|
||||
|
||||
private calculateRequestsPerSecond(): number {
|
||||
// TODO: Calculate from real data based on connection metrics
|
||||
// For now, return a calculated value based on active connections
|
||||
return Math.floor((this.statsState.serverStats?.activeConnections || 0) * 0.8);
|
||||
// Calculate from actual request data in the last minute
|
||||
const oneMinuteAgo = Date.now() - 60000;
|
||||
const recentRequests = this.networkRequests.filter(req => req.timestamp >= oneMinuteAgo);
|
||||
return Math.round(recentRequests.length / 60);
|
||||
}
|
||||
|
||||
private calculateThroughput(): { in: number; out: number } {
|
||||
// TODO: Calculate from real connection data
|
||||
// For now, return estimated values
|
||||
const activeConnections = this.statsState.serverStats?.activeConnections || 0;
|
||||
// Use real throughput data from network state
|
||||
return {
|
||||
in: activeConnections * 1024 * 10, // 10KB per connection estimate
|
||||
out: activeConnections * 1024 * 50, // 50KB per connection estimate
|
||||
in: this.networkState.throughputRate.bytesInPerSecond,
|
||||
out: this.networkState.throughputRate.bytesOutPerSecond,
|
||||
};
|
||||
}
|
||||
|
||||
@ -404,7 +413,6 @@ export class OpsViewNetwork extends DeesElement {
|
||||
name: 'View Details',
|
||||
iconName: 'magnifyingGlass',
|
||||
action: async () => {
|
||||
// TODO: Show connection details
|
||||
},
|
||||
},
|
||||
],
|
||||
@ -448,8 +456,6 @@ export class OpsViewNetwork extends DeesElement {
|
||||
name: 'Export Data',
|
||||
iconName: 'fileExport',
|
||||
action: async () => {
|
||||
// TODO: Export network data
|
||||
// TODO: Implement toast notification when DeesToast.show is available
|
||||
console.log('Export feature coming soon');
|
||||
},
|
||||
},
|
||||
@ -461,43 +467,90 @@ export class OpsViewNetwork extends DeesElement {
|
||||
private async refreshData() {
|
||||
this.isLoading = true;
|
||||
await appstate.statsStatePart.dispatchAction(appstate.fetchAllStatsAction, null);
|
||||
await appstate.networkStatePart.dispatchAction(appstate.fetchNetworkStatsAction, null);
|
||||
await this.updateNetworkData();
|
||||
this.isLoading = false;
|
||||
}
|
||||
|
||||
private renderTopIPs(): TemplateResult {
|
||||
if (this.networkState.topIPs.length === 0) {
|
||||
return html``;
|
||||
}
|
||||
|
||||
return html`
|
||||
<dees-table
|
||||
.data=${this.networkState.topIPs}
|
||||
.displayFunction=${(ipData: { ip: string; count: number }) => ({
|
||||
'IP Address': ipData.ip,
|
||||
'Connections': ipData.count,
|
||||
'Percentage': ((ipData.count / this.networkState.connections.length) * 100).toFixed(1) + '%',
|
||||
})}
|
||||
heading1="Top Connected IPs"
|
||||
heading2="IPs with most active connections"
|
||||
.pagination=${false}
|
||||
dataName="ip"
|
||||
></dees-table>
|
||||
`;
|
||||
}
|
||||
|
||||
private async updateNetworkData() {
|
||||
// TODO: Fetch real network data from the server
|
||||
// For now, using mock data
|
||||
this.generateMockData();
|
||||
// Convert connection data to network requests format
|
||||
if (this.networkState.connections.length > 0) {
|
||||
this.networkRequests = this.networkState.connections.map((conn, index) => ({
|
||||
id: conn.id,
|
||||
timestamp: conn.startTime,
|
||||
method: 'GET', // Default method for proxy connections
|
||||
url: '/',
|
||||
hostname: conn.remoteAddress,
|
||||
port: conn.protocol === 'https' ? 443 : 80,
|
||||
protocol: conn.protocol === 'https' || conn.protocol === 'http' ? conn.protocol : 'tcp',
|
||||
statusCode: conn.state === 'connected' ? 200 : undefined,
|
||||
duration: Date.now() - conn.startTime,
|
||||
bytesIn: conn.bytesReceived,
|
||||
bytesOut: conn.bytesSent,
|
||||
remoteIp: conn.remoteAddress,
|
||||
route: 'proxy',
|
||||
}));
|
||||
} else {
|
||||
this.networkRequests = [];
|
||||
}
|
||||
|
||||
// Generate traffic data based on request history
|
||||
this.updateTrafficData();
|
||||
}
|
||||
|
||||
private generateMockData() {
|
||||
// Generate mock network requests
|
||||
private updateTrafficData() {
|
||||
const now = Date.now();
|
||||
const protocols: Array<'http' | 'https' | 'tcp' | 'udp'> = ['http', 'https', 'tcp', 'udp'];
|
||||
const methods = ['GET', 'POST', 'PUT', 'DELETE', 'HEAD', 'OPTIONS'];
|
||||
const hosts = ['api.example.com', 'app.local', 'mail.server.com', 'dns.resolver.net'];
|
||||
const timeRanges = {
|
||||
'1m': 60 * 1000,
|
||||
'5m': 5 * 60 * 1000,
|
||||
'15m': 15 * 60 * 1000,
|
||||
'1h': 60 * 60 * 1000,
|
||||
'24h': 24 * 60 * 60 * 1000,
|
||||
};
|
||||
|
||||
this.networkRequests = Array.from({ length: 100 }, (_, i) => ({
|
||||
id: `req-${i}`,
|
||||
timestamp: now - (i * 5000), // 5 seconds apart
|
||||
method: methods[Math.floor(Math.random() * methods.length)],
|
||||
url: `/api/v1/resource/${Math.floor(Math.random() * 100)}`,
|
||||
hostname: hosts[Math.floor(Math.random() * hosts.length)],
|
||||
port: Math.random() > 0.5 ? 443 : 80,
|
||||
protocol: protocols[Math.floor(Math.random() * protocols.length)],
|
||||
statusCode: Math.random() > 0.8 ? 404 : 200,
|
||||
duration: Math.floor(Math.random() * 500),
|
||||
bytesIn: Math.floor(Math.random() * 10000),
|
||||
bytesOut: Math.floor(Math.random() * 50000),
|
||||
remoteIp: `192.168.${Math.floor(Math.random() * 255)}.${Math.floor(Math.random() * 255)}`,
|
||||
route: 'main-route',
|
||||
}));
|
||||
|
||||
// Generate traffic data for chart
|
||||
this.trafficData = Array.from({ length: 60 }, (_, i) => ({
|
||||
x: now - (i * 60000), // 1 minute intervals
|
||||
y: Math.floor(Math.random() * 100) + 50,
|
||||
})).reverse();
|
||||
const range = timeRanges[this.selectedTimeRange];
|
||||
const bucketSize = range / 60; // 60 data points
|
||||
|
||||
// Create buckets for traffic data
|
||||
const buckets = new Map<number, number>();
|
||||
|
||||
// Count requests per bucket
|
||||
this.networkRequests.forEach(req => {
|
||||
if (req.timestamp >= now - range) {
|
||||
const bucketIndex = Math.floor((now - req.timestamp) / bucketSize);
|
||||
const bucketTime = now - (bucketIndex * bucketSize);
|
||||
buckets.set(bucketTime, (buckets.get(bucketTime) || 0) + 1);
|
||||
}
|
||||
});
|
||||
|
||||
// Convert to chart data
|
||||
this.trafficData = Array.from({ length: 60 }, (_, i) => {
|
||||
const time = now - (i * bucketSize);
|
||||
return {
|
||||
x: time,
|
||||
y: buckets.get(time) || 0,
|
||||
};
|
||||
}).reverse();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user