feat(monitoring,network-ui,routes): add request-based domain activity metrics and split routes into user and system views

This commit is contained in:
2026-04-13 19:12:56 +00:00
parent 0a39d50d20
commit 754b223f62
7 changed files with 91 additions and 44 deletions

View File

@@ -3,6 +3,6 @@
*/
export const commitinfo = {
name: '@serve.zone/dcrouter',
version: '13.16.2',
version: '13.17.0',
description: 'A multifaceted routing service handling mail and SMS delivery functions.'
}

View File

@@ -560,11 +560,12 @@ export class OpsViewNetworkActivity extends DeesElement {
'Throughput Out': this.formatBitsPerSecond(item.bytesOutPerSecond),
'Transferred / min': this.formatBytes(totalBytesPerMin),
'Connections': item.activeConnections,
'Requests': item.requestCount?.toLocaleString() ?? '0',
'Routes': item.routeCount,
};
}}
heading1="Domain Activity"
heading2="Per-domain network activity aggregated from route metrics"
heading2="Per-domain network activity from request-level metrics"
searchable
.showColumnFilters=${true}
.pagination=${false}

View File

@@ -49,6 +49,8 @@ function setupTlsVisibility(formEl: any) {
@customElement('ops-view-routes')
export class OpsViewRoutes extends DeesElement {
@state() accessor routeFilter: 'User Routes' | 'System Routes' = 'User Routes';
@state() accessor routeState: appstate.IRouteManagementState = {
mergedRoutes: [],
warnings: [],
@@ -156,20 +158,20 @@ export class OpsViewRoutes extends DeesElement {
},
{
id: 'configRoutes',
title: 'From Config',
title: 'System Routes',
type: 'number',
value: configCount,
icon: 'lucide:settings',
description: 'Seeded from config/email/DNS',
description: 'From config, email, and DNS',
color: '#8b5cf6',
},
{
id: 'apiRoutes',
title: 'API Created',
title: 'User Routes',
type: 'number',
value: apiCount,
icon: 'lucide:code',
description: 'Routes added via API',
description: 'Created via API',
color: '#0ea5e9',
},
{
@@ -183,8 +185,14 @@ export class OpsViewRoutes extends DeesElement {
},
];
// Map merged routes to sz-route-list-view format
const szRoutes = mergedRoutes.map((mr) => {
// Filter routes based on selected tab
const isUserRoutes = this.routeFilter === 'User Routes';
const filteredRoutes = mergedRoutes.filter((mr) =>
isUserRoutes ? mr.origin === 'api' : mr.origin !== 'api'
);
// Map filtered routes to sz-route-list-view format
const szRoutes = filteredRoutes.map((mr) => {
const tags = [...(mr.route.tags || [])];
tags.push(mr.origin);
if (!mr.enabled) tags.push('disabled');
@@ -218,6 +226,13 @@ export class OpsViewRoutes extends DeesElement {
]}
></dees-statsgrid>
<dees-input-multitoggle
.type=${'single'}
.options=${['User Routes', 'System Routes']}
.selectedOption=${this.routeFilter}
@change=${(e: any) => { this.routeFilter = e.target.value || e.target.selectedOption; }}
></dees-input-multitoggle>
${warnings.length > 0
? html`
<div class="warnings-bar">
@@ -237,6 +252,7 @@ export class OpsViewRoutes extends DeesElement {
? html`
<sz-route-list-view
.routes=${szRoutes}
.showActionsFilter=${isUserRoutes ? () => true : () => false}
@route-click=${(e: CustomEvent) => this.handleRouteClick(e)}
@route-edit=${(e: CustomEvent) => this.handleRouteEdit(e)}
@route-delete=${(e: CustomEvent) => this.handleRouteDelete(e)}
@@ -244,8 +260,8 @@ export class OpsViewRoutes extends DeesElement {
`
: html`
<div class="empty-state">
<p>No routes configured</p>
<p>Add a route to get started.</p>
<p>No ${isUserRoutes ? 'user' : 'system'} routes</p>
<p>${isUserRoutes ? 'Add a route to get started.' : 'System routes are generated from config, email, and DNS settings.'}</p>
</div>
`}
</div>