mirror of
https://github.com/kubeshark/kubeshark.git
synced 2025-07-05 20:38:50 +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:
|
||||
status: ${{ job.status }}
|
||||
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}>'
|
||||
notify_when: 'failure'
|
||||
env:
|
||||
|
@ -101,16 +101,18 @@ func (s *ServiceMapControllerSuite) TestGet() {
|
||||
|
||||
// response nodes
|
||||
aNode := servicemap.ServiceMapNode{
|
||||
Id: 1,
|
||||
Name: TCPEntryA.Name,
|
||||
Entry: TCPEntryA,
|
||||
Count: 1,
|
||||
Id: 1,
|
||||
Name: TCPEntryA.Name,
|
||||
Entry: TCPEntryA,
|
||||
Resolved: true,
|
||||
Count: 1,
|
||||
}
|
||||
bNode := servicemap.ServiceMapNode{
|
||||
Id: 2,
|
||||
Name: TCPEntryB.Name,
|
||||
Entry: TCPEntryB,
|
||||
Count: 1,
|
||||
Id: 2,
|
||||
Name: TCPEntryB.Name,
|
||||
Entry: TCPEntryB,
|
||||
Resolved: true,
|
||||
Count: 1,
|
||||
}
|
||||
assert.Contains(response.Nodes, aNode)
|
||||
assert.Contains(response.Nodes, bNode)
|
||||
|
@ -18,10 +18,11 @@ type ServiceMapResponse struct {
|
||||
}
|
||||
|
||||
type ServiceMapNode struct {
|
||||
Id int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Entry *tapApi.TCP `json:"entry"`
|
||||
Count int `json:"count"`
|
||||
Id int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Entry *tapApi.TCP `json:"entry"`
|
||||
Count int `json:"count"`
|
||||
Resolved bool `json:"resolved"`
|
||||
}
|
||||
|
||||
type ServiceMapEdge struct {
|
||||
|
@ -227,10 +227,11 @@ func (s *defaultServiceMap) GetNodes() []ServiceMapNode {
|
||||
var nodes []ServiceMapNode
|
||||
for i, n := range s.graph.Nodes {
|
||||
nodes = append(nodes, ServiceMapNode{
|
||||
Id: n.id,
|
||||
Name: string(i),
|
||||
Entry: n.entry,
|
||||
Count: n.count,
|
||||
Id: n.id,
|
||||
Name: string(i),
|
||||
Resolved: n.entry.Name != UnresolvedNodeName,
|
||||
Entry: n.entry,
|
||||
Count: n.count,
|
||||
})
|
||||
}
|
||||
return nodes
|
||||
@ -243,16 +244,18 @@ func (s *defaultServiceMap) GetEdges() []ServiceMapEdge {
|
||||
for _, p := range s.graph.Edges[u][v].data {
|
||||
edges = append(edges, ServiceMapEdge{
|
||||
Source: ServiceMapNode{
|
||||
Id: s.graph.Nodes[u].id,
|
||||
Name: string(u),
|
||||
Entry: s.graph.Nodes[u].entry,
|
||||
Count: s.graph.Nodes[u].count,
|
||||
Id: s.graph.Nodes[u].id,
|
||||
Name: string(u),
|
||||
Entry: s.graph.Nodes[u].entry,
|
||||
Resolved: s.graph.Nodes[u].entry.Name != UnresolvedNodeName,
|
||||
Count: s.graph.Nodes[u].count,
|
||||
},
|
||||
Destination: ServiceMapNode{
|
||||
Id: s.graph.Nodes[v].id,
|
||||
Name: string(v),
|
||||
Entry: s.graph.Nodes[v].entry,
|
||||
Count: s.graph.Nodes[v].count,
|
||||
Id: s.graph.Nodes[v].id,
|
||||
Name: string(v),
|
||||
Entry: s.graph.Nodes[v].entry,
|
||||
Resolved: s.graph.Nodes[v].entry.Name != UnresolvedNodeName,
|
||||
Count: s.graph.Nodes[v].count,
|
||||
},
|
||||
Count: p.count,
|
||||
Protocol: p.protocol,
|
||||
|
@ -10,6 +10,7 @@ import entriesAtom from "../../recoil/entries";
|
||||
import queryAtom from "../../recoil/query";
|
||||
import TrafficViewerApiAtom from "../../recoil/TrafficViewerApi";
|
||||
import TrafficViewerApi from "./TrafficViewerApi";
|
||||
import focusedEntryIdAtom from "../../recoil/focusedEntryId";
|
||||
|
||||
interface EntriesListProps {
|
||||
listEntryREF: any;
|
||||
@ -18,8 +19,6 @@ interface EntriesListProps {
|
||||
setIsSnappedToBottom: any;
|
||||
queriedCurrent: number;
|
||||
setQueriedCurrent: any;
|
||||
queriedTotal: number;
|
||||
setQueriedTotal: any;
|
||||
startTime: number;
|
||||
noMoreDataTop: boolean;
|
||||
setNoMoreDataTop: (flag: boolean) => void;
|
||||
@ -33,16 +32,18 @@ interface EntriesListProps {
|
||||
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 query = useRecoilValue(queryAtom);
|
||||
const isWsConnectionClosed = ws?.current?.readyState !== WebSocket.OPEN;
|
||||
const [focusedEntryId, setFocusedEntryId] = useRecoilState(focusedEntryIdAtom);
|
||||
|
||||
const trafficViewerApi = useRecoilValue(TrafficViewerApiAtom as RecoilState<TrafficViewerApi>)
|
||||
|
||||
const [loadMoreTop, setLoadMoreTop] = useState(false);
|
||||
const [isLoadingTop, setIsLoadingTop] = useState(false);
|
||||
const [queriedTotal, setQueriedTotal] = useState(0);
|
||||
|
||||
useEffect(() => {
|
||||
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;
|
||||
|
||||
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>
|
||||
<div 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 [entries, setEntries] = useRecoilState(entriesAtom);
|
||||
const setEntries = useSetRecoilState(entriesAtom);
|
||||
const [focusedEntryId, setFocusedEntryId] = useRecoilState(focusedEntryIdAtom);
|
||||
const query = useRecoilValue(queryAtom);
|
||||
const setTrafficViewerApiState = useSetRecoilState(trafficViewerApiAtom as RecoilState<TrafficViewerApi>)
|
||||
const [tappingStatus, setTappingStatus] = useRecoilState(tappingStatusAtom);
|
||||
const [noMoreDataTop, setNoMoreDataTop] = useState(false);
|
||||
const [isSnappedToBottom, setIsSnappedToBottom] = useState(true);
|
||||
const [forceRender, setForceRender] = useState(0);
|
||||
const [wsReadyState, setWsReadyState] = useState(0);
|
||||
|
||||
const [queryBackgroundColor, setQueryBackgroundColor] = useState("#f5f5f5");
|
||||
|
||||
const [queriedCurrent, setQueriedCurrent] = useState(0);
|
||||
const [queriedTotal, setQueriedTotal] = useState(0);
|
||||
const [leftOffBottom, setLeftOffBottom] = useState(0);
|
||||
const [leftOffTop, setLeftOffTop] = useState(null);
|
||||
const [truncatedTimestamp, setTruncatedTimestamp] = useState(0);
|
||||
@ -144,9 +143,12 @@ export const TrafficViewer: React.FC<TrafficViewerProps> = ({ setAnalyzeStatus,
|
||||
ws.current = new WebSocket(webSocketUrl);
|
||||
sendQueryWhenWsOpen(query);
|
||||
|
||||
ws.current.onopen = () => {
|
||||
setWsReadyState(ws?.current?.readyState);
|
||||
}
|
||||
|
||||
ws.current.onclose = () => {
|
||||
if (window.location.pathname === "/")
|
||||
setForceRender(forceRender + 1);
|
||||
setWsReadyState(ws?.current?.readyState);
|
||||
}
|
||||
ws.current.onerror = (event) => {
|
||||
console.error("WebSocket error:", event);
|
||||
@ -173,21 +175,10 @@ export const TrafficViewer: React.FC<TrafficViewerProps> = ({ setAnalyzeStatus,
|
||||
}
|
||||
|
||||
if (ws.current) {
|
||||
ws.current.onmessage = (e) => {
|
||||
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 "status":
|
||||
setTappingStatus(message.tappingStatus);
|
||||
break;
|
||||
@ -208,7 +199,6 @@ export const TrafficViewer: React.FC<TrafficViewerProps> = ({ setAnalyzeStatus,
|
||||
break;
|
||||
case "queryMetadata":
|
||||
setQueriedCurrent(queriedCurrent + message.data.current);
|
||||
setQueriedTotal(message.data.total);
|
||||
setLeftOffBottom(message.data.leftOff);
|
||||
setTruncatedTimestamp(message.data.truncatedTimestamp);
|
||||
if (leftOffTop === null) {
|
||||
@ -218,12 +208,8 @@ export const TrafficViewer: React.FC<TrafficViewerProps> = ({ setAnalyzeStatus,
|
||||
case "startTime":
|
||||
setStartTime(message.data);
|
||||
break;
|
||||
default:
|
||||
console.error(
|
||||
`unsupported websocket message type, Got: ${message.messageType}`
|
||||
);
|
||||
}
|
||||
};
|
||||
})
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
@ -272,7 +258,7 @@ export const TrafficViewer: React.FC<TrafficViewerProps> = ({ setAnalyzeStatus,
|
||||
};
|
||||
|
||||
const getConnectionIndicator = () => {
|
||||
switch (ws?.current?.readyState) {
|
||||
switch (wsReadyState) {
|
||||
case WebSocket.OPEN:
|
||||
return <div className={`${TrafficViewerStyles.indicatorContainer} ${TrafficViewerStyles.greenIndicatorContainer}`}>
|
||||
<div className={`${TrafficViewerStyles.indicator} ${TrafficViewerStyles.greenIndicator}`} />
|
||||
@ -285,7 +271,7 @@ export const TrafficViewer: React.FC<TrafficViewerProps> = ({ setAnalyzeStatus,
|
||||
}
|
||||
|
||||
const getConnectionTitle = () => {
|
||||
switch (ws?.current?.readyState) {
|
||||
switch (wsReadyState) {
|
||||
case WebSocket.OPEN:
|
||||
return "streaming live traffic"
|
||||
default:
|
||||
@ -305,9 +291,9 @@ export const TrafficViewer: React.FC<TrafficViewerProps> = ({ setAnalyzeStatus,
|
||||
{tappingStatus && isShowStatusBar && <StatusBar isDemoBannerView={isDemoBannerView} />}
|
||||
<div className={TrafficViewerStyles.TrafficPageHeader}>
|
||||
<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} />
|
||||
<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} />
|
||||
<div className={TrafficViewerStyles.connectionText}>
|
||||
{getConnectionTitle()}
|
||||
@ -331,8 +317,6 @@ export const TrafficViewer: React.FC<TrafficViewerProps> = ({ setAnalyzeStatus,
|
||||
setIsSnappedToBottom={setIsSnappedToBottom}
|
||||
queriedCurrent={queriedCurrent}
|
||||
setQueriedCurrent={setQueriedCurrent}
|
||||
queriedTotal={queriedTotal}
|
||||
setQueriedTotal={setQueriedTotal}
|
||||
startTime={startTime}
|
||||
noMoreDataTop={noMoreDataTop}
|
||||
setNoMoreDataTop={setNoMoreDataTop}
|
||||
|
@ -48,7 +48,8 @@
|
||||
"npm-link-shared": "^0.5.6",
|
||||
"react-app-rewire-alias": "^1.1.7",
|
||||
"react-dev-utils": "^12.0.0",
|
||||
"recoil": "^0.5.2"
|
||||
"recoil": "^0.5.2",
|
||||
"react-error-overlay": "6.0.9"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "craco start",
|
||||
|
Loading…
Reference in New Issue
Block a user