Skip to content

Commit 082de9e

Browse files
committed
Use React hook to deal with websocket
1 parent 6cfb6ff commit 082de9e

File tree

3 files changed

+91
-121
lines changed

3 files changed

+91
-121
lines changed

web-app/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"react-pdf": "7.7.1",
2323
"react-redux": "^8.1.3",
2424
"react-router-dom": "6.22.3",
25+
"react-use-websocket": "^4.8.1",
2526
"react-virtualized": "^9.22.5",
2627
"react-window": "^1.8.10",
2728
"react-window-infinite-loader": "^1.0.9",

web-app/src/screens/Console/Trace/Trace.tsx

Lines changed: 82 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
// You should have received a copy of the GNU Affero General Public License
1515
// along with this program. If not, see <http://www.gnu.org/licenses/>.
1616

17-
import React, { Fragment, useEffect, useState } from "react";
17+
import { Fragment, useEffect, useState } from "react";
1818
import { DateTime } from "luxon";
1919
import { useSelector } from "react-redux";
2020
import {
@@ -41,8 +41,7 @@ import { setHelpName } from "../../../systemSlice";
4141
import TooltipWrapper from "../Common/TooltipWrapper/TooltipWrapper";
4242
import PageHeaderWrapper from "../Common/PageHeaderWrapper/PageHeaderWrapper";
4343
import HelpMenu from "../HelpMenu";
44-
45-
var socket: any = null;
44+
import useWebSocket, { ReadyState } from "react-use-websocket";
4645

4746
const Trace = () => {
4847
const dispatch = useAppDispatch();
@@ -65,68 +64,82 @@ const Trace = () => {
6564
const [errors, setErrors] = useState<boolean>(false);
6665

6766
const [toggleFilter, setToggleFilter] = useState<boolean>(false);
67+
const [logActive, setLogActive] = useState(false);
68+
const [wsUrl, setWsUrl] = useState<string>("");
6869

69-
const startTrace = () => {
70-
dispatch(traceResetMessages());
70+
useEffect(() => {
7171
const url = new URL(window.location.toString());
72-
const isDev = process.env.NODE_ENV === "development";
73-
const port = isDev ? "9090" : url.port;
74-
75-
let calls = `${s3 ? "s3," : ""}${internal ? "internal," : ""}${
76-
storage ? "storage," : ""
77-
}${os ? "os," : ""}`;
72+
const wsProt = wsProtocol(url.protocol);
73+
const port = process.env.NODE_ENV === "development" ? "9090" : url.port;
74+
const calls = all
75+
? "all"
76+
: (() => {
77+
const c = [];
78+
if (s3) c.push("s3");
79+
if (internal) c.push("internal");
80+
if (storage) c.push("storage");
81+
if (os) c.push("os");
82+
return c.join(",");
83+
})();
7884

79-
if (all) {
80-
calls = "all";
81-
}
8285
// check if we are using base path, if not this always is `/`
83-
const baseLocation = new URL(document.baseURI);
84-
const baseUrl = baseLocation.pathname;
86+
const baseLocation = new URL(document.baseURI).pathname;
8587

86-
const wsProt = wsProtocol(url.protocol);
87-
socket = new WebSocket(
88-
`${wsProt}://${
89-
url.hostname
90-
}:${port}${baseUrl}ws/trace?calls=${calls}&threshold=${threshold}&onlyErrors=${
91-
errors ? "yes" : "no"
92-
}&statusCode=${statusCode}&method=${method}&funcname=${func}&path=${path}`,
88+
const wsUrl = new URL(
89+
`${wsProt}://${url.hostname}:${port}${baseLocation}ws/trace`,
9390
);
91+
wsUrl.searchParams.append("calls", calls);
92+
wsUrl.searchParams.append("threshold", threshold.toString());
93+
wsUrl.searchParams.append("onlyErrors", errors ? "yes" : "no");
94+
wsUrl.searchParams.append("statusCode", statusCode);
95+
wsUrl.searchParams.append("method", method);
96+
wsUrl.searchParams.append("funcname", func);
97+
wsUrl.searchParams.append("path", path);
98+
setWsUrl(wsUrl.href);
99+
}, [
100+
all,
101+
s3,
102+
internal,
103+
storage,
104+
os,
105+
threshold,
106+
errors,
107+
statusCode,
108+
method,
109+
func,
110+
path,
111+
]);
94112

95-
let interval: any | null = null;
96-
if (socket !== null) {
97-
socket.onopen = () => {
98-
console.log("WebSocket Client Connected");
99-
dispatch(setTraceStarted(true));
100-
socket.send("ok");
101-
interval = setInterval(() => {
102-
socket.send("ok");
103-
}, 10 * 1000);
104-
};
105-
socket.onmessage = (message: MessageEvent) => {
106-
let m: TraceMessage = JSON.parse(message.data.toString());
113+
const { sendMessage, lastJsonMessage, readyState } =
114+
useWebSocket<TraceMessage>(
115+
wsUrl,
116+
{
117+
heartbeat: {
118+
message: "ok",
119+
interval: 10 * 1000, // send ok every 10 seconds
120+
timeout: 365 * 24 * 60 * 60 * 1000, // disconnect after 365 days (workaround, because heartbeat gets no response)
121+
},
122+
},
123+
logActive,
124+
);
107125

108-
m.ptime = DateTime.fromISO(m.time).toJSDate();
109-
m.key = Math.random();
110-
dispatch(traceMessageReceived(m));
111-
};
112-
socket.onclose = () => {
113-
clearInterval(interval);
114-
console.log("connection closed by server");
115-
dispatch(setTraceStarted(false));
116-
};
117-
return () => {
118-
socket.close(1000);
119-
clearInterval(interval);
120-
console.log("closing websockets");
121-
setTraceStarted(false);
122-
};
126+
useEffect(() => {
127+
if (readyState === ReadyState.CONNECTING) {
128+
dispatch(traceResetMessages());
129+
} else if (readyState === ReadyState.OPEN) {
130+
dispatch(setTraceStarted(true));
131+
} else if (readyState === ReadyState.CLOSED) {
132+
dispatch(setTraceStarted(false));
123133
}
124-
};
134+
}, [readyState, dispatch, sendMessage]);
125135

126-
const stopTrace = () => {
127-
socket.close(1000);
128-
dispatch(setTraceStarted(false));
129-
};
136+
useEffect(() => {
137+
if (lastJsonMessage) {
138+
lastJsonMessage.ptime = DateTime.fromISO(lastJsonMessage.time).toJSDate();
139+
lastJsonMessage.key = Math.random();
140+
dispatch(traceMessageReceived(lastJsonMessage));
141+
}
142+
}, [lastJsonMessage, dispatch]);
130143

131144
useEffect(() => {
132145
dispatch(setHelpName("trace"));
@@ -187,9 +200,7 @@ const Trace = () => {
187200
id={"all_calls"}
188201
name={"all_calls"}
189202
label={"All"}
190-
onChange={() => {
191-
setAll(!all);
192-
}}
203+
onChange={() => setAll(!all)}
193204
value={"all"}
194205
disabled={traceStarted}
195206
/>
@@ -198,9 +209,7 @@ const Trace = () => {
198209
id={"s3_calls"}
199210
name={"s3_calls"}
200211
label={"S3"}
201-
onChange={() => {
202-
setS3(!s3);
203-
}}
212+
onChange={() => setS3(!s3)}
204213
value={"s3"}
205214
disabled={all || traceStarted}
206215
/>
@@ -209,9 +218,7 @@ const Trace = () => {
209218
id={"internal_calls"}
210219
name={"internal_calls"}
211220
label={"Internal"}
212-
onChange={() => {
213-
setInternal(!internal);
214-
}}
221+
onChange={() => setInternal(!internal)}
215222
value={"internal"}
216223
disabled={all || traceStarted}
217224
/>
@@ -220,9 +227,7 @@ const Trace = () => {
220227
id={"storage_calls"}
221228
name={"storage_calls"}
222229
label={"Storage"}
223-
onChange={() => {
224-
setStorage(!storage);
225-
}}
230+
onChange={() => setStorage(!storage)}
226231
value={"storage"}
227232
disabled={all || traceStarted}
228233
/>
@@ -231,9 +236,7 @@ const Trace = () => {
231236
id={"os_calls"}
232237
name={"os_calls"}
233238
label={"OS"}
234-
onChange={() => {
235-
setOS(!os);
236-
}}
239+
onChange={() => setOS(!os)}
237240
value={"os"}
238241
disabled={all || traceStarted}
239242
/>
@@ -249,9 +252,7 @@ const Trace = () => {
249252
<TooltipWrapper tooltip={"More filter options"}>
250253
<Button
251254
id={"filter-toggle"}
252-
onClick={() => {
253-
setToggleFilter(!toggleFilter);
254-
}}
255+
onClick={() => setToggleFilter(!toggleFilter)}
255256
label={"Filters"}
256257
icon={<FilterIcon />}
257258
variant={"regular"}
@@ -269,7 +270,7 @@ const Trace = () => {
269270
label={"Start"}
270271
data-test-id={"trace-start-button"}
271272
variant="callAction"
272-
onClick={startTrace}
273+
onClick={() => setLogActive(true)}
273274
style={{
274275
width: "118px",
275276
}}
@@ -281,7 +282,7 @@ const Trace = () => {
281282
label={"Stop Trace"}
282283
data-test-id={"trace-stop-button"}
283284
variant="callAction"
284-
onClick={stopTrace}
285+
onClick={() => setLogActive(false)}
285286
style={{
286287
width: "118px",
287288
}}
@@ -330,9 +331,7 @@ const Trace = () => {
330331
label="Status Code"
331332
placeholder="e.g. 503"
332333
value={statusCode}
333-
onChange={(e) => {
334-
setStatusCode(e.target.value);
335-
}}
334+
onChange={(e) => setStatusCode(e.target.value)}
336335
disabled={traceStarted}
337336
/>
338337

@@ -343,9 +342,7 @@ const Trace = () => {
343342
label="Function Name"
344343
placeholder="e.g. FunctionName2055"
345344
value={func}
346-
onChange={(e) => {
347-
setFunc(e.target.value);
348-
}}
345+
onChange={(e) => setFunc(e.target.value)}
349346
disabled={traceStarted}
350347
/>
351348

@@ -356,9 +353,7 @@ const Trace = () => {
356353
label="Method"
357354
placeholder="e.g. Method 2056"
358355
value={method}
359-
onChange={(e) => {
360-
setMethod(e.target.value);
361-
}}
356+
onChange={(e) => setMethod(e.target.value)}
362357
disabled={traceStarted}
363358
/>
364359
</Box>
@@ -384,9 +379,7 @@ const Trace = () => {
384379
label="Path"
385380
placeholder="e.g. my-bucket/my-prefix/*"
386381
value={path}
387-
onChange={(e) => {
388-
setPath(e.target.value);
389-
}}
382+
onChange={(e) => setPath(e.target.value)}
390383
disabled={traceStarted}
391384
/>
392385
</Box>
@@ -403,9 +396,7 @@ const Trace = () => {
403396
type="number"
404397
placeholder="e.g. website.io.3249.114.12"
405398
value={`${threshold}`}
406-
onChange={(e) => {
407-
setThreshold(parseInt(e.target.value));
408-
}}
399+
onChange={(e) => setThreshold(parseInt(e.target.value))}
409400
disabled={traceStarted}
410401
/>
411402
</Box>
@@ -423,9 +414,7 @@ const Trace = () => {
423414
id={"only_errors"}
424415
name={"only_errors"}
425416
label={"Display only Errors"}
426-
onChange={() => {
427-
setErrors(!errors);
428-
}}
417+
onChange={() => setErrors(!errors)}
429418
value={"only_errors"}
430419
disabled={traceStarted}
431420
/>

web-app/yarn.lock

Lines changed: 8 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -10429,6 +10429,11 @@ react-transition-group@^4.4.5:
1042910429
loose-envify "^1.4.0"
1043010430
prop-types "^15.6.2"
1043110431

10432+
react-use-websocket@^4.8.1:
10433+
version "4.8.1"
10434+
resolved "https://registry.yarnpkg.com/react-use-websocket/-/react-use-websocket-4.8.1.tgz#be06a0bc956c6d56391a29cbe2caa6ae8edb5615"
10435+
integrity sha512-FTXuG5O+LFozmu1BRfrzl7UIQngECvGJmL7BHsK4TYXuVt+mCizVA8lT0hGSIF0Z0TedF7bOo1nRzOUdginhDw==
10436+
1043210437
react-virtual@^2.8.2:
1043310438
version "2.10.4"
1043410439
resolved "https://registry.yarnpkg.com/react-virtual/-/react-virtual-2.10.4.tgz#08712f0acd79d7d6f7c4726f05651a13b24d8704"
@@ -11399,16 +11404,7 @@ string-natural-compare@^3.0.1:
1139911404
resolved "https://registry.yarnpkg.com/string-natural-compare/-/string-natural-compare-3.0.1.tgz#7a42d58474454963759e8e8b7ae63d71c1e7fdf4"
1140011405
integrity sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw==
1140111406

11402-
"string-width-cjs@npm:string-width@^4.2.0":
11403-
version "4.2.3"
11404-
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
11405-
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
11406-
dependencies:
11407-
emoji-regex "^8.0.0"
11408-
is-fullwidth-code-point "^3.0.0"
11409-
strip-ansi "^6.0.1"
11410-
11411-
"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
11407+
"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
1141211408
version "4.2.3"
1141311409
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
1141411410
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@@ -11503,14 +11499,7 @@ stringify-object@^3.3.0:
1150311499
is-obj "^1.0.1"
1150411500
is-regexp "^1.0.0"
1150511501

11506-
"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
11507-
version "6.0.1"
11508-
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
11509-
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
11510-
dependencies:
11511-
ansi-regex "^5.0.1"
11512-
11513-
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
11502+
"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
1151411503
version "6.0.1"
1151511504
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
1151611505
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
@@ -13260,7 +13249,7 @@ workbox-window@6.6.1:
1326013249
"@types/trusted-types" "^2.0.2"
1326113250
workbox-core "6.6.1"
1326213251

13263-
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
13252+
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
1326413253
version "7.0.0"
1326513254
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
1326613255
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
@@ -13278,15 +13267,6 @@ wrap-ansi@^6.2.0:
1327813267
string-width "^4.1.0"
1327913268
strip-ansi "^6.0.0"
1328013269

13281-
wrap-ansi@^7.0.0:
13282-
version "7.0.0"
13283-
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
13284-
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
13285-
dependencies:
13286-
ansi-styles "^4.0.0"
13287-
string-width "^4.1.0"
13288-
strip-ansi "^6.0.0"
13289-
1329013270
wrap-ansi@^8.1.0:
1329113271
version "8.1.0"
1329213272
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"

0 commit comments

Comments
 (0)