mirror of
https://github.com/kubeshark/kubeshark.git
synced 2025-07-07 05:19:15 +00:00
Merge branch 'develop' into refactor_ws
This commit is contained in:
commit
5ba7423b53
2
.github/workflows/acceptance_tests.yml
vendored
2
.github/workflows/acceptance_tests.yml
vendored
@ -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:
|
||||||
|
@ -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)
|
||||||
|
@ -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 {
|
||||||
|
@ -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,
|
||||||
|
@ -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}>
|
||||||
|
@ -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}
|
||||||
|
@ -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",
|
||||||
|
Loading…
Reference in New Issue
Block a user