@serve.zone/dcrouter 11.9.0 → 11.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/dist_serve/bundle.js +627 -569
  2. package/dist_ts/00_commitinfo_data.js +2 -2
  3. package/dist_ts/classes.cert-provision-scheduler.d.ts +2 -1
  4. package/dist_ts/classes.cert-provision-scheduler.js +13 -5
  5. package/dist_ts/classes.dcrouter.d.ts +1 -0
  6. package/dist_ts/classes.dcrouter.js +13 -2
  7. package/dist_ts/index.js +3 -3
  8. package/dist_ts/monitoring/classes.metricsmanager.d.ts +1 -0
  9. package/dist_ts/monitoring/classes.metricsmanager.js +65 -1
  10. package/dist_ts/opsserver/handlers/security.handler.js +3 -1
  11. package/dist_ts/opsserver/handlers/stats.handler.js +2 -1
  12. package/dist_ts/radius/classes.accounting.manager.d.ts +13 -0
  13. package/dist_ts/radius/classes.accounting.manager.js +46 -1
  14. package/dist_ts/radius/classes.radius.server.js +2 -1
  15. package/dist_ts_interfaces/data/stats.d.ts +22 -0
  16. package/dist_ts_interfaces/requests/stats.d.ts +1 -0
  17. package/dist_ts_web/00_commitinfo_data.js +2 -2
  18. package/dist_ts_web/appstate.d.ts +1 -0
  19. package/dist_ts_web/appstate.js +3 -1
  20. package/dist_ts_web/elements/ops-view-network.d.ts +2 -0
  21. package/dist_ts_web/elements/ops-view-network.js +132 -1
  22. package/package.json +25 -17
  23. package/ts/00_commitinfo_data.ts +1 -1
  24. package/ts/classes.cert-provision-scheduler.ts +14 -4
  25. package/ts/classes.dcrouter.ts +15 -1
  26. package/ts/index.ts +2 -2
  27. package/ts/monitoring/classes.metricsmanager.ts +69 -0
  28. package/ts/opsserver/handlers/security.handler.ts +2 -0
  29. package/ts/opsserver/handlers/stats.handler.ts +1 -0
  30. package/ts/radius/classes.accounting.manager.ts +55 -0
  31. package/ts/radius/classes.radius.server.ts +2 -0
  32. package/ts_web/00_commitinfo_data.ts +1 -1
  33. package/ts_web/appstate.ts +3 -0
  34. package/ts_web/elements/ops-view-network.ts +136 -0
@@ -183,6 +183,8 @@ export class RadiusServer {
183
183
  this.radiusServer = undefined;
184
184
  }
185
185
 
186
+ this.accountingManager.stop();
187
+
186
188
  this.running = false;
187
189
  logger.log('info', 'RADIUS server stopped');
188
190
  }
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@serve.zone/dcrouter',
6
- version: '11.9.0',
6
+ version: '11.10.0',
7
7
  description: 'A multifaceted routing service handling mail and SMS delivery functions.'
8
8
  }
@@ -53,6 +53,7 @@ export interface INetworkState {
53
53
  throughputHistory: Array<{ timestamp: number; in: number; out: number }>;
54
54
  requestsPerSecond: number;
55
55
  requestsTotal: number;
56
+ backends: interfaces.data.IBackendInfo[];
56
57
  lastUpdated: number;
57
58
  isLoading: boolean;
58
59
  error: string | null;
@@ -148,6 +149,7 @@ export const networkStatePart = await appState.getStatePart<INetworkState>(
148
149
  throughputHistory: [],
149
150
  requestsPerSecond: 0,
150
151
  requestsTotal: 0,
152
+ backends: [],
151
153
  lastUpdated: 0,
152
154
  isLoading: false,
153
155
  error: null,
@@ -503,6 +505,7 @@ export const fetchNetworkStatsAction = networkStatePart.createAction(async (stat
503
505
  throughputHistory: networkStatsResponse.throughputHistory || [],
504
506
  requestsPerSecond: networkStatsResponse.requestsPerSecond || 0,
505
507
  requestsTotal: networkStatsResponse.requestsTotal || 0,
508
+ backends: networkStatsResponse.backends || [],
506
509
  lastUpdated: Date.now(),
507
510
  isLoading: false,
508
511
  error: null,
@@ -1,5 +1,6 @@
1
1
  import { DeesElement, property, html, customElement, type TemplateResult, css, state, cssManager } from '@design.estate/dees-element';
2
2
  import * as appstate from '../appstate.js';
3
+ import * as interfaces from '../../dist_ts_interfaces/index.js';
3
4
  import { viewHostCss } from './shared/css.js';
4
5
  import { type IStatsTile } from '@design.estate/dees-catalog';
5
6
 
@@ -198,6 +199,38 @@ export class OpsViewNetwork extends DeesElement {
198
199
  color: ${cssManager.bdTheme('#00796b', '#4db6ac')};
199
200
  }
200
201
 
202
+ .protocolBadge.h1 {
203
+ background: ${cssManager.bdTheme('#e3f2fd', '#1a2c3a')};
204
+ color: ${cssManager.bdTheme('#1976d2', '#5a9fd4')};
205
+ }
206
+
207
+ .protocolBadge.h2 {
208
+ background: ${cssManager.bdTheme('#e8f5e9', '#1a3a1a')};
209
+ color: ${cssManager.bdTheme('#388e3c', '#66bb6a')};
210
+ }
211
+
212
+ .protocolBadge.h3 {
213
+ background: ${cssManager.bdTheme('#f3e5f5', '#2a1a3a')};
214
+ color: ${cssManager.bdTheme('#7b1fa2', '#ba68c8')};
215
+ }
216
+
217
+ .protocolBadge.unknown {
218
+ background: ${cssManager.bdTheme('#f5f5f5', '#2a2a2a')};
219
+ color: ${cssManager.bdTheme('#757575', '#999999')};
220
+ }
221
+
222
+ .suppressionBadge {
223
+ display: inline-flex;
224
+ align-items: center;
225
+ padding: 2px 6px;
226
+ border-radius: 3px;
227
+ font-size: 11px;
228
+ font-weight: 500;
229
+ background: ${cssManager.bdTheme('#fff3e0', '#3a2a1a')};
230
+ color: ${cssManager.bdTheme('#f57c00', '#ff9933')};
231
+ margin-left: 4px;
232
+ }
233
+
201
234
  .statusBadge {
202
235
  display: inline-flex;
203
236
  align-items: center;
@@ -265,6 +298,9 @@ export class OpsViewNetwork extends DeesElement {
265
298
  <!-- Top IPs Section -->
266
299
  ${this.renderTopIPs()}
267
300
 
301
+ <!-- Backend Protocols Section -->
302
+ ${this.renderBackendProtocols()}
303
+
268
304
  <!-- Requests Table -->
269
305
  <dees-table
270
306
  .data=${this.networkRequests}
@@ -519,6 +555,106 @@ export class OpsViewNetwork extends DeesElement {
519
555
  `;
520
556
  }
521
557
 
558
+ private renderBackendProtocols(): TemplateResult {
559
+ const backends = this.networkState.backends;
560
+ if (!backends || backends.length === 0) {
561
+ return html``;
562
+ }
563
+
564
+ return html`
565
+ <dees-table
566
+ .data=${backends}
567
+ .displayFunction=${(item: interfaces.data.IBackendInfo) => {
568
+ const totalErrors = item.connectErrors + item.handshakeErrors + item.requestErrors;
569
+ const protocolClass = item.protocol.toLowerCase().replace(/[^a-z0-9]/g, '');
570
+
571
+ return {
572
+ 'Backend': item.backend,
573
+ 'Domain': item.domain || '-',
574
+ 'Protocol': html`
575
+ <span class="protocolBadge ${protocolClass}">${item.protocol.toUpperCase()}</span>
576
+ ${item.h2Suppressed ? html`<span class="suppressionBadge" title="H2 suppressed: ${item.h2ConsecutiveFailures ?? 0} failures, cooldown ${item.h2CooldownRemainingSecs ?? 0}s">H2 suppressed</span>` : ''}
577
+ ${item.h3Suppressed ? html`<span class="suppressionBadge" title="H3 suppressed: ${item.h3ConsecutiveFailures ?? 0} failures, cooldown ${item.h3CooldownRemainingSecs ?? 0}s">H3 suppressed</span>` : ''}
578
+ `,
579
+ 'Active': item.activeConnections,
580
+ 'Total': this.formatNumber(item.totalConnections),
581
+ 'Avg Connect': item.avgConnectTimeMs > 0 ? `${item.avgConnectTimeMs.toFixed(1)}ms` : '-',
582
+ 'Pool Hit Rate': item.poolHitRate > 0 ? `${(item.poolHitRate * 100).toFixed(1)}%` : '-',
583
+ 'Errors': totalErrors > 0
584
+ ? html`<span class="statusBadge error">${totalErrors}</span>`
585
+ : html`<span class="statusBadge success">0</span>`,
586
+ 'Cache Age': item.cacheAgeSecs != null ? `${Math.round(item.cacheAgeSecs)}s` : '-',
587
+ };
588
+ }}
589
+ .dataActions=${[
590
+ {
591
+ name: 'View Details',
592
+ iconName: 'lucide:info',
593
+ type: ['inRow', 'doubleClick', 'contextmenu'] as any,
594
+ actionFunc: async (actionData: any) => {
595
+ await this.showBackendDetails(actionData.item);
596
+ }
597
+ }
598
+ ]}
599
+ heading1="Backend Protocols"
600
+ heading2="Auto-detected backend protocols and connection pool health"
601
+ searchable
602
+ .pagination=${false}
603
+ dataName="backend"
604
+ ></dees-table>
605
+ `;
606
+ }
607
+
608
+ private async showBackendDetails(backend: interfaces.data.IBackendInfo) {
609
+ const { DeesModal } = await import('@design.estate/dees-catalog');
610
+
611
+ await DeesModal.createAndShow({
612
+ heading: `Backend: ${backend.backend}`,
613
+ content: html`
614
+ <div style="padding: 20px;">
615
+ <dees-dataview-codebox
616
+ .heading=${'Backend Details'}
617
+ progLang="json"
618
+ .codeToDisplay=${JSON.stringify({
619
+ backend: backend.backend,
620
+ domain: backend.domain,
621
+ protocol: backend.protocol,
622
+ activeConnections: backend.activeConnections,
623
+ totalConnections: backend.totalConnections,
624
+ avgConnectTimeMs: backend.avgConnectTimeMs,
625
+ poolHitRate: backend.poolHitRate,
626
+ errors: {
627
+ connect: backend.connectErrors,
628
+ handshake: backend.handshakeErrors,
629
+ request: backend.requestErrors,
630
+ h2Failures: backend.h2Failures,
631
+ },
632
+ suppression: {
633
+ h2Suppressed: backend.h2Suppressed,
634
+ h3Suppressed: backend.h3Suppressed,
635
+ h2CooldownRemainingSecs: backend.h2CooldownRemainingSecs,
636
+ h3CooldownRemainingSecs: backend.h3CooldownRemainingSecs,
637
+ h2ConsecutiveFailures: backend.h2ConsecutiveFailures,
638
+ h3ConsecutiveFailures: backend.h3ConsecutiveFailures,
639
+ },
640
+ h3Port: backend.h3Port,
641
+ cacheAgeSecs: backend.cacheAgeSecs,
642
+ }, null, 2)}
643
+ ></dees-dataview-codebox>
644
+ </div>
645
+ `,
646
+ menuOptions: [
647
+ {
648
+ name: 'Copy Backend Key',
649
+ iconName: 'lucide:Copy',
650
+ action: async () => {
651
+ await navigator.clipboard.writeText(backend.backend);
652
+ }
653
+ }
654
+ ]
655
+ });
656
+ }
657
+
522
658
  private async updateNetworkData() {
523
659
  // Track requests/sec history for the trend sparkline (moved out of render)
524
660
  const reqPerSec = this.networkState.requestsPerSecond || 0;