fix(metrics): fix metrics
This commit is contained in:
@ -46,7 +46,7 @@
|
|||||||
"@push.rocks/smartnetwork": "^4.0.2",
|
"@push.rocks/smartnetwork": "^4.0.2",
|
||||||
"@push.rocks/smartpath": "^5.0.5",
|
"@push.rocks/smartpath": "^5.0.5",
|
||||||
"@push.rocks/smartpromise": "^4.0.3",
|
"@push.rocks/smartpromise": "^4.0.3",
|
||||||
"@push.rocks/smartproxy": "^19.6.7",
|
"@push.rocks/smartproxy": "^19.6.12",
|
||||||
"@push.rocks/smartrequest": "^2.1.0",
|
"@push.rocks/smartrequest": "^2.1.0",
|
||||||
"@push.rocks/smartrule": "^2.0.1",
|
"@push.rocks/smartrule": "^2.0.1",
|
||||||
"@push.rocks/smartrx": "^3.0.10",
|
"@push.rocks/smartrx": "^3.0.10",
|
||||||
|
10
pnpm-lock.yaml
generated
10
pnpm-lock.yaml
generated
@ -72,8 +72,8 @@ importers:
|
|||||||
specifier: ^4.0.3
|
specifier: ^4.0.3
|
||||||
version: 4.2.3
|
version: 4.2.3
|
||||||
'@push.rocks/smartproxy':
|
'@push.rocks/smartproxy':
|
||||||
specifier: ^19.6.7
|
specifier: ^19.6.12
|
||||||
version: 19.6.7(@aws-sdk/credential-providers@3.817.0)(socks@2.8.4)
|
version: 19.6.12(@aws-sdk/credential-providers@3.817.0)(socks@2.8.4)
|
||||||
'@push.rocks/smartrequest':
|
'@push.rocks/smartrequest':
|
||||||
specifier: ^2.1.0
|
specifier: ^2.1.0
|
||||||
version: 2.1.0
|
version: 2.1.0
|
||||||
@ -1110,8 +1110,8 @@ packages:
|
|||||||
'@push.rocks/smartpromise@4.2.3':
|
'@push.rocks/smartpromise@4.2.3':
|
||||||
resolution: {integrity: sha512-Ycg/TJR+tMt+S3wSFurOpEoW6nXv12QBtKXgBcjMZ4RsdO28geN46U09osPn9N9WuwQy1PkmTV5J/V4F9U8qEw==}
|
resolution: {integrity: sha512-Ycg/TJR+tMt+S3wSFurOpEoW6nXv12QBtKXgBcjMZ4RsdO28geN46U09osPn9N9WuwQy1PkmTV5J/V4F9U8qEw==}
|
||||||
|
|
||||||
'@push.rocks/smartproxy@19.6.7':
|
'@push.rocks/smartproxy@19.6.12':
|
||||||
resolution: {integrity: sha512-tC/zqUzSo4/SPqp52UrSe3cPR/YtyZiFC/HhYktCNfDXaWPqxY3ioViTwC2i6tb/6T6LmNdRJUOXxGFAz1j1cQ==}
|
resolution: {integrity: sha512-prA5cXpuZaDNWURpxRsxtbqz4SvBK38wbDPZgAHOsLYccAJR9WNLXF65v7tlF2CUJdjhWhaOyY5MaYF1wr928A==}
|
||||||
|
|
||||||
'@push.rocks/smartpuppeteer@2.0.5':
|
'@push.rocks/smartpuppeteer@2.0.5':
|
||||||
resolution: {integrity: sha512-yK/qSeWVHIGWRp3c8S5tfdGP6WCKllZC4DR8d8CQlEjszOSBmHtlTdyyqOMBZ/BA4kd+eU5f3A1r4K2tGYty1g==}
|
resolution: {integrity: sha512-yK/qSeWVHIGWRp3c8S5tfdGP6WCKllZC4DR8d8CQlEjszOSBmHtlTdyyqOMBZ/BA4kd+eU5f3A1r4K2tGYty1g==}
|
||||||
@ -6476,7 +6476,7 @@ snapshots:
|
|||||||
|
|
||||||
'@push.rocks/smartpromise@4.2.3': {}
|
'@push.rocks/smartpromise@4.2.3': {}
|
||||||
|
|
||||||
'@push.rocks/smartproxy@19.6.7(@aws-sdk/credential-providers@3.817.0)(socks@2.8.4)':
|
'@push.rocks/smartproxy@19.6.12(@aws-sdk/credential-providers@3.817.0)(socks@2.8.4)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@push.rocks/lik': 6.2.2
|
'@push.rocks/lik': 6.2.2
|
||||||
'@push.rocks/smartacme': 8.0.0(@aws-sdk/credential-providers@3.817.0)(socks@2.8.4)
|
'@push.rocks/smartacme': 8.0.0(@aws-sdk/credential-providers@3.817.0)(socks@2.8.4)
|
||||||
|
@ -33,11 +33,6 @@ export class OpsViewNetwork extends DeesElement {
|
|||||||
@state()
|
@state()
|
||||||
private networkState = appstate.networkStatePart.getState();
|
private networkState = appstate.networkStatePart.getState();
|
||||||
|
|
||||||
@state()
|
|
||||||
private selectedTimeRange: '1m' | '5m' | '15m' | '1h' | '24h' = '5m';
|
|
||||||
|
|
||||||
@state()
|
|
||||||
private selectedProtocol: 'all' | 'http' | 'https' | 'smtp' | 'dns' = 'all';
|
|
||||||
|
|
||||||
@state()
|
@state()
|
||||||
private networkRequests: INetworkRequest[] = [];
|
private networkRequests: INetworkRequest[] = [];
|
||||||
@ -48,9 +43,6 @@ export class OpsViewNetwork extends DeesElement {
|
|||||||
@state()
|
@state()
|
||||||
private trafficDataOut: Array<{ x: string | number; y: number }> = [];
|
private trafficDataOut: Array<{ x: string | number; y: number }> = [];
|
||||||
|
|
||||||
@state()
|
|
||||||
private isLoading = false;
|
|
||||||
|
|
||||||
private lastTrafficUpdateTime = 0;
|
private lastTrafficUpdateTime = 0;
|
||||||
private trafficUpdateInterval = 1000; // Update every 1 second
|
private trafficUpdateInterval = 1000; // Update every 1 second
|
||||||
private requestCountHistory = new Map<number, number>(); // Track requests per time bucket
|
private requestCountHistory = new Map<number, number>(); // Track requests per time bucket
|
||||||
@ -86,16 +78,9 @@ export class OpsViewNetwork extends DeesElement {
|
|||||||
|
|
||||||
private initializeTrafficData() {
|
private initializeTrafficData() {
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
const timeRanges = {
|
// Fixed 5 minute time range
|
||||||
'1m': 60 * 1000,
|
const range = 5 * 60 * 1000; // 5 minutes
|
||||||
'5m': 5 * 60 * 1000,
|
const bucketSize = range / 60; // 60 data points
|
||||||
'15m': 15 * 60 * 1000,
|
|
||||||
'1h': 60 * 60 * 1000,
|
|
||||||
'24h': 24 * 60 * 60 * 1000,
|
|
||||||
};
|
|
||||||
|
|
||||||
const range = timeRanges[this.selectedTimeRange];
|
|
||||||
const bucketSize = range / 60;
|
|
||||||
|
|
||||||
// Initialize with empty data points for both in and out
|
// Initialize with empty data points for both in and out
|
||||||
const emptyData = Array.from({ length: 60 }, (_, i) => {
|
const emptyData = Array.from({ length: 60 }, (_, i) => {
|
||||||
@ -127,26 +112,6 @@ export class OpsViewNetwork extends DeesElement {
|
|||||||
gap: 24px;
|
gap: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.controlBar {
|
|
||||||
display: flex;
|
|
||||||
gap: 16px;
|
|
||||||
align-items: center;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
margin-bottom: 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.controlGroup {
|
|
||||||
display: flex;
|
|
||||||
gap: 8px;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.controlLabel {
|
|
||||||
font-size: 14px;
|
|
||||||
color: ${cssManager.bdTheme('#666', '#999')};
|
|
||||||
margin-right: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
dees-statsgrid {
|
dees-statsgrid {
|
||||||
margin-bottom: 24px;
|
margin-bottom: 24px;
|
||||||
}
|
}
|
||||||
@ -220,47 +185,6 @@ export class OpsViewNetwork extends DeesElement {
|
|||||||
<ops-sectionheading>Network Activity</ops-sectionheading>
|
<ops-sectionheading>Network Activity</ops-sectionheading>
|
||||||
|
|
||||||
<div class="networkContainer">
|
<div class="networkContainer">
|
||||||
<!-- Control Bar -->
|
|
||||||
<div class="controlBar">
|
|
||||||
<div class="controlGroup">
|
|
||||||
<span class="controlLabel">Time Range:</span>
|
|
||||||
<dees-button-group>
|
|
||||||
${(['1m', '5m', '15m', '1h', '24h'] as const).map(range => html`
|
|
||||||
<dees-button
|
|
||||||
@click=${() => this.handleTimeRangeChange(range)}
|
|
||||||
.type=${this.selectedTimeRange === range ? 'highlighted' : 'normal'}
|
|
||||||
>
|
|
||||||
${range}
|
|
||||||
</dees-button>
|
|
||||||
`)}
|
|
||||||
</dees-button-group>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="controlGroup">
|
|
||||||
<span class="controlLabel">Protocol:</span>
|
|
||||||
<dees-input-dropdown
|
|
||||||
.options=${[
|
|
||||||
{ key: 'all', label: 'All Protocols' },
|
|
||||||
{ key: 'http', label: 'HTTP' },
|
|
||||||
{ key: 'https', label: 'HTTPS' },
|
|
||||||
{ key: 'smtp', label: 'SMTP' },
|
|
||||||
{ key: 'dns', label: 'DNS' },
|
|
||||||
]}
|
|
||||||
.selectedOption=${{ key: this.selectedProtocol, label: this.getProtocolLabel(this.selectedProtocol) }}
|
|
||||||
@selectedOption=${(e: CustomEvent) => this.selectedProtocol = e.detail.key}
|
|
||||||
></dees-input-dropdown>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style="margin-left: auto;">
|
|
||||||
<dees-button
|
|
||||||
@click=${() => this.refreshData()}
|
|
||||||
.disabled=${this.isLoading}
|
|
||||||
>
|
|
||||||
${this.isLoading ? html`<dees-spinner size="small"></dees-spinner>` : 'Refresh'}
|
|
||||||
</dees-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Stats Grid -->
|
<!-- Stats Grid -->
|
||||||
${this.renderNetworkStats()}
|
${this.renderNetworkStats()}
|
||||||
|
|
||||||
@ -299,7 +223,7 @@ export class OpsViewNetwork extends DeesElement {
|
|||||||
|
|
||||||
<!-- Requests Table -->
|
<!-- Requests Table -->
|
||||||
<dees-table
|
<dees-table
|
||||||
.data=${this.getFilteredRequests()}
|
.data=${this.networkRequests}
|
||||||
.displayFunction=${(req: INetworkRequest) => ({
|
.displayFunction=${(req: INetworkRequest) => ({
|
||||||
Time: new Date(req.timestamp).toLocaleTimeString(),
|
Time: new Date(req.timestamp).toLocaleTimeString(),
|
||||||
Protocol: html`<span class="protocolBadge ${req.protocol}">${req.protocol.toUpperCase()}</span>`,
|
Protocol: html`<span class="protocolBadge ${req.protocol}">${req.protocol.toUpperCase()}</span>`,
|
||||||
@ -322,7 +246,7 @@ export class OpsViewNetwork extends DeesElement {
|
|||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
heading1="Recent Network Activity"
|
heading1="Recent Network Activity"
|
||||||
heading2="Last ${this.selectedTimeRange} of network requests"
|
heading2="Recent network requests"
|
||||||
searchable
|
searchable
|
||||||
.pagination=${true}
|
.pagination=${true}
|
||||||
.paginationSize=${50}
|
.paginationSize=${50}
|
||||||
@ -373,22 +297,6 @@ export class OpsViewNetwork extends DeesElement {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private getFilteredRequests(): INetworkRequest[] {
|
|
||||||
if (this.selectedProtocol === 'all') {
|
|
||||||
return this.networkRequests;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Map protocol filter to actual protocol values
|
|
||||||
const protocolMap: Record<string, string[]> = {
|
|
||||||
'http': ['http'],
|
|
||||||
'https': ['https'],
|
|
||||||
'smtp': ['tcp'], // SMTP runs over TCP
|
|
||||||
'dns': ['udp'], // DNS typically runs over UDP
|
|
||||||
};
|
|
||||||
|
|
||||||
const allowedProtocols = protocolMap[this.selectedProtocol] || [this.selectedProtocol];
|
|
||||||
return this.networkRequests.filter(req => allowedProtocols.includes(req.protocol));
|
|
||||||
}
|
|
||||||
|
|
||||||
private renderStatus(statusCode?: number): TemplateResult {
|
private renderStatus(statusCode?: number): TemplateResult {
|
||||||
if (!statusCode) {
|
if (!statusCode) {
|
||||||
@ -406,16 +314,6 @@ export class OpsViewNetwork extends DeesElement {
|
|||||||
return url.substring(0, maxLength - 3) + '...';
|
return url.substring(0, maxLength - 3) + '...';
|
||||||
}
|
}
|
||||||
|
|
||||||
private getProtocolLabel(protocol: string): string {
|
|
||||||
const labels: Record<string, string> = {
|
|
||||||
'all': 'All Protocols',
|
|
||||||
'http': 'HTTP',
|
|
||||||
'https': 'HTTPS',
|
|
||||||
'smtp': 'SMTP',
|
|
||||||
'dns': 'DNS',
|
|
||||||
};
|
|
||||||
return labels[protocol] || protocol.toUpperCase();
|
|
||||||
}
|
|
||||||
|
|
||||||
private formatNumber(num: number): string {
|
private formatNumber(num: number): string {
|
||||||
if (num >= 1000000) {
|
if (num >= 1000000) {
|
||||||
@ -554,26 +452,22 @@ 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 {
|
private renderTopIPs(): TemplateResult {
|
||||||
if (this.networkState.topIPs.length === 0) {
|
if (this.networkState.topIPs.length === 0) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Calculate total connections across all top IPs
|
||||||
|
const totalConnections = this.networkState.topIPs.reduce((sum, ipData) => sum + ipData.count, 0);
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<dees-table
|
<dees-table
|
||||||
.data=${this.networkState.topIPs}
|
.data=${this.networkState.topIPs}
|
||||||
.displayFunction=${(ipData: { ip: string; count: number }) => ({
|
.displayFunction=${(ipData: { ip: string; count: number }) => ({
|
||||||
'IP Address': ipData.ip,
|
'IP Address': ipData.ip,
|
||||||
'Connections': ipData.count,
|
'Connections': ipData.count,
|
||||||
'Percentage': ((ipData.count / this.networkState.connections.length) * 100).toFixed(1) + '%',
|
'Percentage': totalConnections > 0 ? ((ipData.count / totalConnections) * 100).toFixed(1) + '%' : '0%',
|
||||||
})}
|
})}
|
||||||
heading1="Top Connected IPs"
|
heading1="Top Connected IPs"
|
||||||
heading2="IPs with most active connections"
|
heading2="IPs with most active connections"
|
||||||
@ -611,16 +505,9 @@ export class OpsViewNetwork extends DeesElement {
|
|||||||
|
|
||||||
private updateTrafficData() {
|
private updateTrafficData() {
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
const timeRanges = {
|
// Fixed 5 minute time range
|
||||||
'1m': 60 * 1000,
|
const range = 5 * 60 * 1000; // 5 minutes
|
||||||
'5m': 5 * 60 * 1000,
|
const bucketSize = range / 60; // 60 data points // 60 data points
|
||||||
'15m': 15 * 60 * 1000,
|
|
||||||
'1h': 60 * 60 * 1000,
|
|
||||||
'24h': 24 * 60 * 60 * 1000,
|
|
||||||
};
|
|
||||||
|
|
||||||
const range = timeRanges[this.selectedTimeRange];
|
|
||||||
const bucketSize = range / 60; // 60 data points
|
|
||||||
|
|
||||||
// Check if enough time has passed to add a new data point
|
// Check if enough time has passed to add a new data point
|
||||||
const timeSinceLastUpdate = now - this.lastTrafficUpdateTime;
|
const timeSinceLastUpdate = now - this.lastTrafficUpdateTime;
|
||||||
@ -707,10 +594,4 @@ export class OpsViewNetwork extends DeesElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleTimeRangeChange(range: '1m' | '5m' | '15m' | '1h' | '24h') {
|
|
||||||
this.selectedTimeRange = range;
|
|
||||||
// Reinitialize traffic data for new time range
|
|
||||||
this.initializeTrafficData();
|
|
||||||
this.updateNetworkData();
|
|
||||||
}
|
|
||||||
}
|
}
|
Reference in New Issue
Block a user