@serve.zone/dcrouter 13.13.0 → 13.15.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.
- package/dist_serve/bundle.js +811 -803
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/monitoring/classes.metricsmanager.d.ts +26 -0
- package/dist_ts/monitoring/classes.metricsmanager.js +72 -2
- package/dist_ts/opsserver/handlers/security.handler.js +27 -23
- package/dist_ts/opsserver/handlers/stats.handler.js +22 -3
- package/dist_ts_interfaces/data/stats.d.ts +17 -1
- package/dist_ts_interfaces/requests/stats.d.ts +9 -0
- package/dist_ts_oci_container/plugins.d.ts +3 -0
- package/dist_ts_oci_container/plugins.js +4 -0
- package/dist_ts_web/00_commitinfo_data.js +1 -1
- package/dist_ts_web/appstate.d.ts +7 -0
- package/dist_ts_web/appstate.js +45 -54
- package/dist_ts_web/elements/domains/ops-view-domains.js +9 -11
- package/dist_ts_web/elements/network/ops-view-network-activity.d.ts +2 -20
- package/dist_ts_web/elements/network/ops-view-network-activity.js +65 -115
- package/package.json +1 -1
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/monitoring/classes.metricsmanager.ts +77 -1
- package/ts/opsserver/handlers/security.handler.ts +27 -23
- package/ts/opsserver/handlers/stats.handler.ts +22 -2
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/ts_web/appstate.ts +53 -63
- package/ts_web/elements/domains/ops-view-domains.ts +8 -10
- package/ts_web/elements/network/ops-view-network-activity.ts +67 -132
|
@@ -10,22 +10,6 @@ declare global {
|
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
interface INetworkRequest {
|
|
14
|
-
id: string;
|
|
15
|
-
timestamp: number;
|
|
16
|
-
method: string;
|
|
17
|
-
url: string;
|
|
18
|
-
hostname: string;
|
|
19
|
-
port: number;
|
|
20
|
-
protocol: 'http' | 'https' | 'tcp' | 'udp';
|
|
21
|
-
statusCode?: number;
|
|
22
|
-
duration: number;
|
|
23
|
-
bytesIn: number;
|
|
24
|
-
bytesOut: number;
|
|
25
|
-
remoteIp: string;
|
|
26
|
-
route?: string;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
13
|
@customElement('ops-view-network-activity')
|
|
30
14
|
export class OpsViewNetworkActivity extends DeesElement {
|
|
31
15
|
/** How far back the traffic chart shows */
|
|
@@ -42,9 +26,6 @@ export class OpsViewNetworkActivity extends DeesElement {
|
|
|
42
26
|
accessor networkState = appstate.networkStatePart.getState()!;
|
|
43
27
|
|
|
44
28
|
|
|
45
|
-
@state()
|
|
46
|
-
accessor networkRequests: INetworkRequest[] = [];
|
|
47
|
-
|
|
48
29
|
@state()
|
|
49
30
|
accessor trafficDataIn: Array<{ x: string | number; y: number }> = [];
|
|
50
31
|
|
|
@@ -314,108 +295,21 @@ export class OpsViewNetworkActivity extends DeesElement {
|
|
|
314
295
|
<!-- Protocol Distribution Charts -->
|
|
315
296
|
${this.renderProtocolCharts()}
|
|
316
297
|
|
|
317
|
-
<!-- Top IPs
|
|
298
|
+
<!-- Top IPs by Connection Count -->
|
|
318
299
|
${this.renderTopIPs()}
|
|
319
300
|
|
|
301
|
+
<!-- Top IPs by Bandwidth -->
|
|
302
|
+
${this.renderTopIPsByBandwidth()}
|
|
303
|
+
|
|
304
|
+
<!-- Domain Activity -->
|
|
305
|
+
${this.renderDomainActivity()}
|
|
306
|
+
|
|
320
307
|
<!-- Backend Protocols Section -->
|
|
321
308
|
${this.renderBackendProtocols()}
|
|
322
|
-
|
|
323
|
-
<!-- Requests Table -->
|
|
324
|
-
<dees-table
|
|
325
|
-
.data=${this.networkRequests}
|
|
326
|
-
.rowKey=${'id'}
|
|
327
|
-
.highlightUpdates=${'flash'}
|
|
328
|
-
.displayFunction=${(req: INetworkRequest) => ({
|
|
329
|
-
Time: new Date(req.timestamp).toLocaleTimeString(),
|
|
330
|
-
Protocol: html`<span class="protocolBadge ${req.protocol}">${req.protocol.toUpperCase()}</span>`,
|
|
331
|
-
Method: req.method,
|
|
332
|
-
'Host:Port': `${req.hostname}:${req.port}`,
|
|
333
|
-
Path: this.truncateUrl(req.url),
|
|
334
|
-
Status: this.renderStatus(req.statusCode),
|
|
335
|
-
Duration: `${req.duration}ms`,
|
|
336
|
-
'In/Out': `${this.formatBytes(req.bytesIn)} / ${this.formatBytes(req.bytesOut)}`,
|
|
337
|
-
'Remote IP': req.remoteIp,
|
|
338
|
-
})}
|
|
339
|
-
.dataActions=${[
|
|
340
|
-
{
|
|
341
|
-
name: 'View Details',
|
|
342
|
-
iconName: 'fa:magnifyingGlass',
|
|
343
|
-
type: ['inRow', 'doubleClick', 'contextmenu'],
|
|
344
|
-
actionFunc: async (actionData) => {
|
|
345
|
-
await this.showRequestDetails(actionData.item);
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
]}
|
|
349
|
-
heading1="Recent Network Activity"
|
|
350
|
-
heading2="Recent network requests"
|
|
351
|
-
searchable
|
|
352
|
-
.showColumnFilters=${true}
|
|
353
|
-
.pagination=${true}
|
|
354
|
-
.paginationSize=${50}
|
|
355
|
-
dataName="request"
|
|
356
|
-
></dees-table>
|
|
357
309
|
</div>
|
|
358
310
|
`;
|
|
359
311
|
}
|
|
360
312
|
|
|
361
|
-
private async showRequestDetails(request: INetworkRequest) {
|
|
362
|
-
const { DeesModal } = await import('@design.estate/dees-catalog');
|
|
363
|
-
|
|
364
|
-
await DeesModal.createAndShow({
|
|
365
|
-
heading: 'Request Details',
|
|
366
|
-
content: html`
|
|
367
|
-
<div style="padding: 20px;">
|
|
368
|
-
<dees-dataview-codebox
|
|
369
|
-
.heading=${'Request Information'}
|
|
370
|
-
progLang="json"
|
|
371
|
-
.codeToDisplay=${JSON.stringify({
|
|
372
|
-
id: request.id,
|
|
373
|
-
timestamp: new Date(request.timestamp).toISOString(),
|
|
374
|
-
protocol: request.protocol,
|
|
375
|
-
method: request.method,
|
|
376
|
-
url: request.url,
|
|
377
|
-
hostname: request.hostname,
|
|
378
|
-
port: request.port,
|
|
379
|
-
statusCode: request.statusCode,
|
|
380
|
-
duration: `${request.duration}ms`,
|
|
381
|
-
bytesIn: request.bytesIn,
|
|
382
|
-
bytesOut: request.bytesOut,
|
|
383
|
-
remoteIp: request.remoteIp,
|
|
384
|
-
route: request.route,
|
|
385
|
-
}, null, 2)}
|
|
386
|
-
></dees-dataview-codebox>
|
|
387
|
-
</div>
|
|
388
|
-
`,
|
|
389
|
-
menuOptions: [
|
|
390
|
-
{
|
|
391
|
-
name: 'Copy Request ID',
|
|
392
|
-
iconName: 'lucide:Copy',
|
|
393
|
-
action: async () => {
|
|
394
|
-
await navigator.clipboard.writeText(request.id);
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
]
|
|
398
|
-
});
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
private renderStatus(statusCode?: number): TemplateResult {
|
|
403
|
-
if (!statusCode) {
|
|
404
|
-
return html`<span class="statusBadge warning">N/A</span>`;
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
const statusClass = statusCode >= 200 && statusCode < 300 ? 'success' :
|
|
408
|
-
statusCode >= 400 ? 'error' : 'warning';
|
|
409
|
-
|
|
410
|
-
return html`<span class="statusBadge ${statusClass}">${statusCode}</span>`;
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
private truncateUrl(url: string, maxLength = 50): string {
|
|
414
|
-
if (url.length <= maxLength) return url;
|
|
415
|
-
return url.substring(0, maxLength - 3) + '...';
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
|
|
419
313
|
private formatNumber(num: number): string {
|
|
420
314
|
if (num >= 1000000) {
|
|
421
315
|
return (num / 1000000).toFixed(1) + 'M';
|
|
@@ -619,6 +513,66 @@ export class OpsViewNetworkActivity extends DeesElement {
|
|
|
619
513
|
`;
|
|
620
514
|
}
|
|
621
515
|
|
|
516
|
+
private renderTopIPsByBandwidth(): TemplateResult {
|
|
517
|
+
if (!this.networkState.topIPsByBandwidth || this.networkState.topIPsByBandwidth.length === 0) {
|
|
518
|
+
return html``;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
return html`
|
|
522
|
+
<dees-table
|
|
523
|
+
.data=${this.networkState.topIPsByBandwidth}
|
|
524
|
+
.rowKey=${'ip'}
|
|
525
|
+
.highlightUpdates=${'flash'}
|
|
526
|
+
.displayFunction=${(ipData: { ip: string; count: number; bwIn: number; bwOut: number }) => {
|
|
527
|
+
return {
|
|
528
|
+
'IP Address': ipData.ip,
|
|
529
|
+
'Bandwidth In': this.formatBitsPerSecond(ipData.bwIn),
|
|
530
|
+
'Bandwidth Out': this.formatBitsPerSecond(ipData.bwOut),
|
|
531
|
+
'Total Bandwidth': this.formatBitsPerSecond(ipData.bwIn + ipData.bwOut),
|
|
532
|
+
'Connections': ipData.count,
|
|
533
|
+
};
|
|
534
|
+
}}
|
|
535
|
+
heading1="Top IPs by Bandwidth"
|
|
536
|
+
heading2="IPs with highest throughput"
|
|
537
|
+
searchable
|
|
538
|
+
.showColumnFilters=${true}
|
|
539
|
+
.pagination=${false}
|
|
540
|
+
dataName="ip"
|
|
541
|
+
></dees-table>
|
|
542
|
+
`;
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
private renderDomainActivity(): TemplateResult {
|
|
546
|
+
if (!this.networkState.domainActivity || this.networkState.domainActivity.length === 0) {
|
|
547
|
+
return html``;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
return html`
|
|
551
|
+
<dees-table
|
|
552
|
+
.data=${this.networkState.domainActivity}
|
|
553
|
+
.rowKey=${'domain'}
|
|
554
|
+
.highlightUpdates=${'flash'}
|
|
555
|
+
.displayFunction=${(item: interfaces.data.IDomainActivity) => {
|
|
556
|
+
const totalBytesPerMin = (item.bytesInPerSecond + item.bytesOutPerSecond) * 60;
|
|
557
|
+
return {
|
|
558
|
+
'Domain': item.domain,
|
|
559
|
+
'Throughput In': this.formatBitsPerSecond(item.bytesInPerSecond),
|
|
560
|
+
'Throughput Out': this.formatBitsPerSecond(item.bytesOutPerSecond),
|
|
561
|
+
'Transferred / min': this.formatBytes(totalBytesPerMin),
|
|
562
|
+
'Connections': item.activeConnections,
|
|
563
|
+
'Routes': item.routeCount,
|
|
564
|
+
};
|
|
565
|
+
}}
|
|
566
|
+
heading1="Domain Activity"
|
|
567
|
+
heading2="Per-domain network activity aggregated from route metrics"
|
|
568
|
+
searchable
|
|
569
|
+
.showColumnFilters=${true}
|
|
570
|
+
.pagination=${false}
|
|
571
|
+
dataName="domain"
|
|
572
|
+
></dees-table>
|
|
573
|
+
`;
|
|
574
|
+
}
|
|
575
|
+
|
|
622
576
|
private renderBackendProtocols(): TemplateResult {
|
|
623
577
|
const backends = this.networkState.backends;
|
|
624
578
|
if (!backends || backends.length === 0) {
|
|
@@ -730,25 +684,6 @@ export class OpsViewNetworkActivity extends DeesElement {
|
|
|
730
684
|
this.requestsPerSecHistory.shift();
|
|
731
685
|
}
|
|
732
686
|
|
|
733
|
-
// Reassign unconditionally so dees-table's flash diff can compare per-cell
|
|
734
|
-
// values against the previous snapshot. Row identity is preserved via
|
|
735
|
-
// rowKey='id', so DOM nodes are reused across ticks.
|
|
736
|
-
this.networkRequests = this.networkState.connections.map((conn) => ({
|
|
737
|
-
id: conn.id,
|
|
738
|
-
timestamp: conn.startTime,
|
|
739
|
-
method: 'GET', // Default method for proxy connections
|
|
740
|
-
url: '/',
|
|
741
|
-
hostname: conn.remoteAddress,
|
|
742
|
-
port: conn.protocol === 'https' ? 443 : 80,
|
|
743
|
-
protocol: conn.protocol === 'https' || conn.protocol === 'http' ? conn.protocol : 'tcp',
|
|
744
|
-
statusCode: conn.state === 'connected' ? 200 : undefined,
|
|
745
|
-
duration: Date.now() - conn.startTime,
|
|
746
|
-
bytesIn: conn.bytesReceived,
|
|
747
|
-
bytesOut: conn.bytesSent,
|
|
748
|
-
remoteIp: conn.remoteAddress,
|
|
749
|
-
route: 'proxy',
|
|
750
|
-
}));
|
|
751
|
-
|
|
752
687
|
// Load server-side throughput history into chart (once)
|
|
753
688
|
if (!this.historyLoaded && this.networkState.throughputHistory && this.networkState.throughputHistory.length > 0) {
|
|
754
689
|
this.loadThroughputHistory();
|