Merge branch 'develop' into refactor_ws

This commit is contained in:
Rami Berman 2022-04-04 14:18:31 +03:00
commit 5ba7423b53
7 changed files with 73 additions and 58 deletions

View File

@ -43,7 +43,7 @@ jobs:
with: with:
status: ${{ job.status }} status: ${{ job.status }}
notification_title: 'Mizu {workflow} has {status_message}' notification_title: 'Mizu {workflow} has {status_message}'
message_format: '{emoji} *{workflow}* {status_message} during <{run_url}|run>, after commit <{commit_url}|{commit_sha} ${{ github.event.head_commit.message }}> ${{ github.event.head_commit.committer.name }} <${{ github.event.head_commit.committer.email }}>' message_format: '{emoji} *{workflow}* {status_message} during <{run_url}|run>, after commit <{commit_url}|{commit_sha}> by ${{ github.event.head_commit.committer.name }} <${{ github.event.head_commit.committer.email }}> ```${{ github.event.head_commit.message }}```'
footer: 'Linked Repo <{repo_url}|{repo}>' footer: 'Linked Repo <{repo_url}|{repo}>'
notify_when: 'failure' notify_when: 'failure'
env: env:

View File

@ -104,12 +104,14 @@ func (s *ServiceMapControllerSuite) TestGet() {
Id: 1, Id: 1,
Name: TCPEntryA.Name, Name: TCPEntryA.Name,
Entry: TCPEntryA, Entry: TCPEntryA,
Resolved: true,
Count: 1, Count: 1,
} }
bNode := servicemap.ServiceMapNode{ bNode := servicemap.ServiceMapNode{
Id: 2, Id: 2,
Name: TCPEntryB.Name, Name: TCPEntryB.Name,
Entry: TCPEntryB, Entry: TCPEntryB,
Resolved: true,
Count: 1, Count: 1,
} }
assert.Contains(response.Nodes, aNode) assert.Contains(response.Nodes, aNode)

View File

@ -22,6 +22,7 @@ type ServiceMapNode struct {
Name string `json:"name"` Name string `json:"name"`
Entry *tapApi.TCP `json:"entry"` Entry *tapApi.TCP `json:"entry"`
Count int `json:"count"` Count int `json:"count"`
Resolved bool `json:"resolved"`
} }
type ServiceMapEdge struct { type ServiceMapEdge struct {

View File

@ -229,6 +229,7 @@ func (s *defaultServiceMap) GetNodes() []ServiceMapNode {
nodes = append(nodes, ServiceMapNode{ nodes = append(nodes, ServiceMapNode{
Id: n.id, Id: n.id,
Name: string(i), Name: string(i),
Resolved: n.entry.Name != UnresolvedNodeName,
Entry: n.entry, Entry: n.entry,
Count: n.count, Count: n.count,
}) })
@ -246,12 +247,14 @@ func (s *defaultServiceMap) GetEdges() []ServiceMapEdge {
Id: s.graph.Nodes[u].id, Id: s.graph.Nodes[u].id,
Name: string(u), Name: string(u),
Entry: s.graph.Nodes[u].entry, Entry: s.graph.Nodes[u].entry,
Resolved: s.graph.Nodes[u].entry.Name != UnresolvedNodeName,
Count: s.graph.Nodes[u].count, Count: s.graph.Nodes[u].count,
}, },
Destination: ServiceMapNode{ Destination: ServiceMapNode{
Id: s.graph.Nodes[v].id, Id: s.graph.Nodes[v].id,
Name: string(v), Name: string(v),
Entry: s.graph.Nodes[v].entry, Entry: s.graph.Nodes[v].entry,
Resolved: s.graph.Nodes[v].entry.Name != UnresolvedNodeName,
Count: s.graph.Nodes[v].count, Count: s.graph.Nodes[v].count,
}, },
Count: p.count, Count: p.count,

View File

@ -10,6 +10,7 @@ import entriesAtom from "../../recoil/entries";
import queryAtom from "../../recoil/query"; import queryAtom from "../../recoil/query";
import TrafficViewerApiAtom from "../../recoil/TrafficViewerApi"; import TrafficViewerApiAtom from "../../recoil/TrafficViewerApi";
import TrafficViewerApi from "./TrafficViewerApi"; import TrafficViewerApi from "./TrafficViewerApi";
import focusedEntryIdAtom from "../../recoil/focusedEntryId";
interface EntriesListProps { interface EntriesListProps {
listEntryREF: any; listEntryREF: any;
@ -18,8 +19,6 @@ interface EntriesListProps {
setIsSnappedToBottom: any; setIsSnappedToBottom: any;
queriedCurrent: number; queriedCurrent: number;
setQueriedCurrent: any; setQueriedCurrent: any;
queriedTotal: number;
setQueriedTotal: any;
startTime: number; startTime: number;
noMoreDataTop: boolean; noMoreDataTop: boolean;
setNoMoreDataTop: (flag: boolean) => void; setNoMoreDataTop: (flag: boolean) => void;
@ -33,16 +32,18 @@ interface EntriesListProps {
ws: any; ws: any;
} }
export const EntriesList: React.FC<EntriesListProps> = ({listEntryREF, onSnapBrokenEvent, isSnappedToBottom, setIsSnappedToBottom, queriedCurrent, setQueriedCurrent, queriedTotal, setQueriedTotal, startTime, noMoreDataTop, setNoMoreDataTop, leftOffTop, setLeftOffTop, openWebSocket, leftOffBottom, truncatedTimestamp, setTruncatedTimestamp, scrollableRef, ws}) => { export const EntriesList: React.FC<EntriesListProps> = ({listEntryREF, onSnapBrokenEvent, isSnappedToBottom, setIsSnappedToBottom, queriedCurrent, setQueriedCurrent, startTime, noMoreDataTop, setNoMoreDataTop, leftOffTop, setLeftOffTop, openWebSocket, leftOffBottom, truncatedTimestamp, setTruncatedTimestamp, scrollableRef, ws}) => {
const [entries, setEntries] = useRecoilState(entriesAtom); const [entries, setEntries] = useRecoilState(entriesAtom);
const query = useRecoilValue(queryAtom); const query = useRecoilValue(queryAtom);
const isWsConnectionClosed = ws?.current?.readyState !== WebSocket.OPEN; const isWsConnectionClosed = ws?.current?.readyState !== WebSocket.OPEN;
const [focusedEntryId, setFocusedEntryId] = useRecoilState(focusedEntryIdAtom);
const trafficViewerApi = useRecoilValue(TrafficViewerApiAtom as RecoilState<TrafficViewerApi>) const trafficViewerApi = useRecoilValue(TrafficViewerApiAtom as RecoilState<TrafficViewerApi>)
const [loadMoreTop, setLoadMoreTop] = useState(false); const [loadMoreTop, setLoadMoreTop] = useState(false);
const [isLoadingTop, setIsLoadingTop] = useState(false); const [isLoadingTop, setIsLoadingTop] = useState(false);
const [queriedTotal, setQueriedTotal] = useState(0);
useEffect(() => { useEffect(() => {
const list = document.getElementById('list').firstElementChild; const list = document.getElementById('list').firstElementChild;
@ -103,6 +104,29 @@ export const EntriesList: React.FC<EntriesListProps> = ({listEntryREF, onSnapBro
const scrollbarVisible = scrollableRef.current?.childWrapperRef.current.clientHeight > scrollableRef.current?.wrapperRef.current.clientHeight; const scrollbarVisible = scrollableRef.current?.childWrapperRef.current.clientHeight > scrollableRef.current?.wrapperRef.current.clientHeight;
if (ws.current) {
ws.current.addEventListener("message", (e) => {
if (!e?.data) return;
const message = JSON.parse(e.data);
switch (message.messageType) {
case "entry":
const entry = message.data;
if (!focusedEntryId) setFocusedEntryId(entry.id.toString());
const newEntries = [...entries, entry];
if (newEntries.length === 10001) {
setLeftOffTop(newEntries[0].entry.id);
newEntries.shift();
setNoMoreDataTop(false);
}
setEntries(newEntries);
break;
case "queryMetadata":
setQueriedTotal(message.data.total);
break;
};
});
}
return <React.Fragment> return <React.Fragment>
<div className={styles.list}> <div className={styles.list}>
<div id="list" ref={listEntryREF} className={styles.list}> <div id="list" ref={listEntryREF} className={styles.list}>

View File

@ -58,19 +58,18 @@ export const TrafficViewer: React.FC<TrafficViewerProps> = ({ setAnalyzeStatus,
const classes = useLayoutStyles(); const classes = useLayoutStyles();
const [entries, setEntries] = useRecoilState(entriesAtom); const setEntries = useSetRecoilState(entriesAtom);
const [focusedEntryId, setFocusedEntryId] = useRecoilState(focusedEntryIdAtom); const [focusedEntryId, setFocusedEntryId] = useRecoilState(focusedEntryIdAtom);
const query = useRecoilValue(queryAtom); const query = useRecoilValue(queryAtom);
const setTrafficViewerApiState = useSetRecoilState(trafficViewerApiAtom as RecoilState<TrafficViewerApi>) const setTrafficViewerApiState = useSetRecoilState(trafficViewerApiAtom as RecoilState<TrafficViewerApi>)
const [tappingStatus, setTappingStatus] = useRecoilState(tappingStatusAtom); const [tappingStatus, setTappingStatus] = useRecoilState(tappingStatusAtom);
const [noMoreDataTop, setNoMoreDataTop] = useState(false); const [noMoreDataTop, setNoMoreDataTop] = useState(false);
const [isSnappedToBottom, setIsSnappedToBottom] = useState(true); const [isSnappedToBottom, setIsSnappedToBottom] = useState(true);
const [forceRender, setForceRender] = useState(0); const [wsReadyState, setWsReadyState] = useState(0);
const [queryBackgroundColor, setQueryBackgroundColor] = useState("#f5f5f5"); const [queryBackgroundColor, setQueryBackgroundColor] = useState("#f5f5f5");
const [queriedCurrent, setQueriedCurrent] = useState(0); const [queriedCurrent, setQueriedCurrent] = useState(0);
const [queriedTotal, setQueriedTotal] = useState(0);
const [leftOffBottom, setLeftOffBottom] = useState(0); const [leftOffBottom, setLeftOffBottom] = useState(0);
const [leftOffTop, setLeftOffTop] = useState(null); const [leftOffTop, setLeftOffTop] = useState(null);
const [truncatedTimestamp, setTruncatedTimestamp] = useState(0); const [truncatedTimestamp, setTruncatedTimestamp] = useState(0);
@ -144,9 +143,12 @@ export const TrafficViewer: React.FC<TrafficViewerProps> = ({ setAnalyzeStatus,
ws.current = new WebSocket(webSocketUrl); ws.current = new WebSocket(webSocketUrl);
sendQueryWhenWsOpen(query); sendQueryWhenWsOpen(query);
ws.current.onopen = () => {
setWsReadyState(ws?.current?.readyState);
}
ws.current.onclose = () => { ws.current.onclose = () => {
if (window.location.pathname === "/") setWsReadyState(ws?.current?.readyState);
setForceRender(forceRender + 1);
} }
ws.current.onerror = (event) => { ws.current.onerror = (event) => {
console.error("WebSocket error:", event); console.error("WebSocket error:", event);
@ -173,21 +175,10 @@ export const TrafficViewer: React.FC<TrafficViewerProps> = ({ setAnalyzeStatus,
} }
if (ws.current) { if (ws.current) {
ws.current.onmessage = (e) => { ws.current.addEventListener("message", (e) => {
if (!e?.data) return; if (!e?.data) return;
const message = JSON.parse(e.data); const message = JSON.parse(e.data);
switch (message.messageType) { switch (message.messageType) {
case "entry":
const entry = message.data;
if (!focusedEntryId) setFocusedEntryId(entry.id.toString());
const newEntries = [...entries, entry];
if (newEntries.length === 10001) {
setLeftOffTop(newEntries[0].entry.id);
newEntries.shift();
setNoMoreDataTop(false);
}
setEntries(newEntries);
break;
case "status": case "status":
setTappingStatus(message.tappingStatus); setTappingStatus(message.tappingStatus);
break; break;
@ -208,7 +199,6 @@ export const TrafficViewer: React.FC<TrafficViewerProps> = ({ setAnalyzeStatus,
break; break;
case "queryMetadata": case "queryMetadata":
setQueriedCurrent(queriedCurrent + message.data.current); setQueriedCurrent(queriedCurrent + message.data.current);
setQueriedTotal(message.data.total);
setLeftOffBottom(message.data.leftOff); setLeftOffBottom(message.data.leftOff);
setTruncatedTimestamp(message.data.truncatedTimestamp); setTruncatedTimestamp(message.data.truncatedTimestamp);
if (leftOffTop === null) { if (leftOffTop === null) {
@ -218,12 +208,8 @@ export const TrafficViewer: React.FC<TrafficViewerProps> = ({ setAnalyzeStatus,
case "startTime": case "startTime":
setStartTime(message.data); setStartTime(message.data);
break; break;
default:
console.error(
`unsupported websocket message type, Got: ${message.messageType}`
);
} }
}; })
} }
useEffect(() => { useEffect(() => {
@ -272,7 +258,7 @@ export const TrafficViewer: React.FC<TrafficViewerProps> = ({ setAnalyzeStatus,
}; };
const getConnectionIndicator = () => { const getConnectionIndicator = () => {
switch (ws?.current?.readyState) { switch (wsReadyState) {
case WebSocket.OPEN: case WebSocket.OPEN:
return <div className={`${TrafficViewerStyles.indicatorContainer} ${TrafficViewerStyles.greenIndicatorContainer}`}> return <div className={`${TrafficViewerStyles.indicatorContainer} ${TrafficViewerStyles.greenIndicatorContainer}`}>
<div className={`${TrafficViewerStyles.indicator} ${TrafficViewerStyles.greenIndicator}`} /> <div className={`${TrafficViewerStyles.indicator} ${TrafficViewerStyles.greenIndicator}`} />
@ -285,7 +271,7 @@ export const TrafficViewer: React.FC<TrafficViewerProps> = ({ setAnalyzeStatus,
} }
const getConnectionTitle = () => { const getConnectionTitle = () => {
switch (ws?.current?.readyState) { switch (wsReadyState) {
case WebSocket.OPEN: case WebSocket.OPEN:
return "streaming live traffic" return "streaming live traffic"
default: default:
@ -305,9 +291,9 @@ export const TrafficViewer: React.FC<TrafficViewerProps> = ({ setAnalyzeStatus,
{tappingStatus && isShowStatusBar && <StatusBar isDemoBannerView={isDemoBannerView} />} {tappingStatus && isShowStatusBar && <StatusBar isDemoBannerView={isDemoBannerView} />}
<div className={TrafficViewerStyles.TrafficPageHeader}> <div className={TrafficViewerStyles.TrafficPageHeader}>
<div className={TrafficViewerStyles.TrafficPageStreamStatus}> <div className={TrafficViewerStyles.TrafficPageStreamStatus}>
<img className={TrafficViewerStyles.playPauseIcon} style={{ visibility: ws?.current?.readyState === WebSocket.OPEN ? "visible" : "hidden" }} alt="pause" <img className={TrafficViewerStyles.playPauseIcon} style={{ visibility: wsReadyState === WebSocket.OPEN ? "visible" : "hidden" }} alt="pause"
src={pauseIcon} onClick={toggleConnection} /> src={pauseIcon} onClick={toggleConnection} />
<img className={TrafficViewerStyles.playPauseIcon} style={{ position: "absolute", visibility: ws?.current?.readyState === WebSocket.OPEN ? "hidden" : "visible" }} alt="play" <img className={TrafficViewerStyles.playPauseIcon} style={{ position: "absolute", visibility: wsReadyState === WebSocket.OPEN ? "hidden" : "visible" }} alt="play"
src={playIcon} onClick={toggleConnection} /> src={playIcon} onClick={toggleConnection} />
<div className={TrafficViewerStyles.connectionText}> <div className={TrafficViewerStyles.connectionText}>
{getConnectionTitle()} {getConnectionTitle()}
@ -331,8 +317,6 @@ export const TrafficViewer: React.FC<TrafficViewerProps> = ({ setAnalyzeStatus,
setIsSnappedToBottom={setIsSnappedToBottom} setIsSnappedToBottom={setIsSnappedToBottom}
queriedCurrent={queriedCurrent} queriedCurrent={queriedCurrent}
setQueriedCurrent={setQueriedCurrent} setQueriedCurrent={setQueriedCurrent}
queriedTotal={queriedTotal}
setQueriedTotal={setQueriedTotal}
startTime={startTime} startTime={startTime}
noMoreDataTop={noMoreDataTop} noMoreDataTop={noMoreDataTop}
setNoMoreDataTop={setNoMoreDataTop} setNoMoreDataTop={setNoMoreDataTop}

View File

@ -48,7 +48,8 @@
"npm-link-shared": "^0.5.6", "npm-link-shared": "^0.5.6",
"react-app-rewire-alias": "^1.1.7", "react-app-rewire-alias": "^1.1.7",
"react-dev-utils": "^12.0.0", "react-dev-utils": "^12.0.0",
"recoil": "^0.5.2" "recoil": "^0.5.2",
"react-error-overlay": "6.0.9"
}, },
"scripts": { "scripts": {
"start": "craco start", "start": "craco start",