@serve.zone/dcrouter 17.2.2 → 17.2.4
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/deno.json +1 -1
- package/dist_serve/bundle.js +1649 -1567
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts_web/00_commitinfo_data.js +1 -1
- package/dist_ts_web/elements/network/network-activity-history.js +24 -9
- package/dist_ts_web/elements/network/network-activity-visuals.d.ts +27 -0
- package/dist_ts_web/elements/network/network-activity-visuals.js +73 -0
- package/dist_ts_web/elements/network/ops-view-network-activity.d.ts +0 -1
- package/dist_ts_web/elements/network/ops-view-network-activity.js +21 -43
- package/package.json +3 -3
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/ts_web/elements/network/network-activity-history.ts +32 -9
- package/ts_web/elements/network/network-activity-visuals.ts +93 -0
- package/ts_web/elements/network/ops-view-network-activity.ts +33 -39
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import {
|
|
2
|
+
NETWORK_ACTIVITY_PROTOCOL_ORDER,
|
|
3
|
+
orderNetworkActivityProtocolNames,
|
|
4
|
+
} from './network-activity-visuals.js';
|
|
5
|
+
|
|
1
6
|
export interface IChartPoint {
|
|
2
7
|
x: string | number;
|
|
3
8
|
y: number;
|
|
@@ -14,9 +19,19 @@ export type TProtocolChartSeries = Array<{
|
|
|
14
19
|
data: IChartPoint[];
|
|
15
20
|
}>;
|
|
16
21
|
|
|
17
|
-
export const PROTOCOL_ORDER =
|
|
22
|
+
export const PROTOCOL_ORDER = NETWORK_ACTIVITY_PROTOCOL_ORDER;
|
|
18
23
|
export const PROTOCOL_SERIES_ORDER = ['Total Active', ...PROTOCOL_ORDER] as const;
|
|
19
24
|
|
|
25
|
+
const getProtocolSeriesOrder = (
|
|
26
|
+
protocolNamesArg: string[],
|
|
27
|
+
): string[] => [
|
|
28
|
+
'Total Active',
|
|
29
|
+
...orderNetworkActivityProtocolNames([
|
|
30
|
+
...PROTOCOL_ORDER,
|
|
31
|
+
...protocolNamesArg,
|
|
32
|
+
]),
|
|
33
|
+
];
|
|
34
|
+
|
|
20
35
|
const toEpochSecond = (timestampArg: string | number): number => {
|
|
21
36
|
const timestampMs = typeof timestampArg === 'number'
|
|
22
37
|
? timestampArg
|
|
@@ -59,7 +74,9 @@ export const mergeChartPoints = (
|
|
|
59
74
|
|
|
60
75
|
export const createProtocolConnectionSeries = (
|
|
61
76
|
historyArg: IProtocolConnectionHistoryPointLike[] = [],
|
|
62
|
-
): TProtocolChartSeries =>
|
|
77
|
+
): TProtocolChartSeries => getProtocolSeriesOrder(
|
|
78
|
+
historyArg.flatMap((point) => Object.keys(point.protocols)),
|
|
79
|
+
).map((seriesName) => ({
|
|
63
80
|
name: seriesName,
|
|
64
81
|
data: historyArg.map((point) => ({
|
|
65
82
|
x: new Date(point.timestamp).toISOString(),
|
|
@@ -79,8 +96,12 @@ export const mergeProtocolConnectionHistory = (
|
|
|
79
96
|
createProtocolConnectionSeries(canonicalHistoryArg)
|
|
80
97
|
.map((series) => [series.name, series]),
|
|
81
98
|
);
|
|
99
|
+
const seriesOrder = getProtocolSeriesOrder([
|
|
100
|
+
...localSeriesArg.map((series) => series.name),
|
|
101
|
+
...canonicalHistoryArg.flatMap((point) => Object.keys(point.protocols)),
|
|
102
|
+
]);
|
|
82
103
|
|
|
83
|
-
return
|
|
104
|
+
return seriesOrder.map((seriesName) => ({
|
|
84
105
|
name: seriesName,
|
|
85
106
|
data: mergeChartPoints(
|
|
86
107
|
localSeriesByName.get(seriesName)?.data ?? [],
|
|
@@ -92,10 +113,9 @@ export const mergeProtocolConnectionHistory = (
|
|
|
92
113
|
|
|
93
114
|
export const getProtocolConnectionTotal = (
|
|
94
115
|
protocolsArg: Record<string, number>,
|
|
95
|
-
): number => (protocolsArg
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
+ (protocolsArg.Other ?? 0);
|
|
116
|
+
): number => Object.entries(protocolsArg)
|
|
117
|
+
.filter(([name]) => name !== 'WebSocket')
|
|
118
|
+
.reduce((total, [, count]) => total + count, 0);
|
|
99
119
|
|
|
100
120
|
export const appendProtocolConnectionSample = (
|
|
101
121
|
localSeriesArg: TProtocolChartSeries,
|
|
@@ -104,7 +124,11 @@ export const appendProtocolConnectionSample = (
|
|
|
104
124
|
maximumPointsArg: number,
|
|
105
125
|
): TProtocolChartSeries => {
|
|
106
126
|
const localSeriesByName = new Map(localSeriesArg.map((series) => [series.name, series]));
|
|
107
|
-
|
|
127
|
+
const seriesOrder = getProtocolSeriesOrder([
|
|
128
|
+
...localSeriesArg.map((series) => series.name),
|
|
129
|
+
...Object.keys(protocolsArg),
|
|
130
|
+
]);
|
|
131
|
+
return seriesOrder.map((seriesName) => ({
|
|
108
132
|
name: seriesName,
|
|
109
133
|
data: mergeChartPoints(
|
|
110
134
|
localSeriesByName.get(seriesName)?.data ?? [],
|
|
@@ -123,4 +147,3 @@ export const shouldRestartNetworkActivityTimer = (
|
|
|
123
147
|
isConnectedArg: boolean,
|
|
124
148
|
documentHiddenArg: boolean,
|
|
125
149
|
): boolean => isConnectedArg && !documentHiddenArg;
|
|
126
|
-
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
export const NETWORK_ACTIVITY_COLORS = {
|
|
2
|
+
'Total Active': '#64748b',
|
|
3
|
+
'HTTP/1.1': '#1976d2',
|
|
4
|
+
'HTTP/2': '#388e3c',
|
|
5
|
+
'HTTP/3': '#7b1fa2',
|
|
6
|
+
'WebSocket': '#f57c00',
|
|
7
|
+
'Other': '#757575',
|
|
8
|
+
'Inbound': '#22c55e',
|
|
9
|
+
'Outbound': '#8b5cf6',
|
|
10
|
+
'Requests/sec': '#3b82f6',
|
|
11
|
+
} as const;
|
|
12
|
+
|
|
13
|
+
export const NETWORK_ACTIVITY_PROTOCOL_ORDER = [
|
|
14
|
+
'HTTP/1.1',
|
|
15
|
+
'HTTP/2',
|
|
16
|
+
'HTTP/3',
|
|
17
|
+
'WebSocket',
|
|
18
|
+
'Other',
|
|
19
|
+
] as const;
|
|
20
|
+
|
|
21
|
+
export const PROTOCOL_CONNECTION_LEGEND_STATS: Array<'latest'> = ['latest'];
|
|
22
|
+
export const PROTOCOL_CONNECTION_CHART_LINES: Array<'avg' | 'max'> = [];
|
|
23
|
+
|
|
24
|
+
export const NETWORK_ACTIVITY_FALLBACK_COLORS = [
|
|
25
|
+
'#007aff',
|
|
26
|
+
'#32ade6',
|
|
27
|
+
'#af52de',
|
|
28
|
+
'#ff9500',
|
|
29
|
+
'#34c759',
|
|
30
|
+
'#ff2d55',
|
|
31
|
+
] as const;
|
|
32
|
+
|
|
33
|
+
const knownProtocolNames = new Set<string>(NETWORK_ACTIVITY_PROTOCOL_ORDER);
|
|
34
|
+
|
|
35
|
+
export const getNetworkActivityColor = (
|
|
36
|
+
nameArg: string,
|
|
37
|
+
fallbackIndexArg = 0,
|
|
38
|
+
): string => {
|
|
39
|
+
const canonicalColor = NETWORK_ACTIVITY_COLORS[
|
|
40
|
+
nameArg as keyof typeof NETWORK_ACTIVITY_COLORS
|
|
41
|
+
];
|
|
42
|
+
if (canonicalColor) return canonicalColor;
|
|
43
|
+
const fallbackIndex = Math.max(0, Math.trunc(fallbackIndexArg));
|
|
44
|
+
return NETWORK_ACTIVITY_FALLBACK_COLORS[
|
|
45
|
+
fallbackIndex % NETWORK_ACTIVITY_FALLBACK_COLORS.length
|
|
46
|
+
];
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export const orderNetworkActivityProtocolNames = (
|
|
50
|
+
namesArg: string[],
|
|
51
|
+
): string[] => {
|
|
52
|
+
const names = new Set(namesArg.filter((name) => name && name !== 'Total Active'));
|
|
53
|
+
const orderedKnown = NETWORK_ACTIVITY_PROTOCOL_ORDER
|
|
54
|
+
.filter((name) => name !== 'Other' && names.has(name));
|
|
55
|
+
const orderedUnknown = [...names]
|
|
56
|
+
.filter((name) => !knownProtocolNames.has(name))
|
|
57
|
+
.sort((nameA, nameB) => nameA.localeCompare(nameB));
|
|
58
|
+
return [
|
|
59
|
+
...orderedKnown,
|
|
60
|
+
...orderedUnknown,
|
|
61
|
+
...(names.has('Other') ? ['Other'] : []),
|
|
62
|
+
];
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
export const createNetworkProtocolDonutData = (
|
|
66
|
+
countsArg: Record<string, number>,
|
|
67
|
+
paletteProtocolNamesArg: string[] = [],
|
|
68
|
+
): Array<{ name: string; value: number; color: string }> => {
|
|
69
|
+
const orderedNames = orderNetworkActivityProtocolNames(Object.keys(countsArg));
|
|
70
|
+
const paletteNames = orderNetworkActivityProtocolNames([
|
|
71
|
+
...orderedNames,
|
|
72
|
+
...paletteProtocolNamesArg,
|
|
73
|
+
]);
|
|
74
|
+
const unknownNames = paletteNames.filter((name) => !knownProtocolNames.has(name));
|
|
75
|
+
return orderedNames
|
|
76
|
+
.filter((name) => (countsArg[name] ?? 0) > 0)
|
|
77
|
+
.map((name) => ({
|
|
78
|
+
name,
|
|
79
|
+
value: countsArg[name] ?? 0,
|
|
80
|
+
color: getNetworkActivityColor(name, unknownNames.indexOf(name)),
|
|
81
|
+
}));
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export const colorNetworkProtocolSeries = <T extends { name: string }>(
|
|
85
|
+
seriesArg: T[],
|
|
86
|
+
): Array<T & { color: string }> => {
|
|
87
|
+
const orderedNames = orderNetworkActivityProtocolNames(seriesArg.map((series) => series.name));
|
|
88
|
+
const unknownNames = orderedNames.filter((name) => !knownProtocolNames.has(name));
|
|
89
|
+
return seriesArg.map((series) => ({
|
|
90
|
+
...series,
|
|
91
|
+
color: getNetworkActivityColor(series.name, unknownNames.indexOf(series.name)),
|
|
92
|
+
}));
|
|
93
|
+
};
|
|
@@ -14,14 +14,14 @@ import {
|
|
|
14
14
|
type IChartPoint,
|
|
15
15
|
type TProtocolChartSeries,
|
|
16
16
|
} from './network-activity-history.js';
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
};
|
|
17
|
+
import {
|
|
18
|
+
NETWORK_ACTIVITY_COLORS,
|
|
19
|
+
PROTOCOL_CONNECTION_CHART_LINES,
|
|
20
|
+
PROTOCOL_CONNECTION_LEGEND_STATS,
|
|
21
|
+
colorNetworkProtocolSeries,
|
|
22
|
+
createNetworkProtocolDonutData,
|
|
23
|
+
getNetworkActivityColor,
|
|
24
|
+
} from './network-activity-visuals.js';
|
|
25
25
|
|
|
26
26
|
declare global {
|
|
27
27
|
interface HTMLElementTagNameMap {
|
|
@@ -181,13 +181,6 @@ export class OpsViewNetworkActivity extends DeesElement {
|
|
|
181
181
|
};
|
|
182
182
|
}
|
|
183
183
|
|
|
184
|
-
private getProtocolSeriesWithColors(seriesArg: TProtocolChartSeries) {
|
|
185
|
-
return seriesArg.map((series) => ({
|
|
186
|
-
...series,
|
|
187
|
-
color: series.name === 'Total Active' ? '#ef4444' : (PROTOCOL_COLORS[series.name] ?? '#757575'),
|
|
188
|
-
}));
|
|
189
|
-
}
|
|
190
|
-
|
|
191
184
|
private mergeProtocolConnectionHistories(): void {
|
|
192
185
|
const frontendHistory = this.networkState.frontendConnectionHistory || [];
|
|
193
186
|
const latestFrontendEpochSecond = getLatestHistoryEpochSecond(frontendHistory);
|
|
@@ -389,12 +382,12 @@ export class OpsViewNetworkActivity extends DeesElement {
|
|
|
389
382
|
{
|
|
390
383
|
name: 'Inbound',
|
|
391
384
|
data: this.trafficDataIn,
|
|
392
|
-
color:
|
|
385
|
+
color: NETWORK_ACTIVITY_COLORS.Inbound,
|
|
393
386
|
},
|
|
394
387
|
{
|
|
395
388
|
name: 'Outbound',
|
|
396
389
|
data: this.trafficDataOut,
|
|
397
|
-
color:
|
|
390
|
+
color: NETWORK_ACTIVITY_COLORS.Outbound,
|
|
398
391
|
}
|
|
399
392
|
]}
|
|
400
393
|
.realtimeMode=${true}
|
|
@@ -602,7 +595,7 @@ export class OpsViewNetworkActivity extends DeesElement {
|
|
|
602
595
|
value: activeConnections,
|
|
603
596
|
type: 'number',
|
|
604
597
|
icon: 'lucide:Plug',
|
|
605
|
-
color:
|
|
598
|
+
color: NETWORK_ACTIVITY_COLORS['Total Active'],
|
|
606
599
|
description: `Total: ${this.formatNumber(this.statsState.serverStats?.totalConnections || 0)} connections`,
|
|
607
600
|
actions: [
|
|
608
601
|
{
|
|
@@ -619,7 +612,7 @@ export class OpsViewNetworkActivity extends DeesElement {
|
|
|
619
612
|
value: reqPerSec,
|
|
620
613
|
type: 'trend',
|
|
621
614
|
icon: 'lucide:ChartLine',
|
|
622
|
-
color: '
|
|
615
|
+
color: NETWORK_ACTIVITY_COLORS['Requests/sec'],
|
|
623
616
|
trendData: trendData,
|
|
624
617
|
description: `Total: ${this.formatNumber(this.networkState.requestsTotal || 0)} requests`,
|
|
625
618
|
},
|
|
@@ -630,7 +623,7 @@ export class OpsViewNetworkActivity extends DeesElement {
|
|
|
630
623
|
unit: '',
|
|
631
624
|
type: 'number',
|
|
632
625
|
icon: 'lucide:Download',
|
|
633
|
-
color:
|
|
626
|
+
color: NETWORK_ACTIVITY_COLORS.Inbound,
|
|
634
627
|
description: `Total: ${this.formatBytes(this.networkState.totalBytes?.in || 0)}`,
|
|
635
628
|
},
|
|
636
629
|
{
|
|
@@ -640,7 +633,7 @@ export class OpsViewNetworkActivity extends DeesElement {
|
|
|
640
633
|
unit: '',
|
|
641
634
|
type: 'number',
|
|
642
635
|
icon: 'lucide:Upload',
|
|
643
|
-
color:
|
|
636
|
+
color: NETWORK_ACTIVITY_COLORS.Outbound,
|
|
644
637
|
description: `Total: ${this.formatBytes(this.networkState.totalBytes?.out || 0)}`,
|
|
645
638
|
},
|
|
646
639
|
];
|
|
@@ -657,28 +650,25 @@ export class OpsViewNetworkActivity extends DeesElement {
|
|
|
657
650
|
const fp = this.networkState.frontendProtocols;
|
|
658
651
|
const bp = this.networkState.backendProtocols;
|
|
659
652
|
|
|
660
|
-
const
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
if (dist.otherActive > 0) items.push({ name: 'Other', value: dist.otherActive, color: protoColors['Other'] });
|
|
670
|
-
return items;
|
|
671
|
-
};
|
|
653
|
+
const buildDonutData = (
|
|
654
|
+
dist: interfaces.data.IProtocolDistribution | null,
|
|
655
|
+
historySeries: TProtocolChartSeries,
|
|
656
|
+
) => dist
|
|
657
|
+
? createNetworkProtocolDonutData(
|
|
658
|
+
this.getProtocolCounts(dist),
|
|
659
|
+
historySeries.map((series) => series.name),
|
|
660
|
+
)
|
|
661
|
+
: [];
|
|
672
662
|
|
|
673
|
-
const frontendData = buildDonutData(fp);
|
|
674
|
-
const backendData = buildDonutData(bp);
|
|
663
|
+
const frontendData = buildDonutData(fp, this.frontendConnectionSeries);
|
|
664
|
+
const backendData = buildDonutData(bp, this.backendConnectionSeries);
|
|
675
665
|
|
|
676
666
|
return html`
|
|
677
667
|
<div class="protocolChartGrid">
|
|
678
668
|
<div class="protocolChartColumn">
|
|
679
669
|
<dees-chart-donut
|
|
680
670
|
.label=${'Frontend Protocols'}
|
|
681
|
-
.data=${frontendData.length > 0 ? frontendData : [{ name: 'No Traffic', value: 1, color: '
|
|
671
|
+
.data=${frontendData.length > 0 ? frontendData : [{ name: 'No Traffic', value: 1, color: getNetworkActivityColor('Other') }]}
|
|
682
672
|
.showLegend=${true}
|
|
683
673
|
.showLabels=${true}
|
|
684
674
|
.innerRadiusPercent=${'55%'}
|
|
@@ -686,7 +676,9 @@ export class OpsViewNetworkActivity extends DeesElement {
|
|
|
686
676
|
></dees-chart-donut>
|
|
687
677
|
<dees-chart-area
|
|
688
678
|
.label=${'Frontend Active Connections'}
|
|
689
|
-
.series=${
|
|
679
|
+
.series=${colorNetworkProtocolSeries(this.frontendConnectionSeries)}
|
|
680
|
+
.legendStats=${PROTOCOL_CONNECTION_LEGEND_STATS}
|
|
681
|
+
.chartLines=${PROTOCOL_CONNECTION_CHART_LINES}
|
|
690
682
|
.realtimeMode=${true}
|
|
691
683
|
.rollingWindow=${OpsViewNetworkActivity.CHART_WINDOW_MS}
|
|
692
684
|
.yAxisFormatter=${(val: number) => `${Math.round(val)} active`}
|
|
@@ -695,7 +687,7 @@ export class OpsViewNetworkActivity extends DeesElement {
|
|
|
695
687
|
<div class="protocolChartColumn">
|
|
696
688
|
<dees-chart-donut
|
|
697
689
|
.label=${'Backend Protocols'}
|
|
698
|
-
.data=${backendData.length > 0 ? backendData : [{ name: 'No Traffic', value: 1, color: '
|
|
690
|
+
.data=${backendData.length > 0 ? backendData : [{ name: 'No Traffic', value: 1, color: getNetworkActivityColor('Other') }]}
|
|
699
691
|
.showLegend=${true}
|
|
700
692
|
.showLabels=${true}
|
|
701
693
|
.innerRadiusPercent=${'55%'}
|
|
@@ -703,7 +695,9 @@ export class OpsViewNetworkActivity extends DeesElement {
|
|
|
703
695
|
></dees-chart-donut>
|
|
704
696
|
<dees-chart-area
|
|
705
697
|
.label=${'Backend Active Connections'}
|
|
706
|
-
.series=${
|
|
698
|
+
.series=${colorNetworkProtocolSeries(this.backendConnectionSeries)}
|
|
699
|
+
.legendStats=${PROTOCOL_CONNECTION_LEGEND_STATS}
|
|
700
|
+
.chartLines=${PROTOCOL_CONNECTION_CHART_LINES}
|
|
707
701
|
.realtimeMode=${true}
|
|
708
702
|
.rollingWindow=${OpsViewNetworkActivity.CHART_WINDOW_MS}
|
|
709
703
|
.yAxisFormatter=${(val: number) => `${Math.round(val)} active`}
|