@serve.zone/dcrouter 17.1.8 → 17.2.1
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 +886 -860
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/monitoring/classes.metricsmanager.d.ts +5 -1
- package/dist_ts/monitoring/classes.metricsmanager.js +18 -3
- package/dist_ts/opsserver/handlers/security.handler.js +5 -1
- package/dist_ts/opsserver/handlers/stats.handler.js +3 -1
- package/dist_ts_interfaces/data/stats.d.ts +7 -0
- package/dist_ts_interfaces/requests/stats.d.ts +2 -0
- package/dist_ts_web/00_commitinfo_data.js +1 -1
- package/dist_ts_web/appstate/network.d.ts +2 -0
- package/dist_ts_web/appstate/network.js +5 -1
- package/dist_ts_web/appstate/runtime.js +3 -1
- package/dist_ts_web/elements/network/network-activity-history.d.ts +24 -0
- package/dist_ts_web/elements/network/network-activity-history.js +65 -0
- package/dist_ts_web/elements/network/ops-view-network-activity.d.ts +14 -17
- package/dist_ts_web/elements/network/ops-view-network-activity.js +139 -77
- package/package.json +3 -3
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/monitoring/classes.metricsmanager.ts +18 -3
- package/ts/opsserver/handlers/security.handler.ts +4 -0
- package/ts/opsserver/handlers/stats.handler.ts +2 -0
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/ts_web/appstate/network.ts +6 -0
- package/ts_web/appstate/runtime.ts +2 -0
- package/ts_web/elements/network/network-activity-history.ts +126 -0
- package/ts_web/elements/network/ops-view-network-activity.ts +180 -81
|
@@ -19,6 +19,8 @@ export interface INetworkState {
|
|
|
19
19
|
ipIntelligence: interfaces.data.IIpIntelligenceRecord[];
|
|
20
20
|
domainActivity: interfaces.data.IDomainActivity[];
|
|
21
21
|
throughputHistory: Array<{ timestamp: number; in: number; out: number }>;
|
|
22
|
+
frontendConnectionHistory: interfaces.data.IProtocolConnectionHistoryPoint[];
|
|
23
|
+
backendConnectionHistory: interfaces.data.IProtocolConnectionHistoryPoint[];
|
|
22
24
|
requestsPerSecond: number;
|
|
23
25
|
requestsTotal: number;
|
|
24
26
|
backends: interfaces.data.IBackendInfo[];
|
|
@@ -43,6 +45,8 @@ export const networkStatePart = await appState.getStatePart<INetworkState>(
|
|
|
43
45
|
ipIntelligence: [],
|
|
44
46
|
domainActivity: [],
|
|
45
47
|
throughputHistory: [],
|
|
48
|
+
frontendConnectionHistory: [],
|
|
49
|
+
backendConnectionHistory: [],
|
|
46
50
|
requestsPerSecond: 0,
|
|
47
51
|
requestsTotal: 0,
|
|
48
52
|
backends: [],
|
|
@@ -150,6 +154,8 @@ export const fetchNetworkStatsAction = networkStatePart.createAction(async (stat
|
|
|
150
154
|
ipIntelligence: currentState.ipIntelligence,
|
|
151
155
|
domainActivity: networkStatsResponse.domainActivity || [],
|
|
152
156
|
throughputHistory: networkStatsResponse.throughputHistory || [],
|
|
157
|
+
frontendConnectionHistory: networkStatsResponse.frontendConnectionHistory || [],
|
|
158
|
+
backendConnectionHistory: networkStatsResponse.backendConnectionHistory || [],
|
|
153
159
|
requestsPerSecond: networkStatsResponse.requestsPerSecond || 0,
|
|
154
160
|
requestsTotal: networkStatsResponse.requestsTotal || 0,
|
|
155
161
|
backends: networkStatsResponse.backends || [],
|
|
@@ -340,6 +340,8 @@ async function dispatchCombinedRefreshActionInner() {
|
|
|
340
340
|
throughputByIP: network.topEndpoints.map(e => ({ ip: e.endpoint, in: e.bandwidth?.in || 0, out: e.bandwidth?.out || 0 })),
|
|
341
341
|
domainActivity: network.domainActivity || [],
|
|
342
342
|
throughputHistory: network.throughputHistory || [],
|
|
343
|
+
frontendConnectionHistory: network.frontendConnectionHistory || [],
|
|
344
|
+
backendConnectionHistory: network.backendConnectionHistory || [],
|
|
343
345
|
requestsPerSecond: network.requestsPerSecond || 0,
|
|
344
346
|
requestsTotal: network.requestsTotal || 0,
|
|
345
347
|
backends: network.backends || [],
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
export interface IChartPoint {
|
|
2
|
+
x: string | number;
|
|
3
|
+
y: number;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export interface IProtocolConnectionHistoryPointLike {
|
|
7
|
+
timestamp: number;
|
|
8
|
+
total: number;
|
|
9
|
+
protocols: Record<string, number>;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export type TProtocolChartSeries = Array<{
|
|
13
|
+
name: string;
|
|
14
|
+
data: IChartPoint[];
|
|
15
|
+
}>;
|
|
16
|
+
|
|
17
|
+
export const PROTOCOL_ORDER = ['HTTP/1.1', 'HTTP/2', 'HTTP/3', 'WebSocket', 'Other'] as const;
|
|
18
|
+
export const PROTOCOL_SERIES_ORDER = ['Total Active', ...PROTOCOL_ORDER] as const;
|
|
19
|
+
|
|
20
|
+
const toEpochSecond = (timestampArg: string | number): number => {
|
|
21
|
+
const timestampMs = typeof timestampArg === 'number'
|
|
22
|
+
? timestampArg
|
|
23
|
+
: new Date(timestampArg).getTime();
|
|
24
|
+
return Math.floor(timestampMs / 1000);
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export const getLatestHistoryEpochSecond = (
|
|
28
|
+
historyArg: Array<{ timestamp: number }>,
|
|
29
|
+
): number => historyArg.reduce(
|
|
30
|
+
(latest, point) => Math.max(latest, Math.floor(point.timestamp / 1000)),
|
|
31
|
+
0,
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
export const mergeChartPoints = (
|
|
35
|
+
localPointsArg: IChartPoint[],
|
|
36
|
+
canonicalPointsArg: IChartPoint[],
|
|
37
|
+
maximumPointsArg: number,
|
|
38
|
+
): IChartPoint[] => {
|
|
39
|
+
const pointsBySecond = new Map<number, IChartPoint>();
|
|
40
|
+
for (const point of localPointsArg) {
|
|
41
|
+
const epochSecond = toEpochSecond(point.x);
|
|
42
|
+
if (Number.isFinite(epochSecond)) {
|
|
43
|
+
pointsBySecond.set(epochSecond, point);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
// Canonical engine samples win when a locally repeated cached sample used the same second.
|
|
47
|
+
for (const point of canonicalPointsArg) {
|
|
48
|
+
const epochSecond = toEpochSecond(point.x);
|
|
49
|
+
if (Number.isFinite(epochSecond)) {
|
|
50
|
+
pointsBySecond.set(epochSecond, point);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return [...pointsBySecond.entries()]
|
|
55
|
+
.sort(([secondA], [secondB]) => secondA - secondB)
|
|
56
|
+
.map(([, point]) => point)
|
|
57
|
+
.slice(-maximumPointsArg);
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export const createProtocolConnectionSeries = (
|
|
61
|
+
historyArg: IProtocolConnectionHistoryPointLike[] = [],
|
|
62
|
+
): TProtocolChartSeries => PROTOCOL_SERIES_ORDER.map((seriesName) => ({
|
|
63
|
+
name: seriesName,
|
|
64
|
+
data: historyArg.map((point) => ({
|
|
65
|
+
x: new Date(point.timestamp).toISOString(),
|
|
66
|
+
y: seriesName === 'Total Active'
|
|
67
|
+
? point.total
|
|
68
|
+
: (point.protocols[seriesName] ?? 0),
|
|
69
|
+
})),
|
|
70
|
+
}));
|
|
71
|
+
|
|
72
|
+
export const mergeProtocolConnectionHistory = (
|
|
73
|
+
localSeriesArg: TProtocolChartSeries,
|
|
74
|
+
canonicalHistoryArg: IProtocolConnectionHistoryPointLike[],
|
|
75
|
+
maximumPointsArg: number,
|
|
76
|
+
): TProtocolChartSeries => {
|
|
77
|
+
const localSeriesByName = new Map(localSeriesArg.map((series) => [series.name, series]));
|
|
78
|
+
const canonicalSeriesByName = new Map(
|
|
79
|
+
createProtocolConnectionSeries(canonicalHistoryArg)
|
|
80
|
+
.map((series) => [series.name, series]),
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
return PROTOCOL_SERIES_ORDER.map((seriesName) => ({
|
|
84
|
+
name: seriesName,
|
|
85
|
+
data: mergeChartPoints(
|
|
86
|
+
localSeriesByName.get(seriesName)?.data ?? [],
|
|
87
|
+
canonicalSeriesByName.get(seriesName)?.data ?? [],
|
|
88
|
+
maximumPointsArg,
|
|
89
|
+
),
|
|
90
|
+
}));
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
export const getProtocolConnectionTotal = (
|
|
94
|
+
protocolsArg: Record<string, number>,
|
|
95
|
+
): number => (protocolsArg['HTTP/1.1'] ?? 0)
|
|
96
|
+
+ (protocolsArg['HTTP/2'] ?? 0)
|
|
97
|
+
+ (protocolsArg['HTTP/3'] ?? 0)
|
|
98
|
+
+ (protocolsArg.Other ?? 0);
|
|
99
|
+
|
|
100
|
+
export const appendProtocolConnectionSample = (
|
|
101
|
+
localSeriesArg: TProtocolChartSeries,
|
|
102
|
+
timestampArg: string | number,
|
|
103
|
+
protocolsArg: Record<string, number>,
|
|
104
|
+
maximumPointsArg: number,
|
|
105
|
+
): TProtocolChartSeries => {
|
|
106
|
+
const localSeriesByName = new Map(localSeriesArg.map((series) => [series.name, series]));
|
|
107
|
+
return PROTOCOL_SERIES_ORDER.map((seriesName) => ({
|
|
108
|
+
name: seriesName,
|
|
109
|
+
data: mergeChartPoints(
|
|
110
|
+
localSeriesByName.get(seriesName)?.data ?? [],
|
|
111
|
+
[{
|
|
112
|
+
x: timestampArg,
|
|
113
|
+
y: seriesName === 'Total Active'
|
|
114
|
+
? getProtocolConnectionTotal(protocolsArg)
|
|
115
|
+
: (protocolsArg[seriesName] ?? 0),
|
|
116
|
+
}],
|
|
117
|
+
maximumPointsArg,
|
|
118
|
+
),
|
|
119
|
+
}));
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
export const shouldRestartNetworkActivityTimer = (
|
|
123
|
+
isConnectedArg: boolean,
|
|
124
|
+
documentHiddenArg: boolean,
|
|
125
|
+
): boolean => isConnectedArg && !documentHiddenArg;
|
|
126
|
+
|
|
@@ -4,6 +4,25 @@ import * as interfaces from '../../../dist_ts_interfaces/index.js';
|
|
|
4
4
|
import { viewHostCss } from '../shared/css.js';
|
|
5
5
|
import { type IStatsTile } from '@design.estate/dees-catalog';
|
|
6
6
|
|
|
7
|
+
import {
|
|
8
|
+
appendProtocolConnectionSample,
|
|
9
|
+
createProtocolConnectionSeries,
|
|
10
|
+
getLatestHistoryEpochSecond,
|
|
11
|
+
mergeChartPoints,
|
|
12
|
+
mergeProtocolConnectionHistory,
|
|
13
|
+
shouldRestartNetworkActivityTimer,
|
|
14
|
+
type IChartPoint,
|
|
15
|
+
type TProtocolChartSeries,
|
|
16
|
+
} from './network-activity-history.js';
|
|
17
|
+
|
|
18
|
+
const PROTOCOL_COLORS: Record<string, string> = {
|
|
19
|
+
'HTTP/1.1': '#1976d2',
|
|
20
|
+
'HTTP/2': '#388e3c',
|
|
21
|
+
'HTTP/3': '#7b1fa2',
|
|
22
|
+
'WebSocket': '#f57c00',
|
|
23
|
+
'Other': '#757575',
|
|
24
|
+
};
|
|
25
|
+
|
|
7
26
|
declare global {
|
|
8
27
|
interface HTMLElementTagNameMap {
|
|
9
28
|
'ops-view-network-activity': OpsViewNetworkActivity;
|
|
@@ -12,8 +31,8 @@ declare global {
|
|
|
12
31
|
|
|
13
32
|
@customElement('ops-view-network-activity')
|
|
14
33
|
export class OpsViewNetworkActivity extends DeesElement {
|
|
15
|
-
/** How far back the
|
|
16
|
-
private static readonly CHART_WINDOW_MS =
|
|
34
|
+
/** How far back the realtime charts show */
|
|
35
|
+
private static readonly CHART_WINDOW_MS = 10 * 60 * 1000; // 10 minutes
|
|
17
36
|
/** How often a new data point is added */
|
|
18
37
|
private static readonly UPDATE_INTERVAL_MS = 1000; // 1 second
|
|
19
38
|
/** Derived: max data points the buffer holds */
|
|
@@ -27,10 +46,16 @@ export class OpsViewNetworkActivity extends DeesElement {
|
|
|
27
46
|
|
|
28
47
|
|
|
29
48
|
@state()
|
|
30
|
-
accessor trafficDataIn:
|
|
49
|
+
accessor trafficDataIn: IChartPoint[] = [];
|
|
50
|
+
|
|
51
|
+
@state()
|
|
52
|
+
accessor trafficDataOut: IChartPoint[] = [];
|
|
53
|
+
|
|
54
|
+
@state()
|
|
55
|
+
accessor frontendConnectionSeries: TProtocolChartSeries = createProtocolConnectionSeries();
|
|
31
56
|
|
|
32
57
|
@state()
|
|
33
|
-
accessor
|
|
58
|
+
accessor backendConnectionSeries: TProtocolChartSeries = createProtocolConnectionSeries();
|
|
34
59
|
|
|
35
60
|
// Track if we need to update the chart to avoid unnecessary re-renders
|
|
36
61
|
private lastChartUpdate = 0;
|
|
@@ -38,8 +63,10 @@ export class OpsViewNetworkActivity extends DeesElement {
|
|
|
38
63
|
|
|
39
64
|
private trafficUpdateTimer: any = null;
|
|
40
65
|
private requestsPerSecHistory: number[] = []; // Track requests/sec over time for trend
|
|
41
|
-
private historyLoaded = false; // Whether server-side throughput history has been loaded
|
|
42
66
|
private visibilityHandler: (() => void) | null = null;
|
|
67
|
+
private lastThroughputHistoryEpochSecond = 0;
|
|
68
|
+
private lastFrontendHistoryEpochSecond = 0;
|
|
69
|
+
private lastBackendHistoryEpochSecond = 0;
|
|
43
70
|
|
|
44
71
|
constructor() {
|
|
45
72
|
super();
|
|
@@ -57,7 +84,16 @@ export class OpsViewNetworkActivity extends DeesElement {
|
|
|
57
84
|
if (document.hidden) {
|
|
58
85
|
this.stopTrafficUpdateTimer();
|
|
59
86
|
} else {
|
|
60
|
-
|
|
87
|
+
void appstate.networkStatePart
|
|
88
|
+
.dispatchAction(appstate.fetchNetworkStatsAction, null)
|
|
89
|
+
.catch((error) => {
|
|
90
|
+
console.error('Failed to refresh network history after visibility resume:', error);
|
|
91
|
+
})
|
|
92
|
+
.finally(() => {
|
|
93
|
+
if (shouldRestartNetworkActivityTimer(this.isConnected, document.hidden)) {
|
|
94
|
+
this.startTrafficUpdateTimer();
|
|
95
|
+
}
|
|
96
|
+
});
|
|
61
97
|
}
|
|
62
98
|
};
|
|
63
99
|
document.addEventListener('visibilitychange', this.visibilityHandler);
|
|
@@ -106,51 +142,92 @@ export class OpsViewNetworkActivity extends DeesElement {
|
|
|
106
142
|
this.trafficDataOut = emptyData.map(point => ({ ...point }));
|
|
107
143
|
}
|
|
108
144
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
if (!history || history.length === 0) return;
|
|
118
|
-
|
|
119
|
-
this.historyLoaded = true;
|
|
120
|
-
|
|
121
|
-
// Convert history points to chart data format (bytes/sec → Mbit/s)
|
|
122
|
-
const historyIn = history.map(p => ({
|
|
123
|
-
x: new Date(p.timestamp).toISOString(),
|
|
124
|
-
y: Math.round((p.in * 8) / 1000000 * 10) / 10,
|
|
145
|
+
private mergeThroughputHistory(): void {
|
|
146
|
+
const history = this.networkState.throughputHistory || [];
|
|
147
|
+
const latestHistoryEpochSecond = getLatestHistoryEpochSecond(history);
|
|
148
|
+
if (latestHistoryEpochSecond <= this.lastThroughputHistoryEpochSecond) return;
|
|
149
|
+
|
|
150
|
+
const canonicalIn = history.map((point) => ({
|
|
151
|
+
x: new Date(point.timestamp).toISOString(),
|
|
152
|
+
y: Math.round(((point.in * 8) / 1000000) * 10) / 10,
|
|
125
153
|
}));
|
|
126
|
-
const
|
|
127
|
-
x: new Date(
|
|
128
|
-
y: Math.round((
|
|
154
|
+
const canonicalOut = history.map((point) => ({
|
|
155
|
+
x: new Date(point.timestamp).toISOString(),
|
|
156
|
+
y: Math.round(((point.out * 8) / 1000000) * 10) / 10,
|
|
129
157
|
}));
|
|
130
158
|
|
|
131
|
-
|
|
159
|
+
this.trafficDataIn = mergeChartPoints(
|
|
160
|
+
this.trafficDataIn,
|
|
161
|
+
canonicalIn,
|
|
162
|
+
OpsViewNetworkActivity.MAX_DATA_POINTS,
|
|
163
|
+
);
|
|
164
|
+
this.trafficDataOut = mergeChartPoints(
|
|
165
|
+
this.trafficDataOut,
|
|
166
|
+
canonicalOut,
|
|
167
|
+
OpsViewNetworkActivity.MAX_DATA_POINTS,
|
|
168
|
+
);
|
|
169
|
+
this.lastThroughputHistoryEpochSecond = latestHistoryEpochSecond;
|
|
170
|
+
}
|
|
132
171
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
: now;
|
|
145
|
-
|
|
146
|
-
const padIn = Array.from({ length: padCount }, (_, i) => ({
|
|
147
|
-
x: new Date(firstTimestamp - ((padCount - i) * UPDATE_INTERVAL_MS)).toISOString(),
|
|
148
|
-
y: 0,
|
|
149
|
-
}));
|
|
150
|
-
const padOut = padIn.map(p => ({ ...p }));
|
|
172
|
+
private getProtocolCounts(
|
|
173
|
+
distributionArg: interfaces.data.IProtocolDistribution,
|
|
174
|
+
): Record<string, number> {
|
|
175
|
+
return {
|
|
176
|
+
'HTTP/1.1': distributionArg.h1Active,
|
|
177
|
+
'HTTP/2': distributionArg.h2Active,
|
|
178
|
+
'HTTP/3': distributionArg.h3Active,
|
|
179
|
+
'WebSocket': distributionArg.wsActive,
|
|
180
|
+
'Other': distributionArg.otherActive,
|
|
181
|
+
};
|
|
182
|
+
}
|
|
151
183
|
|
|
152
|
-
|
|
153
|
-
|
|
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
|
+
private mergeProtocolConnectionHistories(): void {
|
|
192
|
+
const frontendHistory = this.networkState.frontendConnectionHistory || [];
|
|
193
|
+
const latestFrontendEpochSecond = getLatestHistoryEpochSecond(frontendHistory);
|
|
194
|
+
if (latestFrontendEpochSecond > this.lastFrontendHistoryEpochSecond) {
|
|
195
|
+
this.frontendConnectionSeries = mergeProtocolConnectionHistory(
|
|
196
|
+
this.frontendConnectionSeries,
|
|
197
|
+
frontendHistory,
|
|
198
|
+
OpsViewNetworkActivity.MAX_DATA_POINTS,
|
|
199
|
+
);
|
|
200
|
+
this.lastFrontendHistoryEpochSecond = latestFrontendEpochSecond;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const backendHistory = this.networkState.backendConnectionHistory || [];
|
|
204
|
+
const latestBackendEpochSecond = getLatestHistoryEpochSecond(backendHistory);
|
|
205
|
+
if (latestBackendEpochSecond > this.lastBackendHistoryEpochSecond) {
|
|
206
|
+
this.backendConnectionSeries = mergeProtocolConnectionHistory(
|
|
207
|
+
this.backendConnectionSeries,
|
|
208
|
+
backendHistory,
|
|
209
|
+
OpsViewNetworkActivity.MAX_DATA_POINTS,
|
|
210
|
+
);
|
|
211
|
+
this.lastBackendHistoryEpochSecond = latestBackendEpochSecond;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
private addProtocolConnectionDataPoints(timestampArg: string): void {
|
|
216
|
+
if (this.networkState.frontendProtocols) {
|
|
217
|
+
this.frontendConnectionSeries = appendProtocolConnectionSample(
|
|
218
|
+
this.frontendConnectionSeries,
|
|
219
|
+
timestampArg,
|
|
220
|
+
this.getProtocolCounts(this.networkState.frontendProtocols),
|
|
221
|
+
OpsViewNetworkActivity.MAX_DATA_POINTS,
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
if (this.networkState.backendProtocols) {
|
|
225
|
+
this.backendConnectionSeries = appendProtocolConnectionSample(
|
|
226
|
+
this.backendConnectionSeries,
|
|
227
|
+
timestampArg,
|
|
228
|
+
this.getProtocolCounts(this.networkState.backendProtocols),
|
|
229
|
+
OpsViewNetworkActivity.MAX_DATA_POINTS,
|
|
230
|
+
);
|
|
154
231
|
}
|
|
155
232
|
}
|
|
156
233
|
|
|
@@ -268,9 +345,17 @@ export class OpsViewNetworkActivity extends DeesElement {
|
|
|
268
345
|
|
|
269
346
|
.protocolChartGrid {
|
|
270
347
|
display: grid;
|
|
271
|
-
grid-template-columns:
|
|
348
|
+
grid-template-columns: 1fr;
|
|
349
|
+
gap: 16px;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
.protocolChartColumn {
|
|
353
|
+
display: flex;
|
|
354
|
+
flex-direction: column;
|
|
272
355
|
gap: 16px;
|
|
356
|
+
min-width: 0;
|
|
273
357
|
}
|
|
358
|
+
|
|
274
359
|
`,
|
|
275
360
|
];
|
|
276
361
|
|
|
@@ -557,13 +642,7 @@ export class OpsViewNetworkActivity extends DeesElement {
|
|
|
557
642
|
const fp = this.networkState.frontendProtocols;
|
|
558
643
|
const bp = this.networkState.backendProtocols;
|
|
559
644
|
|
|
560
|
-
const protoColors
|
|
561
|
-
'HTTP/1.1': '#1976d2',
|
|
562
|
-
'HTTP/2': '#388e3c',
|
|
563
|
-
'HTTP/3': '#7b1fa2',
|
|
564
|
-
'WebSocket': '#f57c00',
|
|
565
|
-
'Other': '#757575',
|
|
566
|
-
};
|
|
645
|
+
const protoColors = PROTOCOL_COLORS;
|
|
567
646
|
|
|
568
647
|
const buildDonutData = (dist: interfaces.data.IProtocolDistribution | null) => {
|
|
569
648
|
if (!dist) return [];
|
|
@@ -581,22 +660,40 @@ export class OpsViewNetworkActivity extends DeesElement {
|
|
|
581
660
|
|
|
582
661
|
return html`
|
|
583
662
|
<div class="protocolChartGrid">
|
|
584
|
-
<
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
663
|
+
<div class="protocolChartColumn">
|
|
664
|
+
<dees-chart-donut
|
|
665
|
+
.label=${'Frontend Protocols'}
|
|
666
|
+
.data=${frontendData.length > 0 ? frontendData : [{ name: 'No Traffic', value: 1, color: '#757575' }]}
|
|
667
|
+
.showLegend=${true}
|
|
668
|
+
.showLabels=${true}
|
|
669
|
+
.innerRadiusPercent=${'55%'}
|
|
670
|
+
.valueFormatter=${(val: number) => `${val} active`}
|
|
671
|
+
></dees-chart-donut>
|
|
672
|
+
<dees-chart-area
|
|
673
|
+
.label=${'Frontend Active Connections'}
|
|
674
|
+
.series=${this.getProtocolSeriesWithColors(this.frontendConnectionSeries)}
|
|
675
|
+
.realtimeMode=${true}
|
|
676
|
+
.rollingWindow=${OpsViewNetworkActivity.CHART_WINDOW_MS}
|
|
677
|
+
.yAxisFormatter=${(val: number) => `${Math.round(val)} active`}
|
|
678
|
+
></dees-chart-area>
|
|
679
|
+
</div>
|
|
680
|
+
<div class="protocolChartColumn">
|
|
681
|
+
<dees-chart-donut
|
|
682
|
+
.label=${'Backend Protocols'}
|
|
683
|
+
.data=${backendData.length > 0 ? backendData : [{ name: 'No Traffic', value: 1, color: '#757575' }]}
|
|
684
|
+
.showLegend=${true}
|
|
685
|
+
.showLabels=${true}
|
|
686
|
+
.innerRadiusPercent=${'55%'}
|
|
687
|
+
.valueFormatter=${(val: number) => `${val} active`}
|
|
688
|
+
></dees-chart-donut>
|
|
689
|
+
<dees-chart-area
|
|
690
|
+
.label=${'Backend Active Connections'}
|
|
691
|
+
.series=${this.getProtocolSeriesWithColors(this.backendConnectionSeries)}
|
|
692
|
+
.realtimeMode=${true}
|
|
693
|
+
.rollingWindow=${OpsViewNetworkActivity.CHART_WINDOW_MS}
|
|
694
|
+
.yAxisFormatter=${(val: number) => `${Math.round(val)} active`}
|
|
695
|
+
></dees-chart-area>
|
|
696
|
+
</div>
|
|
600
697
|
</div>
|
|
601
698
|
`;
|
|
602
699
|
}
|
|
@@ -962,10 +1059,8 @@ export class OpsViewNetworkActivity extends DeesElement {
|
|
|
962
1059
|
this.requestsPerSecHistory.shift();
|
|
963
1060
|
}
|
|
964
1061
|
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
this.loadThroughputHistory();
|
|
968
|
-
}
|
|
1062
|
+
this.mergeThroughputHistory();
|
|
1063
|
+
this.mergeProtocolConnectionHistories();
|
|
969
1064
|
}
|
|
970
1065
|
|
|
971
1066
|
private startTrafficUpdateTimer() {
|
|
@@ -1005,13 +1100,17 @@ export class OpsViewNetworkActivity extends DeesElement {
|
|
|
1005
1100
|
y: Math.round(throughputOutMbps * 10) / 10
|
|
1006
1101
|
};
|
|
1007
1102
|
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
this.
|
|
1014
|
-
|
|
1103
|
+
this.trafficDataIn = mergeChartPoints(
|
|
1104
|
+
this.trafficDataIn,
|
|
1105
|
+
[newDataPointIn],
|
|
1106
|
+
OpsViewNetworkActivity.MAX_DATA_POINTS,
|
|
1107
|
+
);
|
|
1108
|
+
this.trafficDataOut = mergeChartPoints(
|
|
1109
|
+
this.trafficDataOut,
|
|
1110
|
+
[newDataPointOut],
|
|
1111
|
+
OpsViewNetworkActivity.MAX_DATA_POINTS,
|
|
1112
|
+
);
|
|
1113
|
+
this.addProtocolConnectionDataPoints(timestamp);
|
|
1015
1114
|
|
|
1016
1115
|
this.lastChartUpdate = now;
|
|
1017
1116
|
}
|