feat(monitoring): add frontend and backend protocol distribution metrics to network stats
This commit is contained in:
@@ -1,5 +1,13 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 2026-04-04 - 12.9.0 - feat(monitoring)
|
||||||
|
add frontend and backend protocol distribution metrics to network stats
|
||||||
|
|
||||||
|
- Expose frontend and backend protocol distribution data in monitoring metrics, stats responses, and shared interfaces.
|
||||||
|
- Render protocol distribution donut charts in the ops network view using the new stats fields.
|
||||||
|
- Preserve existing stored certificate IDs when updating certificate records by domain.
|
||||||
|
- Bump @design.estate/dees-catalog to ^3.55.5 for the new chart component support.
|
||||||
|
|
||||||
## 2026-04-04 - 12.8.1 - fix(ops-view-routes)
|
## 2026-04-04 - 12.8.1 - fix(ops-view-routes)
|
||||||
correct route form dropdown selection handling for security profiles and network targets
|
correct route form dropdown selection handling for security profiles and network targets
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,7 @@
|
|||||||
"@api.global/typedserver": "^8.4.6",
|
"@api.global/typedserver": "^8.4.6",
|
||||||
"@api.global/typedsocket": "^4.1.2",
|
"@api.global/typedsocket": "^4.1.2",
|
||||||
"@apiclient.xyz/cloudflare": "^7.1.0",
|
"@apiclient.xyz/cloudflare": "^7.1.0",
|
||||||
"@design.estate/dees-catalog": "^3.55.1",
|
"@design.estate/dees-catalog": "^3.55.5",
|
||||||
"@design.estate/dees-element": "^2.2.4",
|
"@design.estate/dees-element": "^2.2.4",
|
||||||
"@push.rocks/lik": "^6.4.0",
|
"@push.rocks/lik": "^6.4.0",
|
||||||
"@push.rocks/projectinfo": "^5.1.0",
|
"@push.rocks/projectinfo": "^5.1.0",
|
||||||
|
|||||||
43
pnpm-lock.yaml
generated
43
pnpm-lock.yaml
generated
@@ -24,8 +24,8 @@ importers:
|
|||||||
specifier: ^7.1.0
|
specifier: ^7.1.0
|
||||||
version: 7.1.0
|
version: 7.1.0
|
||||||
'@design.estate/dees-catalog':
|
'@design.estate/dees-catalog':
|
||||||
specifier: ^3.55.1
|
specifier: ^3.55.5
|
||||||
version: 3.55.1(@tiptap/pm@2.27.2)
|
version: 3.55.5(@tiptap/pm@2.27.2)
|
||||||
'@design.estate/dees-element':
|
'@design.estate/dees-element':
|
||||||
specifier: ^2.2.4
|
specifier: ^2.2.4
|
||||||
version: 2.2.4
|
version: 2.2.4
|
||||||
@@ -350,8 +350,8 @@ packages:
|
|||||||
'@configvault.io/interfaces@1.0.17':
|
'@configvault.io/interfaces@1.0.17':
|
||||||
resolution: {integrity: sha512-bEcCUR2VBDJsTin8HQh8Uw/mlYl2v8A3jMIaQ+MTB9Hrqd6CZL2dL7iJdWyFl/3EIX+LDxWFR+Oq7liIq7w+1Q==}
|
resolution: {integrity: sha512-bEcCUR2VBDJsTin8HQh8Uw/mlYl2v8A3jMIaQ+MTB9Hrqd6CZL2dL7iJdWyFl/3EIX+LDxWFR+Oq7liIq7w+1Q==}
|
||||||
|
|
||||||
'@design.estate/dees-catalog@3.55.1':
|
'@design.estate/dees-catalog@3.55.5':
|
||||||
resolution: {integrity: sha512-UXBC68Dg+L2cGJynvrXyaJATlSLnmiA5SMrE1SWVcp2H1niXqHph6KVi9+E52YSLoEmsCS23cf+XjUjoRNgZTw==}
|
resolution: {integrity: sha512-NAMUkTVqdZZmwI/g1xKOxOYM9QUd9FHODh6MYkP6LhLjD0NOGh3bITCnNN9Z3x8/mI7vQQOlSe9tyTtxCP1itQ==}
|
||||||
|
|
||||||
'@design.estate/dees-comms@1.0.30':
|
'@design.estate/dees-comms@1.0.30':
|
||||||
resolution: {integrity: sha512-KchMlklJfKAjQiJiR0xmofXtQ27VgZtBIxcMwPE9d+h3jJRv+lPZxzBQVOM0eyM0uS44S5vJMZ11IeV4uDXSHg==}
|
resolution: {integrity: sha512-KchMlklJfKAjQiJiR0xmofXtQ27VgZtBIxcMwPE9d+h3jJRv+lPZxzBQVOM0eyM0uS44S5vJMZ11IeV4uDXSHg==}
|
||||||
@@ -2516,6 +2516,9 @@ packages:
|
|||||||
ecdsa-sig-formatter@1.0.11:
|
ecdsa-sig-formatter@1.0.11:
|
||||||
resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==}
|
resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==}
|
||||||
|
|
||||||
|
echarts@5.6.0:
|
||||||
|
resolution: {integrity: sha512-oTbVTsXfKuEhxftHqL5xprgLoc0k7uScAwtryCgWF6hPYFLRwOUHiFmHGCBKP5NPFNkDVopOieyUqYGH8Fa3kA==}
|
||||||
|
|
||||||
emoji-regex@8.0.0:
|
emoji-regex@8.0.0:
|
||||||
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
|
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
|
||||||
|
|
||||||
@@ -2866,8 +2869,8 @@ packages:
|
|||||||
humanize-ms@1.2.1:
|
humanize-ms@1.2.1:
|
||||||
resolution: {integrity: sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=}
|
resolution: {integrity: sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=}
|
||||||
|
|
||||||
ibantools@4.5.1:
|
ibantools@4.5.2:
|
||||||
resolution: {integrity: sha512-DfKQpLlFq9yEUIEnFuCJzss3XavD7iHZTU5PyqXiAJ+rmaMp+NFP3hboumHKuK8nZjuOJg93WemTzcQ5b9jOZA==}
|
resolution: {integrity: sha512-is+8TgZcKS/AMv/z9nW1zz0bhjhoyjpA1p0nc3A6GkW/InOdcQiUZpkufADzh/aO/LY/TOD/P3oPWncNRn5QMA==}
|
||||||
|
|
||||||
iconv-lite@0.4.24:
|
iconv-lite@0.4.24:
|
||||||
resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==}
|
resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==}
|
||||||
@@ -4068,6 +4071,9 @@ packages:
|
|||||||
tslib@1.14.1:
|
tslib@1.14.1:
|
||||||
resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==}
|
resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==}
|
||||||
|
|
||||||
|
tslib@2.3.0:
|
||||||
|
resolution: {integrity: sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==}
|
||||||
|
|
||||||
tslib@2.8.1:
|
tslib@2.8.1:
|
||||||
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
|
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
|
||||||
|
|
||||||
@@ -4315,6 +4321,9 @@ packages:
|
|||||||
zod@3.25.76:
|
zod@3.25.76:
|
||||||
resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==}
|
resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==}
|
||||||
|
|
||||||
|
zrender@5.6.1:
|
||||||
|
resolution: {integrity: sha512-OFXkDJKcrlx5su2XbzJvj/34Q3m6PvyCZkVPHGYpcCJ52ek4U/ymZyfuV1nKE23AyBJ51E/6Yr0mhZ7xGTO4ag==}
|
||||||
|
|
||||||
zwitch@2.0.4:
|
zwitch@2.0.4:
|
||||||
resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
|
resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
|
||||||
|
|
||||||
@@ -4342,7 +4351,7 @@ snapshots:
|
|||||||
'@api.global/typedrequest-interfaces': 3.0.19
|
'@api.global/typedrequest-interfaces': 3.0.19
|
||||||
'@api.global/typedsocket': 4.1.2(@push.rocks/smartserve@2.0.3)
|
'@api.global/typedsocket': 4.1.2(@push.rocks/smartserve@2.0.3)
|
||||||
'@cloudflare/workers-types': 4.20260317.1
|
'@cloudflare/workers-types': 4.20260317.1
|
||||||
'@design.estate/dees-catalog': 3.55.1(@tiptap/pm@2.27.2)
|
'@design.estate/dees-catalog': 3.55.5(@tiptap/pm@2.27.2)
|
||||||
'@design.estate/dees-comms': 1.0.30
|
'@design.estate/dees-comms': 1.0.30
|
||||||
'@push.rocks/lik': 6.4.0
|
'@push.rocks/lik': 6.4.0
|
||||||
'@push.rocks/smartdelay': 3.0.5
|
'@push.rocks/smartdelay': 3.0.5
|
||||||
@@ -4871,7 +4880,7 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@api.global/typedrequest-interfaces': 3.0.19
|
'@api.global/typedrequest-interfaces': 3.0.19
|
||||||
|
|
||||||
'@design.estate/dees-catalog@3.55.1(@tiptap/pm@2.27.2)':
|
'@design.estate/dees-catalog@3.55.5(@tiptap/pm@2.27.2)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@design.estate/dees-domtools': 2.5.4
|
'@design.estate/dees-domtools': 2.5.4
|
||||||
'@design.estate/dees-element': 2.2.4
|
'@design.estate/dees-element': 2.2.4
|
||||||
@@ -4891,8 +4900,9 @@ snapshots:
|
|||||||
'@tiptap/extension-underline': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))
|
'@tiptap/extension-underline': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))
|
||||||
'@tiptap/starter-kit': 2.27.2
|
'@tiptap/starter-kit': 2.27.2
|
||||||
'@tsclass/tsclass': 9.5.0
|
'@tsclass/tsclass': 9.5.0
|
||||||
|
echarts: 5.6.0
|
||||||
highlight.js: 11.11.1
|
highlight.js: 11.11.1
|
||||||
ibantools: 4.5.1
|
ibantools: 4.5.2
|
||||||
lightweight-charts: 5.1.0
|
lightweight-charts: 5.1.0
|
||||||
lucide: 0.577.0
|
lucide: 0.577.0
|
||||||
monaco-editor: 0.55.1
|
monaco-editor: 0.55.1
|
||||||
@@ -6909,7 +6919,7 @@ snapshots:
|
|||||||
|
|
||||||
'@serve.zone/catalog@2.11.0(@tiptap/pm@2.27.2)':
|
'@serve.zone/catalog@2.11.0(@tiptap/pm@2.27.2)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@design.estate/dees-catalog': 3.55.1(@tiptap/pm@2.27.2)
|
'@design.estate/dees-catalog': 3.55.5(@tiptap/pm@2.27.2)
|
||||||
'@design.estate/dees-domtools': 2.5.4
|
'@design.estate/dees-domtools': 2.5.4
|
||||||
'@design.estate/dees-element': 2.2.4
|
'@design.estate/dees-element': 2.2.4
|
||||||
'@design.estate/dees-wcctools': 3.8.0
|
'@design.estate/dees-wcctools': 3.8.0
|
||||||
@@ -7978,6 +7988,11 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
safe-buffer: 5.2.1
|
safe-buffer: 5.2.1
|
||||||
|
|
||||||
|
echarts@5.6.0:
|
||||||
|
dependencies:
|
||||||
|
tslib: 2.3.0
|
||||||
|
zrender: 5.6.1
|
||||||
|
|
||||||
emoji-regex@8.0.0: {}
|
emoji-regex@8.0.0: {}
|
||||||
|
|
||||||
encoding-japanese@2.2.0: {}
|
encoding-japanese@2.2.0: {}
|
||||||
@@ -8410,7 +8425,7 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
ms: 2.1.3
|
ms: 2.1.3
|
||||||
|
|
||||||
ibantools@4.5.1: {}
|
ibantools@4.5.2: {}
|
||||||
|
|
||||||
iconv-lite@0.4.24:
|
iconv-lite@0.4.24:
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -9942,6 +9957,8 @@ snapshots:
|
|||||||
|
|
||||||
tslib@1.14.1: {}
|
tslib@1.14.1: {}
|
||||||
|
|
||||||
|
tslib@2.3.0: {}
|
||||||
|
|
||||||
tslib@2.8.1: {}
|
tslib@2.8.1: {}
|
||||||
|
|
||||||
tsx@4.21.0:
|
tsx@4.21.0:
|
||||||
@@ -10169,4 +10186,8 @@ snapshots:
|
|||||||
|
|
||||||
zod@3.25.76: {}
|
zod@3.25.76: {}
|
||||||
|
|
||||||
|
zrender@5.6.1:
|
||||||
|
dependencies:
|
||||||
|
tslib: 2.3.0
|
||||||
|
|
||||||
zwitch@2.0.4: {}
|
zwitch@2.0.4: {}
|
||||||
|
|||||||
@@ -3,6 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@serve.zone/dcrouter',
|
name: '@serve.zone/dcrouter',
|
||||||
version: '12.8.1',
|
version: '12.9.0',
|
||||||
description: 'A multifaceted routing service handling mail and SMS delivery functions.'
|
description: 'A multifaceted routing service handling mail and SMS delivery functions.'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,9 +29,9 @@ export class StorageBackedCertManager implements plugins.smartacme.ICertManager
|
|||||||
let doc = await AcmeCertDoc.findByDomain(cert.domainName);
|
let doc = await AcmeCertDoc.findByDomain(cert.domainName);
|
||||||
if (!doc) {
|
if (!doc) {
|
||||||
doc = new AcmeCertDoc();
|
doc = new AcmeCertDoc();
|
||||||
|
doc.id = cert.id;
|
||||||
doc.domainName = cert.domainName;
|
doc.domainName = cert.domainName;
|
||||||
}
|
}
|
||||||
doc.id = cert.id;
|
|
||||||
doc.created = cert.created;
|
doc.created = cert.created;
|
||||||
doc.privateKey = cert.privateKey;
|
doc.privateKey = cert.privateKey;
|
||||||
doc.publicKey = cert.publicKey;
|
doc.publicKey = cert.publicKey;
|
||||||
|
|||||||
@@ -591,6 +591,11 @@ export class MetricsManager {
|
|||||||
const requestsPerSecond = proxyMetrics.requests.perSecond();
|
const requestsPerSecond = proxyMetrics.requests.perSecond();
|
||||||
const requestsTotal = proxyMetrics.requests.total();
|
const requestsTotal = proxyMetrics.requests.total();
|
||||||
|
|
||||||
|
// Get frontend/backend protocol distribution (available in SmartProxy >= next release)
|
||||||
|
const conn = proxyMetrics.connections as any;
|
||||||
|
const frontendProtocols = conn.frontendProtocols?.() ?? null;
|
||||||
|
const backendProtocols = conn.backendProtocols?.() ?? null;
|
||||||
|
|
||||||
// Collect backend protocol data
|
// Collect backend protocol data
|
||||||
const backendMetrics = proxyMetrics.backends.byBackend();
|
const backendMetrics = proxyMetrics.backends.byBackend();
|
||||||
const protocolCache = proxyMetrics.backends.detectedProtocols();
|
const protocolCache = proxyMetrics.backends.detectedProtocols();
|
||||||
@@ -705,6 +710,8 @@ export class MetricsManager {
|
|||||||
requestsPerSecond,
|
requestsPerSecond,
|
||||||
requestsTotal,
|
requestsTotal,
|
||||||
backends,
|
backends,
|
||||||
|
frontendProtocols,
|
||||||
|
backendProtocols,
|
||||||
};
|
};
|
||||||
}, 1000); // 1s cache — matches typical dashboard poll interval
|
}, 1000); // 1s cache — matches typical dashboard poll interval
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -311,6 +311,8 @@ export class StatsHandler {
|
|||||||
requestsPerSecond: stats.requestsPerSecond || 0,
|
requestsPerSecond: stats.requestsPerSecond || 0,
|
||||||
requestsTotal: stats.requestsTotal || 0,
|
requestsTotal: stats.requestsTotal || 0,
|
||||||
backends: stats.backends || [],
|
backends: stats.backends || [],
|
||||||
|
frontendProtocols: stats.frontendProtocols || null,
|
||||||
|
backendProtocols: stats.backendProtocols || null,
|
||||||
};
|
};
|
||||||
})()
|
})()
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -166,6 +166,21 @@ export interface INetworkMetrics {
|
|||||||
requestsPerSecond?: number;
|
requestsPerSecond?: number;
|
||||||
requestsTotal?: number;
|
requestsTotal?: number;
|
||||||
backends?: IBackendInfo[];
|
backends?: IBackendInfo[];
|
||||||
|
frontendProtocols?: IProtocolDistribution | null;
|
||||||
|
backendProtocols?: IProtocolDistribution | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IProtocolDistribution {
|
||||||
|
h1Active: number;
|
||||||
|
h1Total: number;
|
||||||
|
h2Active: number;
|
||||||
|
h2Total: number;
|
||||||
|
h3Active: number;
|
||||||
|
h3Total: number;
|
||||||
|
wsActive: number;
|
||||||
|
wsTotal: number;
|
||||||
|
otherActive: number;
|
||||||
|
otherTotal: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IConnectionDetails {
|
export interface IConnectionDetails {
|
||||||
|
|||||||
@@ -3,6 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@serve.zone/dcrouter',
|
name: '@serve.zone/dcrouter',
|
||||||
version: '12.8.1',
|
version: '12.9.0',
|
||||||
description: 'A multifaceted routing service handling mail and SMS delivery functions.'
|
description: 'A multifaceted routing service handling mail and SMS delivery functions.'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,6 +56,8 @@ export interface INetworkState {
|
|||||||
requestsPerSecond: number;
|
requestsPerSecond: number;
|
||||||
requestsTotal: number;
|
requestsTotal: number;
|
||||||
backends: interfaces.data.IBackendInfo[];
|
backends: interfaces.data.IBackendInfo[];
|
||||||
|
frontendProtocols: interfaces.data.IProtocolDistribution | null;
|
||||||
|
backendProtocols: interfaces.data.IProtocolDistribution | null;
|
||||||
lastUpdated: number;
|
lastUpdated: number;
|
||||||
isLoading: boolean;
|
isLoading: boolean;
|
||||||
error: string | null;
|
error: string | null;
|
||||||
@@ -154,6 +156,8 @@ export const networkStatePart = await appState.getStatePart<INetworkState>(
|
|||||||
requestsPerSecond: 0,
|
requestsPerSecond: 0,
|
||||||
requestsTotal: 0,
|
requestsTotal: 0,
|
||||||
backends: [],
|
backends: [],
|
||||||
|
frontendProtocols: null,
|
||||||
|
backendProtocols: null,
|
||||||
lastUpdated: 0,
|
lastUpdated: 0,
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
error: null,
|
error: null,
|
||||||
@@ -523,6 +527,8 @@ export const fetchNetworkStatsAction = networkStatePart.createAction(async (stat
|
|||||||
requestsPerSecond: networkStatsResponse.requestsPerSecond || 0,
|
requestsPerSecond: networkStatsResponse.requestsPerSecond || 0,
|
||||||
requestsTotal: networkStatsResponse.requestsTotal || 0,
|
requestsTotal: networkStatsResponse.requestsTotal || 0,
|
||||||
backends: networkStatsResponse.backends || [],
|
backends: networkStatsResponse.backends || [],
|
||||||
|
frontendProtocols: networkStatsResponse.frontendProtocols || null,
|
||||||
|
backendProtocols: networkStatsResponse.backendProtocols || null,
|
||||||
lastUpdated: Date.now(),
|
lastUpdated: Date.now(),
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
error: null,
|
error: null,
|
||||||
@@ -1845,6 +1851,8 @@ async function dispatchCombinedRefreshActionInner() {
|
|||||||
requestsPerSecond: network.requestsPerSecond || 0,
|
requestsPerSecond: network.requestsPerSecond || 0,
|
||||||
requestsTotal: network.requestsTotal || 0,
|
requestsTotal: network.requestsTotal || 0,
|
||||||
backends: network.backends || [],
|
backends: network.backends || [],
|
||||||
|
frontendProtocols: network.frontendProtocols || null,
|
||||||
|
backendProtocols: network.backendProtocols || null,
|
||||||
lastUpdated: Date.now(),
|
lastUpdated: Date.now(),
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
error: null,
|
error: null,
|
||||||
@@ -1866,6 +1874,8 @@ async function dispatchCombinedRefreshActionInner() {
|
|||||||
requestsPerSecond: network.requestsPerSecond || 0,
|
requestsPerSecond: network.requestsPerSecond || 0,
|
||||||
requestsTotal: network.requestsTotal || 0,
|
requestsTotal: network.requestsTotal || 0,
|
||||||
backends: network.backends || [],
|
backends: network.backends || [],
|
||||||
|
frontendProtocols: network.frontendProtocols || null,
|
||||||
|
backendProtocols: network.backendProtocols || null,
|
||||||
lastUpdated: Date.now(),
|
lastUpdated: Date.now(),
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
error: null,
|
error: null,
|
||||||
|
|||||||
@@ -274,6 +274,12 @@ export class OpsViewNetwork extends DeesElement {
|
|||||||
background: ${cssManager.bdTheme('#fff3e0', '#3a2a1a')};
|
background: ${cssManager.bdTheme('#fff3e0', '#3a2a1a')};
|
||||||
color: ${cssManager.bdTheme('#f57c00', '#ff9933')};
|
color: ${cssManager.bdTheme('#f57c00', '#ff9933')};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.protocolChartGrid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -305,6 +311,9 @@ export class OpsViewNetwork extends DeesElement {
|
|||||||
.yAxisFormatter=${(val: number) => `${val} Mbit/s`}
|
.yAxisFormatter=${(val: number) => `${val} Mbit/s`}
|
||||||
></dees-chart-area>
|
></dees-chart-area>
|
||||||
|
|
||||||
|
<!-- Protocol Distribution Charts -->
|
||||||
|
${this.renderProtocolCharts()}
|
||||||
|
|
||||||
<!-- Top IPs Section -->
|
<!-- Top IPs Section -->
|
||||||
${this.renderTopIPs()}
|
${this.renderTopIPs()}
|
||||||
|
|
||||||
@@ -527,6 +536,53 @@ export class OpsViewNetwork extends DeesElement {
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private renderProtocolCharts(): TemplateResult {
|
||||||
|
const fp = this.networkState.frontendProtocols;
|
||||||
|
const bp = this.networkState.backendProtocols;
|
||||||
|
|
||||||
|
const protoColors: Record<string, string> = {
|
||||||
|
'HTTP/1.1': '#1976d2',
|
||||||
|
'HTTP/2': '#388e3c',
|
||||||
|
'HTTP/3': '#7b1fa2',
|
||||||
|
'WebSocket': '#f57c00',
|
||||||
|
'Other': '#757575',
|
||||||
|
};
|
||||||
|
|
||||||
|
const buildDonutData = (dist: interfaces.data.IProtocolDistribution | null) => {
|
||||||
|
if (!dist) return [];
|
||||||
|
const items: Array<{ name: string; value: number; color: string }> = [];
|
||||||
|
if (dist.h1Active > 0) items.push({ name: 'HTTP/1.1', value: dist.h1Active, color: protoColors['HTTP/1.1'] });
|
||||||
|
if (dist.h2Active > 0) items.push({ name: 'HTTP/2', value: dist.h2Active, color: protoColors['HTTP/2'] });
|
||||||
|
if (dist.h3Active > 0) items.push({ name: 'HTTP/3', value: dist.h3Active, color: protoColors['HTTP/3'] });
|
||||||
|
if (dist.wsActive > 0) items.push({ name: 'WebSocket', value: dist.wsActive, color: protoColors['WebSocket'] });
|
||||||
|
if (dist.otherActive > 0) items.push({ name: 'Other', value: dist.otherActive, color: protoColors['Other'] });
|
||||||
|
return items;
|
||||||
|
};
|
||||||
|
|
||||||
|
const frontendData = buildDonutData(fp);
|
||||||
|
const backendData = buildDonutData(bp);
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<div class="protocolChartGrid">
|
||||||
|
<dees-chart-donut
|
||||||
|
.label=${'Frontend Protocols'}
|
||||||
|
.data=${frontendData.length > 0 ? frontendData : [{ name: 'No Traffic', value: 1, color: '#757575' }]}
|
||||||
|
.showLegend=${true}
|
||||||
|
.showLabels=${true}
|
||||||
|
.innerRadiusPercent=${'55%'}
|
||||||
|
.valueFormatter=${(val: number) => `${val} active`}
|
||||||
|
></dees-chart-donut>
|
||||||
|
<dees-chart-donut
|
||||||
|
.label=${'Backend Protocols'}
|
||||||
|
.data=${backendData.length > 0 ? backendData : [{ name: 'No Traffic', value: 1, color: '#757575' }]}
|
||||||
|
.showLegend=${true}
|
||||||
|
.showLabels=${true}
|
||||||
|
.innerRadiusPercent=${'55%'}
|
||||||
|
.valueFormatter=${(val: number) => `${val} active`}
|
||||||
|
></dees-chart-donut>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
private renderTopIPs(): TemplateResult {
|
private renderTopIPs(): TemplateResult {
|
||||||
if (this.networkState.topIPs.length === 0) {
|
if (this.networkState.topIPs.length === 0) {
|
||||||
|
|||||||
Reference in New Issue
Block a user