fix(metrics): fix metrics

This commit is contained in:
Juergen Kunz
2025-06-23 00:19:47 +00:00
parent d24e51117d
commit 28cbf84f97
3 changed files with 188 additions and 185 deletions

View File

@ -43,7 +43,10 @@ export class OpsViewNetwork extends DeesElement {
private networkRequests: INetworkRequest[] = [];
@state()
private trafficData: Array<{ x: string | number; y: number }> = [];
private trafficDataIn: Array<{ x: string | number; y: number }> = [];
@state()
private trafficDataOut: Array<{ x: string | number; y: number }> = [];
@state()
private isLoading = false;
@ -52,11 +55,9 @@ export class OpsViewNetwork extends DeesElement {
private trafficUpdateInterval = 1000; // Update every 1 second
private requestCountHistory = new Map<number, number>(); // Track requests per time bucket
private trafficUpdateTimer: any = null;
private requestsPerSecHistory: number[] = []; // Track requests/sec over time for trend
// Track bytes for calculating true per-second throughput
private lastBytesIn = 0;
private lastBytesOut = 0;
private lastBytesSampleTime = 0;
// Removed byte tracking - now using real-time data from SmartProxy
constructor() {
super();
@ -96,8 +97,8 @@ export class OpsViewNetwork extends DeesElement {
const range = timeRanges[this.selectedTimeRange];
const bucketSize = range / 60;
// Initialize with empty data points
this.trafficData = Array.from({ length: 60 }, (_, i) => {
// Initialize with empty data points for both in and out
const emptyData = Array.from({ length: 60 }, (_, i) => {
const time = now - ((59 - i) * bucketSize);
return {
x: new Date(time).toISOString(),
@ -105,6 +106,9 @@ export class OpsViewNetwork extends DeesElement {
};
});
this.trafficDataIn = [...emptyData];
this.trafficDataOut = emptyData.map(point => ({ ...point }));
this.lastTrafficUpdateTime = now;
}
@ -265,11 +269,29 @@ export class OpsViewNetwork extends DeesElement {
.label=${'Network Traffic'}
.series=${[
{
name: 'Throughput (Mbps)',
data: this.trafficData,
name: 'Inbound',
data: this.trafficDataIn,
color: '#22c55e', // Green for download
},
{
name: 'Outbound',
data: this.trafficDataOut,
color: '#8b5cf6', // Purple for upload
}
]}
.yAxisFormatter=${(val: number) => `${val} Mbps`}
.stacked=${false}
.yAxisFormatter=${(val: number) => `${val} Mbit/s`}
.tooltipFormatter=${(point: any) => {
const mbps = point.y || 0;
const seriesName = point.series?.name || 'Throughput';
const timestamp = new Date(point.x).toLocaleTimeString();
return `
<div style="padding: 8px;">
<div style="font-weight: bold; margin-bottom: 4px;">${timestamp}</div>
<div>${seriesName}: ${mbps.toFixed(2)} Mbit/s</div>
</div>
`;
}}
></dees-chart-area>
<!-- Top IPs Section -->
@ -416,12 +438,34 @@ export class OpsViewNetwork extends DeesElement {
return `${size.toFixed(1)} ${units[unitIndex]}`;
}
private formatBitsPerSecond(bytesPerSecond: number): string {
const bitsPerSecond = bytesPerSecond * 8; // Convert bytes to bits
const units = ['bit/s', 'kbit/s', 'Mbit/s', 'Gbit/s'];
let size = bitsPerSecond;
let unitIndex = 0;
while (size >= 1000 && unitIndex < units.length - 1) {
size /= 1000; // Use 1000 for bits (not 1024)
unitIndex++;
}
return `${size.toFixed(1)} ${units[unitIndex]}`;
}
private calculateRequestsPerSecond(): number {
// 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);
const reqPerSec = Math.round(recentRequests.length / 60);
// Track history for trend (keep last 20 values)
this.requestsPerSecHistory.push(reqPerSec);
if (this.requestsPerSecHistory.length > 20) {
this.requestsPerSecHistory.shift();
}
return reqPerSec;
}
private calculateThroughput(): { in: number; out: number } {
@ -437,12 +481,12 @@ export class OpsViewNetwork extends DeesElement {
const throughput = this.calculateThroughput();
const activeConnections = this.statsState.serverStats?.activeConnections || 0;
// Use actual traffic data for trends (last 20 points)
const trendData = this.trafficData.slice(-20).map(point => point.y);
// Use request count history for the requests/sec trend
const trendData = [...this.requestsPerSecHistory];
// If we don't have enough data, pad with the current value
// If we don't have enough data, pad with zeros
while (trendData.length < 20) {
trendData.unshift(reqPerSec);
trendData.unshift(0);
}
const tiles: IStatsTile[] = [
@ -471,13 +515,13 @@ export class OpsViewNetwork extends DeesElement {
icon: 'chartLine',
color: '#3b82f6',
trendData: trendData,
description: `${this.formatNumber(reqPerSec)} req/s`,
description: `Average over last minute`,
},
{
id: 'throughputIn',
title: 'Throughput In',
value: this.formatBytes(throughput.in),
unit: '/s',
value: this.formatBitsPerSecond(throughput.in),
unit: '',
type: 'number',
icon: 'download',
color: '#22c55e',
@ -485,8 +529,8 @@ export class OpsViewNetwork extends DeesElement {
{
id: 'throughputOut',
title: 'Throughput Out',
value: this.formatBytes(throughput.out),
unit: '/s',
value: this.formatBitsPerSecond(throughput.out),
unit: '',
type: 'number',
icon: 'upload',
color: '#8b5cf6',
@ -586,77 +630,65 @@ export class OpsViewNetwork extends DeesElement {
networkRequestsCount: this.networkRequests.length,
timeSinceLastUpdate,
shouldAddNewPoint,
currentDataPoints: this.trafficData.length
currentDataPoints: this.trafficDataIn.length
});
if (!shouldAddNewPoint && this.trafficData.length > 0) {
if (!shouldAddNewPoint && this.trafficDataIn.length > 0) {
// Not enough time has passed, don't update
return;
}
// Calculate actual per-second throughput by tracking deltas
let throughputMbps = 0;
// Use real-time throughput data from SmartProxy (same as throughput tiles)
const throughput = this.calculateThroughput();
// Get total bytes from all active connections
let currentBytesIn = 0;
let currentBytesOut = 0;
// Convert to Mbps (bytes * 8 / 1,000,000)
const throughputInMbps = (throughput.in * 8) / 1000000;
const throughputOutMbps = (throughput.out * 8) / 1000000;
this.networkRequests.forEach(req => {
currentBytesIn += req.bytesIn;
currentBytesOut += req.bytesOut;
console.log('Throughput calculation:', {
bytesInPerSecond: throughput.in,
bytesOutPerSecond: throughput.out,
throughputInMbps,
throughputOutMbps,
throughputTileValue: `${this.formatBitsPerSecond(throughput.in)} IN, ${this.formatBitsPerSecond(throughput.out)} OUT`
});
// If we have a previous sample, calculate the delta
if (this.lastBytesSampleTime > 0) {
const timeDelta = (now - this.lastBytesSampleTime) / 1000; // Convert to seconds
const bytesInDelta = Math.max(0, currentBytesIn - this.lastBytesIn);
const bytesOutDelta = Math.max(0, currentBytesOut - this.lastBytesOut);
// Calculate bytes per second for this interval
const bytesPerSecond = (bytesInDelta + bytesOutDelta) / timeDelta;
// Convert to Mbps (1 Mbps = 125000 bytes/second)
throughputMbps = bytesPerSecond / 125000;
console.log('Throughput calculation:', {
timeDelta,
bytesInDelta,
bytesOutDelta,
bytesPerSecond,
throughputMbps
});
}
// Update last sample values
this.lastBytesIn = currentBytesIn;
this.lastBytesOut = currentBytesOut;
this.lastBytesSampleTime = now;
if (this.trafficData.length === 0) {
if (this.trafficDataIn.length === 0) {
// Initialize if empty
this.initializeTrafficData();
} else {
// Add new data point and remove oldest if we have 60 points
const newDataPoint = {
x: new Date(now).toISOString(),
y: Math.round(throughputMbps * 10) / 10 // Round to 1 decimal place
// Add new data points for both in and out
const timestamp = new Date(now).toISOString();
const newDataPointIn = {
x: timestamp,
y: Math.round(throughputInMbps * 10) / 10 // Round to 1 decimal place
};
// Create new array with existing data plus new point
const newTrafficData = [...this.trafficData, newDataPoint];
const newDataPointOut = {
x: timestamp,
y: Math.round(throughputOutMbps * 10) / 10 // Round to 1 decimal place
};
// Create new arrays with existing data plus new points
const newTrafficDataIn = [...this.trafficDataIn, newDataPointIn];
const newTrafficDataOut = [...this.trafficDataOut, newDataPointOut];
// Keep only the last 60 points
if (newTrafficData.length > 60) {
newTrafficData.shift(); // Remove oldest point
if (newTrafficDataIn.length > 60) {
newTrafficDataIn.shift(); // Remove oldest point
newTrafficDataOut.shift();
}
this.trafficData = newTrafficData;
this.trafficDataIn = newTrafficDataIn;
this.trafficDataOut = newTrafficDataOut;
this.lastTrafficUpdateTime = now;
console.log('Added new traffic data point:', {
timestamp: newDataPoint.x,
throughputMbps: newDataPoint.y,
totalPoints: this.trafficData.length
console.log('Added new traffic data points:', {
timestamp: timestamp,
throughputInMbps: newDataPointIn.y,
throughputOutMbps: newDataPointOut.y,
totalPoints: this.trafficDataIn.length
});
}
}