Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 466654ee4c | |||
| f1a11e3f6a | |||
| e193b3a8eb | |||
| 1bbf31605c | |||
| f2cfa923a0 | |||
| cdc77305e5 |
@@ -1,5 +1,23 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 2026-04-13 - 13.17.3 - fix(ops-view-routes)
|
||||||
|
sync route filter toggle selection via component changeSubject
|
||||||
|
|
||||||
|
- Replaces the inline change handler on the route filter toggle with a subscription to the component's changeSubject in firstUpdated.
|
||||||
|
- Ensures switching between user and system routes updates the view reliably and is cleaned up through existing rxSubscriptions management.
|
||||||
|
|
||||||
|
## 2026-04-13 - 13.17.2 - fix(monitoring)
|
||||||
|
exclude unconfigured routes from domain activity aggregation
|
||||||
|
|
||||||
|
- Removes fallback aggregation that reported routes without domain configuration as synthetic domain entries based on route names
|
||||||
|
- Keeps domain activity focused on configured domain mappings when splitting connection and throughput metrics
|
||||||
|
|
||||||
|
## 2026-04-13 - 13.17.1 - fix(monitoring)
|
||||||
|
stop allocating route metrics to domains when no request data exists
|
||||||
|
|
||||||
|
- Removes the equal-split fallback for shared routes in MetricsManager.
|
||||||
|
- Sets the proportional share to zero when a route has no recorded requests, avoiding inflated per-domain connection and throughput totals.
|
||||||
|
|
||||||
## 2026-04-13 - 13.17.0 - feat(monitoring,network-ui,routes)
|
## 2026-04-13 - 13.17.0 - feat(monitoring,network-ui,routes)
|
||||||
add request-based domain activity metrics and split routes into user and system views
|
add request-based domain activity metrics and split routes into user and system views
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@serve.zone/dcrouter",
|
"name": "@serve.zone/dcrouter",
|
||||||
"private": false,
|
"private": false,
|
||||||
"version": "13.17.0",
|
"version": "13.17.3",
|
||||||
"description": "A multifaceted routing service handling mail and SMS delivery functions.",
|
"description": "A multifaceted routing service handling mail and SMS delivery functions.",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"exports": {
|
"exports": {
|
||||||
|
|||||||
@@ -3,6 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@serve.zone/dcrouter',
|
name: '@serve.zone/dcrouter',
|
||||||
version: '13.17.0',
|
version: '13.17.3',
|
||||||
description: 'A multifaceted routing service handling mail and SMS delivery functions.'
|
description: 'A multifaceted routing service handling mail and SMS delivery functions.'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -792,7 +792,6 @@ export class MetricsManager {
|
|||||||
routeCount: number;
|
routeCount: number;
|
||||||
requestCount: number;
|
requestCount: number;
|
||||||
}>();
|
}>();
|
||||||
const accountedRoutes = new Set<string>();
|
|
||||||
|
|
||||||
for (const [domain, routeNames] of domainToRoutes) {
|
for (const [domain, routeNames] of domainToRoutes) {
|
||||||
const domainReqs = domainRequestTotals.get(domain) || 0;
|
const domainReqs = domainRequestTotals.get(domain) || 0;
|
||||||
@@ -801,25 +800,11 @@ export class MetricsManager {
|
|||||||
let totalOut = 0;
|
let totalOut = 0;
|
||||||
|
|
||||||
for (const routeName of routeNames) {
|
for (const routeName of routeNames) {
|
||||||
accountedRoutes.add(routeName);
|
|
||||||
const conns = connectionsByRoute.get(routeName) || 0;
|
const conns = connectionsByRoute.get(routeName) || 0;
|
||||||
const tp = throughputByRoute.get(routeName) || { in: 0, out: 0 };
|
const tp = throughputByRoute.get(routeName) || { in: 0, out: 0 };
|
||||||
const routeTotal = routeTotalRequests.get(routeName) || 0;
|
const routeTotal = routeTotalRequests.get(routeName) || 0;
|
||||||
|
|
||||||
// Proportional share based on actual request counts
|
const share = routeTotal > 0 ? domainReqs / routeTotal : 0;
|
||||||
// Fall back to equal split only when no request data exists
|
|
||||||
let share: number;
|
|
||||||
if (routeTotal > 0 && domainReqs > 0) {
|
|
||||||
share = domainReqs / routeTotal;
|
|
||||||
} else {
|
|
||||||
// Count how many resolved domains share this route
|
|
||||||
let domainsInRoute = 0;
|
|
||||||
for (const [, routes] of domainToRoutes) {
|
|
||||||
if (routes.includes(routeName)) domainsInRoute++;
|
|
||||||
}
|
|
||||||
share = 1 / Math.max(domainsInRoute, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
totalConns += conns * share;
|
totalConns += conns * share;
|
||||||
totalIn += tp.in * share;
|
totalIn += tp.in * share;
|
||||||
totalOut += tp.out * share;
|
totalOut += tp.out * share;
|
||||||
@@ -834,29 +819,6 @@ export class MetricsManager {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Include routes with no domain config (fallback: use route name)
|
|
||||||
for (const [routeName, activeConns] of connectionsByRoute) {
|
|
||||||
if (accountedRoutes.has(routeName)) continue;
|
|
||||||
if (routeDomains.has(routeName)) continue;
|
|
||||||
const tp = throughputByRoute.get(routeName) || { in: 0, out: 0 };
|
|
||||||
if (activeConns === 0 && tp.in === 0 && tp.out === 0) continue;
|
|
||||||
const existing = domainAgg.get(routeName);
|
|
||||||
if (existing) {
|
|
||||||
existing.activeConnections += activeConns;
|
|
||||||
existing.bytesInPerSec += tp.in;
|
|
||||||
existing.bytesOutPerSec += tp.out;
|
|
||||||
existing.routeCount++;
|
|
||||||
} else {
|
|
||||||
domainAgg.set(routeName, {
|
|
||||||
activeConnections: activeConns,
|
|
||||||
bytesInPerSec: tp.in,
|
|
||||||
bytesOutPerSec: tp.out,
|
|
||||||
routeCount: 1,
|
|
||||||
requestCount: 0,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const domainActivity = Array.from(domainAgg.entries())
|
const domainActivity = Array.from(domainAgg.entries())
|
||||||
.map(([domain, data]) => ({
|
.map(([domain, data]) => ({
|
||||||
domain,
|
domain,
|
||||||
|
|||||||
@@ -3,6 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@serve.zone/dcrouter',
|
name: '@serve.zone/dcrouter',
|
||||||
version: '13.17.0',
|
version: '13.17.3',
|
||||||
description: 'A multifaceted routing service handling mail and SMS delivery functions.'
|
description: 'A multifaceted routing service handling mail and SMS delivery functions.'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -227,10 +227,10 @@ export class OpsViewRoutes extends DeesElement {
|
|||||||
></dees-statsgrid>
|
></dees-statsgrid>
|
||||||
|
|
||||||
<dees-input-multitoggle
|
<dees-input-multitoggle
|
||||||
|
class="routeFilterToggle"
|
||||||
.type=${'single'}
|
.type=${'single'}
|
||||||
.options=${['User Routes', 'System Routes']}
|
.options=${['User Routes', 'System Routes']}
|
||||||
.selectedOption=${this.routeFilter}
|
.selectedOption=${this.routeFilter}
|
||||||
@change=${(e: any) => { this.routeFilter = e.target.value || e.target.selectedOption; }}
|
|
||||||
></dees-input-multitoggle>
|
></dees-input-multitoggle>
|
||||||
|
|
||||||
${warnings.length > 0
|
${warnings.length > 0
|
||||||
@@ -677,5 +677,13 @@ export class OpsViewRoutes extends DeesElement {
|
|||||||
|
|
||||||
async firstUpdated() {
|
async firstUpdated() {
|
||||||
await appstate.routeManagementStatePart.dispatchAction(appstate.fetchMergedRoutesAction, null);
|
await appstate.routeManagementStatePart.dispatchAction(appstate.fetchMergedRoutesAction, null);
|
||||||
|
|
||||||
|
const toggle = this.shadowRoot!.querySelector('.routeFilterToggle') as any;
|
||||||
|
if (toggle) {
|
||||||
|
const sub = toggle.changeSubject.subscribe(() => {
|
||||||
|
this.routeFilter = toggle.selectedOption;
|
||||||
|
});
|
||||||
|
this.rxSubscriptions.push(sub);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user