From 0dc0459dff14e2f62c8df8c37bcbaca6ded622ef Mon Sep 17 00:00:00 2001 From: lirazyehezkel <61656597+lirazyehezkel@users.noreply.github.com> Date: Sun, 8 May 2022 15:45:33 +0300 Subject: [PATCH 1/9] Disable tapping status when streaming is paused (#1070) --- ui-common/src/components/TrafficViewer/TrafficViewer.tsx | 2 +- ui-common/src/components/UI/StatusBar.tsx | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/ui-common/src/components/TrafficViewer/TrafficViewer.tsx b/ui-common/src/components/TrafficViewer/TrafficViewer.tsx index b4a044859..a8a0e7380 100644 --- a/ui-common/src/components/TrafficViewer/TrafficViewer.tsx +++ b/ui-common/src/components/TrafficViewer/TrafficViewer.tsx @@ -240,7 +240,7 @@ export const TrafficViewer: React.FC = ({ return (
- {tappingStatus && isShowStatusBar && } + {tappingStatus && isShowStatusBar && }
{ return `${noun}${amount !== 1 ? 's' : ''}` @@ -12,20 +13,22 @@ const pluralize = (noun: string, amount: number) => { interface StatusBarProps { isDemoBannerView: boolean; + disabled?: boolean; } -export const StatusBar: React.FC = ({isDemoBannerView}) => { +export const StatusBar: React.FC = ({isDemoBannerView, disabled}) => { const tappingStatus = useRecoilValue(tappingStatusAtom); const [expandedBar, setExpandedBar] = useState(false); const {uniqueNamespaces, amountOfPods, amountOfTappedPods, amountOfUntappedPods} = useRecoilValue(tappingStatusDetails); - return
setExpandedBar(true)} onMouseLeave={() => setExpandedBar(false)} data-cy="expandedStatusBar"> + return
setExpandedBar(true)} onMouseLeave={() => setExpandedBar(false)} data-cy="expandedStatusBar">
{tappingStatus.some(pod => !pod.isTapped) && warning} + {disabled && warning} {`Tapping ${amountOfUntappedPods > 0 ? amountOfTappedPods + " / " + amountOfPods : amountOfPods} ${pluralize('pod', amountOfPods)} in ${pluralize('namespace', uniqueNamespaces.length)} ${uniqueNamespaces.join(", ")}`}
- {expandedBar &&
+ {expandedBar && !disabled &&
From 4c0aeb8146f654d538a45d9e3957633cb76f23e9 Mon Sep 17 00:00:00 2001 From: RoyUP9 <87927115+RoyUP9@users.noreply.github.com> Date: Sun, 8 May 2022 16:52:50 +0300 Subject: [PATCH 2/9] Fixed default mime type to empty string instead of text/html (#1071) --- agent/pkg/har/utils.go | 8 ++++---- tap/extensions/http/Makefile | 2 +- tap/extensions/http/main.go | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/agent/pkg/har/utils.go b/agent/pkg/har/utils.go index 24e04e853..3c1289858 100644 --- a/agent/pkg/har/utils.go +++ b/agent/pkg/har/utils.go @@ -124,8 +124,8 @@ func NewRequest(request map[string]interface{}) (harRequest *Request, err error) postData, _ := request["postData"].(map[string]interface{}) mimeType := postData["mimeType"] - if mimeType == nil || len(mimeType.(string)) == 0 { - mimeType = "text/html" + if mimeType == nil { + mimeType = "" } text := postData["text"] postDataText := "" @@ -177,8 +177,8 @@ func NewResponse(response map[string]interface{}) (harResponse *Response, err er content, _ := response["content"].(map[string]interface{}) mimeType := content["mimeType"] - if mimeType == nil || len(mimeType.(string)) == 0 { - mimeType = "text/html" + if mimeType == nil { + mimeType = "" } encoding := content["encoding"] text := content["text"] diff --git a/tap/extensions/http/Makefile b/tap/extensions/http/Makefile index 1bdbf379b..41e520dad 100644 --- a/tap/extensions/http/Makefile +++ b/tap/extensions/http/Makefile @@ -13,4 +13,4 @@ test-pull-bin: test-pull-expect: @mkdir -p expect - @[ "${skipexpect}" ] && echo "Skipping downloading expected JSONs" || gsutil -o 'GSUtil:parallel_process_count=5' -o 'GSUtil:parallel_thread_count=5' -m cp -r gs://static.up9.io/mizu/test-pcap/expect8/http/\* expect + @[ "${skipexpect}" ] && echo "Skipping downloading expected JSONs" || gsutil -o 'GSUtil:parallel_process_count=5' -o 'GSUtil:parallel_thread_count=5' -m cp -r gs://static.up9.io/mizu/test-pcap/expect9/http/\* expect diff --git a/tap/extensions/http/main.go b/tap/extensions/http/main.go index 6b32cc72f..e8131076a 100644 --- a/tap/extensions/http/main.go +++ b/tap/extensions/http/main.go @@ -401,8 +401,8 @@ func representRequest(request map[string]interface{}) (repRequest []interface{}) postData, _ := request["postData"].(map[string]interface{}) mimeType := postData["mimeType"] - if mimeType == nil || len(mimeType.(string)) == 0 { - mimeType = "text/html" + if mimeType == nil { + mimeType = "" } text := postData["text"] if text != nil { @@ -483,8 +483,8 @@ func representResponse(response map[string]interface{}) (repResponse []interface content, _ := response["content"].(map[string]interface{}) mimeType := content["mimeType"] - if mimeType == nil || len(mimeType.(string)) == 0 { - mimeType = "text/html" + if mimeType == nil { + mimeType = "" } encoding := content["encoding"] text := content["text"] From eef0ee80237a2bf8bce91766c0ffd27468e69d9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=2E=20Mert=20Y=C4=B1ld=C4=B1ran?= Date: Mon, 9 May 2022 09:11:27 -0700 Subject: [PATCH 3/9] Fetch N number of records in M milliseconds timeout before streaming the records (#1056) * Fetch N number of records in M milliseconds timeout before streaming the records * Implement the functionality inside socket data streamer * Reverse the `fetchData` slice * #run_acceptance_tests * Trying to fix the tests. #run_acceptance_tests * javascript compilation error. * #run_acceptance_tests * Name the method better * Upgrade Basenine version to `v0.8.0` * Fix some issues related to `Fetch` * Upgrade the Basenine version in `Dockerfile` as well * Remove underscore from the parameter name * Parameterize fetch timeout ms Co-authored-by: gadotroee <55343099+gadotroee@users.noreply.github.com> Co-authored-by: Roee Gadot --- Dockerfile | 4 +- .../integration/testHelpers/TrafficHelper.js | 15 +---- .../integration/tests/IgnoredUserAgents.js | 14 ++-- .../cypress/integration/tests/UiTest.js | 4 -- agent/go.mod | 2 +- agent/go.sum | 4 +- agent/pkg/api/socket_data_streamer.go | 66 ++++++++++++++++++- agent/pkg/api/socket_routes.go | 3 + agent/pkg/entries/entries_provider.go | 4 +- agent/pkg/oas/oas_generator.go | 2 +- agent/pkg/up9/main.go | 2 +- .../components/TrafficViewer/EntriesList.tsx | 8 +-- .../TrafficViewer/TrafficViewer.tsx | 24 +++---- ui-common/src/hooks/useWS.tsx | 4 +- ui-common/src/index.tsx | 4 +- 15 files changed, 105 insertions(+), 55 deletions(-) diff --git a/Dockerfile b/Dockerfile index 62ba07c93..4923cc9ae 100644 --- a/Dockerfile +++ b/Dockerfile @@ -94,8 +94,8 @@ RUN go build -ldflags="-extldflags=-static -s -w \ -X 'github.com/up9inc/mizu/agent/pkg/version.Ver=${VER}'" -o mizuagent . # Download Basenine executable, verify the sha1sum -ADD https://github.com/up9inc/basenine/releases/download/v0.7.3/basenine_linux_${GOARCH} ./basenine_linux_${GOARCH} -ADD https://github.com/up9inc/basenine/releases/download/v0.7.3/basenine_linux_${GOARCH}.sha256 ./basenine_linux_${GOARCH}.sha256 +ADD https://github.com/up9inc/basenine/releases/download/v0.8.1/basenine_linux_${GOARCH} ./basenine_linux_${GOARCH} +ADD https://github.com/up9inc/basenine/releases/download/v0.8.1/basenine_linux_${GOARCH}.sha256 ./basenine_linux_${GOARCH}.sha256 RUN shasum -a 256 -c basenine_linux_"${GOARCH}".sha256 && \ chmod +x ./basenine_linux_"${GOARCH}" && \ diff --git a/acceptanceTests/cypress/integration/testHelpers/TrafficHelper.js b/acceptanceTests/cypress/integration/testHelpers/TrafficHelper.js index e63821d9c..1fb286760 100644 --- a/acceptanceTests/cypress/integration/testHelpers/TrafficHelper.js +++ b/acceptanceTests/cypress/integration/testHelpers/TrafficHelper.js @@ -57,13 +57,6 @@ export function rightOnHoverCheck(path, expectedText) { cy.get(`#rightSideContainer [data-cy='QueryableTooltip']`).invoke('text').should('match', new RegExp(expectedText)); } -export function checkThatAllEntriesShown() { - cy.get('#entries-length').then(number => { - if (number.text() === '1') - cy.get('[title="Fetch old records"]').click(); - }); -} - export function checkFilterByMethod(funcDict) { const {protocol, method, methodQuery, summary, summaryQuery} = funcDict; const summaryDict = getSummaryDict(summary, summaryQuery); @@ -76,12 +69,7 @@ export function checkFilterByMethod(funcDict) { cy.get('[type="submit"]').click(); cy.get('.w-tc-editor').should('have.attr', 'style').and('include', Cypress.env('greenFilterColor')); - cy.get('#entries-length').then(number => { - // if the entries list isn't expanded it expands here - if (number.text() === '0' || number.text() === '1') // todo change when TRA-4262 is fixed - cy.get('[title="Fetch old records"]').click(); - - cy.get('#entries-length').should('not.have.text', '0').and('not.have.text', '1').then(() => { + cy.get('#entries-length').should('not.have.text', '0').then(() => { cy.get(`#list [id]`).then(elements => { const listElmWithIdAttr = Object.values(elements); let doneCheckOnFirst = false; @@ -108,7 +96,6 @@ export function checkFilterByMethod(funcDict) { }); }); }); - }); } export function getEntryId(id) { diff --git a/acceptanceTests/cypress/integration/tests/IgnoredUserAgents.js b/acceptanceTests/cypress/integration/tests/IgnoredUserAgents.js index f6c11a85d..50f59953a 100644 --- a/acceptanceTests/cypress/integration/tests/IgnoredUserAgents.js +++ b/acceptanceTests/cypress/integration/tests/IgnoredUserAgents.js @@ -1,5 +1,4 @@ import { - checkThatAllEntriesShown, isValueExistsInElement, resizeToHugeMizu, } from "../testHelpers/TrafficHelper"; @@ -12,13 +11,14 @@ checkEntries(); function checkEntries() { it('checking all entries', function () { - checkThatAllEntriesShown(); - resizeToHugeMizu(); + cy.get('#entries-length').should('not.have.text', '0').then(() => { + resizeToHugeMizu(); - cy.get('#list [id^=entry]').each(entryElement => { - entryElement.click(); - cy.get('#tbody-Headers').should('be.visible'); - isValueExistsInElement(false, 'Ignored-User-Agent', '#tbody-Headers'); + cy.get('#list [id^=entry]').each(entryElement => { + entryElement.click(); + cy.get('#tbody-Headers').should('be.visible'); + isValueExistsInElement(false, 'Ignored-User-Agent', '#tbody-Headers'); + }); }); }); } diff --git a/acceptanceTests/cypress/integration/tests/UiTest.js b/acceptanceTests/cypress/integration/tests/UiTest.js index 2e538ac18..6b9de5069 100644 --- a/acceptanceTests/cypress/integration/tests/UiTest.js +++ b/acceptanceTests/cypress/integration/tests/UiTest.js @@ -218,12 +218,8 @@ function checkFilter(filterDetails) { checkRightSideResponseBody(); }); - cy.get('[title="Fetch old records"]').click(); resizeToHugeMizu(); - // waiting for the entries number to load - cy.get('#entries-length', {timeout: refreshWaitTimeout}).should('have.text', totalEntries); - // checking only 'leftTextCheck' on all entries because the rest of the checks require more time cy.get(`#list [id^=entry]`).each(elem => { const element = elem[0]; diff --git a/agent/go.mod b/agent/go.mod index 9564468c6..37ba205a8 100644 --- a/agent/go.mod +++ b/agent/go.mod @@ -20,7 +20,7 @@ require ( github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 github.com/orcaman/concurrent-map v1.0.0 github.com/stretchr/testify v1.7.0 - github.com/up9inc/basenine/client/go v0.0.0-20220419100955-e2ca51087607 + github.com/up9inc/basenine/client/go v0.0.0-20220508080324-c66c4e1b9337 github.com/up9inc/mizu/logger v0.0.0 github.com/up9inc/mizu/shared v0.0.0 github.com/up9inc/mizu/tap v0.0.0 diff --git a/agent/go.sum b/agent/go.sum index 624535717..a8a3bbdfc 100644 --- a/agent/go.sum +++ b/agent/go.sum @@ -683,8 +683,8 @@ github.com/ugorji/go v1.2.6/go.mod h1:anCg0y61KIhDlPZmnH+so+RQbysYVyDko0IMgJv0Nn github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/ugorji/go/codec v1.2.6 h1:7kbGefxLoDBuYXOms4yD7223OpNMMPNPZxXk5TvFcyQ= github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxWFFpvxTw= -github.com/up9inc/basenine/client/go v0.0.0-20220419100955-e2ca51087607 h1:UqxUSkOYOmsLZWQtMSk02ttnhdRwBRLOLt2aDiS9tEk= -github.com/up9inc/basenine/client/go v0.0.0-20220419100955-e2ca51087607/go.mod h1:SvJGPoa/6erhUQV7kvHBwM/0x5LyO6XaG2lUaCaKiUI= +github.com/up9inc/basenine/client/go v0.0.0-20220508080324-c66c4e1b9337 h1:eRXRZnojrZyhbiSuGHl0EPvFtWvx1ZMrsY/bSoBzYNE= +github.com/up9inc/basenine/client/go v0.0.0-20220508080324-c66c4e1b9337/go.mod h1:SvJGPoa/6erhUQV7kvHBwM/0x5LyO6XaG2lUaCaKiUI= github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg= github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= github.com/wI2L/jsondiff v0.1.1 h1:r2TkoEet7E4JMO5+s1RCY2R0LrNPNHY6hbDeow2hRHw= diff --git a/agent/pkg/api/socket_data_streamer.go b/agent/pkg/api/socket_data_streamer.go index 42094875d..7ed1d01cb 100644 --- a/agent/pkg/api/socket_data_streamer.go +++ b/agent/pkg/api/socket_data_streamer.go @@ -3,6 +3,7 @@ package api import ( "context" "encoding/json" + "time" basenine "github.com/up9inc/basenine/client/go" "github.com/up9inc/mizu/agent/pkg/dependency" @@ -38,6 +39,11 @@ func (e *BasenineEntryStreamer) Get(ctx context.Context, socketId int, params *W entryStreamerSocketConnector.SendToastError(socketId, err) } + leftOff, err := e.fetch(socketId, params, entryStreamerSocketConnector) + if err != nil { + logger.Log.Errorf("Fetch error: %v", err.Error()) + } + handleDataChannel := func(c *basenine.Connection, data chan []byte) { for { bytes := <-data @@ -79,7 +85,7 @@ func (e *BasenineEntryStreamer) Get(ctx context.Context, socketId int, params *W go handleDataChannel(connection, data) go handleMetaChannel(connection, meta) - if err = connection.Query(query, data, meta); err != nil { + if err = connection.Query(leftOff, query, data, meta); err != nil { logger.Log.Errorf("Query mode call failed: %v", err) entryStreamerSocketConnector.CleanupSocket(socketId) return err @@ -94,3 +100,61 @@ func (e *BasenineEntryStreamer) Get(ctx context.Context, socketId int, params *W return nil } + +// Reverses a []byte slice. +func (e *BasenineEntryStreamer) fetch(socketId int, params *WebSocketParams, connector EntryStreamerSocketConnector) (leftOff string, err error) { + if params.Fetch <= 0 { + leftOff = params.LeftOff + return + } + + var data [][]byte + var firstMeta []byte + var lastMeta []byte + data, firstMeta, lastMeta, err = basenine.Fetch( + shared.BasenineHost, + shared.BaseninePort, + params.LeftOff, + -1, + params.Query, + params.Fetch, + time.Duration(params.TimeoutMs)*time.Millisecond, + ) + if err != nil { + return + } + + var firstMetadata *basenine.Metadata + err = json.Unmarshal(firstMeta, &firstMetadata) + if err != nil { + return + } + leftOff = firstMetadata.LeftOff + + var lastMetadata *basenine.Metadata + err = json.Unmarshal(lastMeta, &lastMetadata) + if err != nil { + return + } + connector.SendMetadata(socketId, lastMetadata) + + data = e.reverseBytesSlice(data) + for _, row := range data { + var entry *tapApi.Entry + err = json.Unmarshal(row, &entry) + if err != nil { + break + } + + connector.SendEntry(socketId, entry, params) + } + return +} + +// Reverses a []byte slice. +func (e *BasenineEntryStreamer) reverseBytesSlice(arr [][]byte) (newArr [][]byte) { + for i := len(arr) - 1; i >= 0; i-- { + newArr = append(newArr, arr[i]) + } + return newArr +} diff --git a/agent/pkg/api/socket_routes.go b/agent/pkg/api/socket_routes.go index 33d428fa0..7e2c1b896 100644 --- a/agent/pkg/api/socket_routes.go +++ b/agent/pkg/api/socket_routes.go @@ -34,8 +34,11 @@ type SocketConnection struct { } type WebSocketParams struct { + LeftOff string `json:"leftOff"` Query string `json:"query"` EnableFullEntries bool `json:"enableFullEntries"` + Fetch int `json:"fetch"` + TimeoutMs int `json:"timeoutMs"` } var ( diff --git a/agent/pkg/entries/entries_provider.go b/agent/pkg/entries/entries_provider.go index ceb8c34a7..f9b97fc17 100644 --- a/agent/pkg/entries/entries_provider.go +++ b/agent/pkg/entries/entries_provider.go @@ -22,7 +22,7 @@ type EntriesProvider interface { type BasenineEntriesProvider struct{} func (e *BasenineEntriesProvider) GetEntries(entriesRequest *models.EntriesRequest) ([]*tapApi.EntryWrapper, *basenine.Metadata, error) { - data, meta, err := basenine.Fetch(shared.BasenineHost, shared.BaseninePort, + data, _, lastMeta, err := basenine.Fetch(shared.BasenineHost, shared.BaseninePort, entriesRequest.LeftOff, entriesRequest.Direction, entriesRequest.Query, entriesRequest.Limit, time.Duration(entriesRequest.TimeoutMs)*time.Millisecond) if err != nil { @@ -49,7 +49,7 @@ func (e *BasenineEntriesProvider) GetEntries(entriesRequest *models.EntriesReque } var metadata *basenine.Metadata - err = json.Unmarshal(meta, &metadata) + err = json.Unmarshal(lastMeta, &metadata) if err != nil { logger.Log.Debugf("Error recieving metadata: %v", err.Error()) } diff --git a/agent/pkg/oas/oas_generator.go b/agent/pkg/oas/oas_generator.go index 5ca61a9dc..5132d6e21 100644 --- a/agent/pkg/oas/oas_generator.go +++ b/agent/pkg/oas/oas_generator.go @@ -104,7 +104,7 @@ func (g *defaultOasGenerator) runGenerator() { g.dbMutex.Lock() defer g.dbMutex.Unlock() logger.Log.Infof("Querying DB for OAS generator with query '%s'", g.entriesQuery) - if err := g.dbConn.Query(g.entriesQuery, dataChan, metaChan); err != nil { + if err := g.dbConn.Query("", g.entriesQuery, dataChan, metaChan); err != nil { logger.Log.Errorf("Query mode call failed: %v", err) } diff --git a/agent/pkg/up9/main.go b/agent/pkg/up9/main.go index 513ed8216..bdd44b476 100644 --- a/agent/pkg/up9/main.go +++ b/agent/pkg/up9/main.go @@ -327,7 +327,7 @@ BasenineReconnect: go handleMetaChannel(&wg, connection, meta) wg.Add(2) - if err = connection.Query(query, data, meta); err != nil { + if err = connection.Query("", query, data, meta); err != nil { logger.Log.Errorf("Query mode call failed: %v", err) connection.Close() time.Sleep(shared.BasenineReconnectInterval * time.Second) diff --git a/ui-common/src/components/TrafficViewer/EntriesList.tsx b/ui-common/src/components/TrafficViewer/EntriesList.tsx index f14c8bd90..9c03cc58b 100644 --- a/ui-common/src/components/TrafficViewer/EntriesList.tsx +++ b/ui-common/src/components/TrafficViewer/EntriesList.tsx @@ -23,7 +23,7 @@ interface EntriesListProps { setIsSnappedToBottom: any; noMoreDataTop: boolean; setNoMoreDataTop: (flag: boolean) => void; - openWebSocket: (query: string, resetEntries: boolean) => void; + openWebSocket: (leftOff: string, query: string, resetEntries: boolean, fetch: number, fetchTimeoutMs: number) => void; scrollableRef: any; ws: any; } @@ -195,11 +195,7 @@ export const EntriesList: React.FC = ({ className={`${styles.btnLive} ${isSnappedToBottom && !isWsConnectionClosed ? styles.hideButton : styles.showButton}`} onClick={(_) => { if (isWsConnectionClosed) { - if (query) { - openWebSocket(`(${query}) and leftOff("${leftOffBottom}")`, false); - } else { - openWebSocket(`leftOff("${leftOffBottom}")`, false); - } + openWebSocket(leftOffBottom, query, false, 0, 0); } scrollableRef.current.jumpToBottom(); setIsSnappedToBottom(true); diff --git a/ui-common/src/components/TrafficViewer/TrafficViewer.tsx b/ui-common/src/components/TrafficViewer/TrafficViewer.tsx index a8a0e7380..f1eef2124 100644 --- a/ui-common/src/components/TrafficViewer/TrafficViewer.tsx +++ b/ui-common/src/components/TrafficViewer/TrafficViewer.tsx @@ -20,7 +20,7 @@ import {StatusBar} from "../UI/StatusBar"; import tappingStatusAtom from "../../recoil/tappingStatus/atom"; import {TOAST_CONTAINER_ID} from "../../configs/Consts"; import leftOffTopAtom from "../../recoil/leftOffTop"; -import { DEFAULT_QUERY } from '../../hooks/useWS'; +import { DEFAULT_LEFTOFF, DEFAULT_FETCH, DEFAULT_FETCH_TIMEOUT_MS } from '../../hooks/useWS'; const useLayoutStyles = makeStyles(() => ({ details: { @@ -114,11 +114,7 @@ export const TrafficViewer: React.FC = ({ const ws = useRef(null); const openEmptyWebSocket = () => { - if (query) { - openWebSocket(`(${query}) and ${DEFAULT_QUERY}`, true); - } else { - openWebSocket(DEFAULT_QUERY, true); - } + openWebSocket(DEFAULT_LEFTOFF, query, true, DEFAULT_FETCH, DEFAULT_FETCH_TIMEOUT_MS); } const closeWebSocket = () => { @@ -129,7 +125,7 @@ export const TrafficViewer: React.FC = ({ } const listEntry = useRef(null); - const openWebSocket = (query: string, resetEntries: boolean) => { + const openWebSocket = (leftOff: string, query: string, resetEntries: boolean, fetch: number, fetchTimeoutMs: number) => { if (resetEntries) { setFocusedEntryId(null); setEntries([]); @@ -138,7 +134,7 @@ export const TrafficViewer: React.FC = ({ } try { ws.current = new WebSocket(webSocketUrl); - sendQueryWhenWsOpen(query); + sendQueryWhenWsOpen(leftOff, query, fetch, fetchTimeoutMs); ws.current.onopen = () => { setWsReadyState(ws?.current?.readyState); @@ -157,12 +153,18 @@ export const TrafficViewer: React.FC = ({ } } - const sendQueryWhenWsOpen = (query) => { + const sendQueryWhenWsOpen = (leftOff: string, query: string, fetch: number, fetchTimeoutMs: number) => { setTimeout(() => { if (ws?.current?.readyState === WebSocket.OPEN) { - ws.current.send(JSON.stringify({"query": query, "enableFullEntries": false})); + ws.current.send(JSON.stringify({ + "leftOff": leftOff, + "query": query, + "enableFullEntries": false, + "fetch": fetch, + "timeoutMs": fetchTimeoutMs + })); } else { - sendQueryWhenWsOpen(query); + sendQueryWhenWsOpen(leftOff, query, fetch, fetchTimeoutMs); } }, 500) } diff --git a/ui-common/src/hooks/useWS.tsx b/ui-common/src/hooks/useWS.tsx index a49c8760c..f06ea280d 100644 --- a/ui-common/src/hooks/useWS.tsx +++ b/ui-common/src/hooks/useWS.tsx @@ -7,7 +7,9 @@ enum WebSocketReadyState { CLOSED } -export const DEFAULT_QUERY = `leftOff("latest")`; +export const DEFAULT_LEFTOFF = `latest`; +export const DEFAULT_FETCH = 50; +export const DEFAULT_FETCH_TIMEOUT_MS = 3000; const useWS = (wsUrl: string) => { const [message, setMessage] = useState(null); diff --git a/ui-common/src/index.tsx b/ui-common/src/index.tsx index 08db78d49..d0b4eb13e 100644 --- a/ui-common/src/index.tsx +++ b/ui-common/src/index.tsx @@ -1,11 +1,11 @@ import TrafficViewer from './components/TrafficViewer/TrafficViewer'; import * as UI from "./components/UI" import { StatusBar } from './components/UI'; -import useWS, { DEFAULT_QUERY } from './hooks/useWS'; +import useWS, { DEFAULT_LEFTOFF } from './hooks/useWS'; import { AnalyzeButton } from "./components/AnalyzeButton/AnalyzeButton" import OasModal from './components/OasModal/OasModal'; import { ServiceMapModal } from './components/ServiceMapModal/ServiceMapModal'; export { UI, AnalyzeButton, StatusBar, OasModal, ServiceMapModal } -export { useWS, DEFAULT_QUERY } +export { useWS, DEFAULT_LEFTOFF } export default TrafficViewer; From b2830f133f6261d2b1fff63230cf7e334364085b Mon Sep 17 00:00:00 2001 From: leon-up9 <97597983+leon-up9@users.noreply.github.com> Date: Tue, 10 May 2022 13:27:41 +0300 Subject: [PATCH 4/9] UI/Service-map-GUI-improvements (#1055) * filters visble on click * servicemap layout * headers added Icon changed * flex removed , we have max size for filter * added mixins * search input caption * PR commemts * changed colors to variables * lint fix small buttom style fix Co-authored-by: Leon <> --- ui-common/src/components.scss | 22 +++++ .../ServiceMapModal.module.sass | 87 ++++++++++++++----- .../ServiceMapModal/ServiceMapModal.tsx | 83 ++++++++++++------ .../assets/filter-icon-clicked.svg | 3 + .../ServiceMapModal/assets/filter-icon.svg | 3 + ui-common/src/components/UI/SelectList.tsx | 4 +- .../UI/style/Resizeable.module.sass | 1 - ui-common/src/helpers/commonStyle.ts | 17 ++-- ui-common/src/variables.module.scss | 4 + 9 files changed, 164 insertions(+), 60 deletions(-) create mode 100644 ui-common/src/components.scss create mode 100644 ui-common/src/components/ServiceMapModal/assets/filter-icon-clicked.svg create mode 100644 ui-common/src/components/ServiceMapModal/assets/filter-icon.svg diff --git a/ui-common/src/components.scss b/ui-common/src/components.scss new file mode 100644 index 000000000..901c1505b --- /dev/null +++ b/ui-common/src/components.scss @@ -0,0 +1,22 @@ +.subSectionHeader{ + position: relative; + font-style: normal; + font-weight: bold; + font-size: 12px; + line-height: 15px; + color: $font-color; + &::after{ + content: ""; + border: 1px solid #E9EBF8; + transform: rotate(180deg); + position: absolute; + left: 0px; + right: -100%; + top: 100%; + bottom: 0%; + width: 100%; + width: -moz-available; + width: -webkit-fill-available; + width: strech; + } +} \ No newline at end of file diff --git a/ui-common/src/components/ServiceMapModal/ServiceMapModal.module.sass b/ui-common/src/components/ServiceMapModal/ServiceMapModal.module.sass index dc552f232..a00abdf3f 100644 --- a/ui-common/src/components/ServiceMapModal/ServiceMapModal.module.sass +++ b/ui-common/src/components/ServiceMapModal/ServiceMapModal.module.sass @@ -1,34 +1,67 @@ @import "../../variables.module" +@import "../../components" + +.closeIcon + position: absolute + right: 20px + top: 20px .modalContainer display: flex + height: calc(100% - 110px) + background: #F0F5FF + padding: 0 15px + padding-bottom: 25px + +.headerContainer width: 100% - height: 100% + background: white + display: flex + align-items: center + margin-bottom: 15px + +.headerSection + display: flex + align-content: center + align-items: center + margin-left: 35px + margin-bottom: 25px + margin-top: 25px + + & .title + font-size: 28px + color: $blue-gray + font-weight: 600 + margin-right: 35px + + & .actions .graphSection flex: 85% .filterSection - flex: 15% height: 100% + display: none + + &.show + display: inline-block .filters table margin-top: 0px - tr - border-style: none - td - color: #8f9bb2 + color: $light-gray font-size: 11px font-weight: 600 - padding-top: 2px - padding-bottom: 2px + padding-top: 5px + padding-bottom: 5px + th + font-size: 12px .colorBlock display: inline-block - height: 15px - width: 50px + height: 12px + width: 22px .filterWrapper height: 100% @@ -36,29 +69,35 @@ flex-direction: column margin-right: 10px width: 100% + border-radius: 4px .servicesFilterSearch - width: calc(100% - 10px) - max-width: 300px + width: -moz-available + width: -webkit-fill-available + width: fill-available + max-width: 200px box-shadow: 0px 1px 5px #979797 margin-left: 10px margin-bottom: 5px + margin-top: 10px + margin-right: 10px + +.protocolsFilterList, .servicesFilter + background: white + padding: 10px + border-radius: 4px + user-select: none .servicesFilter - margin-top: 15px + margin-top: 10px height: 100% overflow: hidden + border-radius: 4px & .servicesFilterList - overflow-y: auto - height: calc(100% - 30px - 5px) + height: calc(100% - 30px - 52px) -.separtorLine - margin-top: 10px - border: 1px solid #E9EBF8 - -.closeIcon - cursor: pointer - user-select: none - margin-top: -15px - margin-right: 5px +.totalSelected + font-size: 12px + color: $light-blue-color + font-weight: 700 diff --git a/ui-common/src/components/ServiceMapModal/ServiceMapModal.tsx b/ui-common/src/components/ServiceMapModal/ServiceMapModal.tsx index 5e5a7dae7..176075cb9 100644 --- a/ui-common/src/components/ServiceMapModal/ServiceMapModal.tsx +++ b/ui-common/src/components/ServiceMapModal/ServiceMapModal.tsx @@ -8,6 +8,8 @@ import debounce from 'lodash/debounce'; import ServiceMapOptions from './ServiceMapOptions' import { useCommonStyles } from "../../helpers/commonStyle"; import refreshIcon from "assets/refresh.svg"; +import filterIcon from "assets/filter-icon.svg"; +import filterIconClicked from "assets/filter-icon-clicked.svg"; import closeIcon from "assets/close.svg" import styles from './ServiceMapModal.module.sass' import SelectList from "../UI/SelectList"; @@ -23,14 +25,14 @@ const modalStyle = { transform: 'translate(-50%, 0%)', width: '89vw', height: '82vh', - bgcolor: 'background.paper', + bgcolor: '#F0F5FF', borderRadius: '5px', boxShadow: 24, p: 4, color: '#000', - padding: "25px 15px" + padding: "1px 1px", + paddingBottom: "15px" }; - interface LegentLabelProps { color: string, name: string @@ -46,13 +48,13 @@ const LegentLabel: React.FC = ({ color, name }) => { } const protocols = [ - { key: "HTTP", value: "HTTP", component: }, - { key: "HTTP/2", value: "HTTP/2", component: }, - { key: "gRPC", value: "gRPC", component: }, + { key: "HTTP", value: "HTTP", component: }, + { key: "HTTP/2", value: "HTTP/2", component: }, + { key: "gRPC", value: "gRPC", component: }, { key: "GQL", value: "GQL", component: }, - { key: "AMQP", value: "AMQP", component: }, - { key: "KAFKA", value: "KAFKA", component: }, - { key: "REDIS", value: "REDIS", component: },] + { key: "AMQP", value: "AMQP", component: }, + { key: "KAFKA", value: "KAFKA", component: }, + { key: "REDIS", value: "REDIS", component: },] interface ServiceMapModalProps { @@ -71,6 +73,7 @@ export const ServiceMapModal: React.FC = ({ isOpen, onClos const [serviceMapApiData, setServiceMapApiData] = useState({ edges: [], nodes: [] }) const [servicesSearchVal, setServicesSearchVal] = useState("") const [graphOptions, setGraphOptions] = useState(ServiceMapOptions); + const [isFilterClicked, setIsFilterClicked] = useState(true) const getServiceMapData = useCallback(async () => { try { @@ -113,15 +116,15 @@ export const ServiceMapModal: React.FC = ({ isOpen, onClos }, } } - const mapToKeyValForFilter = (arr) => arr.map(mapNodesDatatoGraph) + const mapToKeyValForFilter = useCallback((arr) => arr.map(mapNodesDatatoGraph) .map((edge) => { return { key: edge.label, value: edge.label } }) - .sort((a, b) => { return a.key.localeCompare(b.key) }); + .sort((a, b) => { return a.key.localeCompare(b.key) }), []) const getServicesForFilter = useMemo(() => { const resolved = mapToKeyValForFilter(serviceMapApiData.nodes?.filter(x => x.resolved)) const unResolved = mapToKeyValForFilter(serviceMapApiData.nodes?.filter(x => !x.resolved)) return [...resolved, ...unResolved] - }, [serviceMapApiData]) + }, [mapToKeyValForFilter, serviceMapApiData.nodes]) useEffect(() => { const newGraphData: GraphData = { @@ -142,8 +145,9 @@ export const ServiceMapModal: React.FC = ({ isOpen, onClos } useEffect(() => { - if (checkedServices.length == 0) + if (checkedServices.length === 0) setCheckedServices(getServicesForFilter.map(x => x.key).filter(serviceName => !Utils.isIpAddress(serviceName))) + // eslint-disable-next-line react-hooks/exhaustive-deps }, [getServicesForFilter]) useEffect(() => { @@ -173,19 +177,52 @@ export const ServiceMapModal: React.FC = ({ isOpen, onClos BackdropProps={{ timeout: 500 }}> +
+ close onClose()} style={{ cursor: "pointer", userSelect: "none" }}> +
+
+
+ Services + + +
+
+
-
+
- + PROTOCOLS +  ({checkedProtocols.length}) + +
-
- setServicesSearchVal(event.target.value)} /> +

+ SERVICES +  ({checkedServices.length}) +

+ setServicesSearchVal(event.target.value)} />
-
@@ -194,16 +231,6 @@ export const ServiceMapModal: React.FC = ({ isOpen, onClos
- - close onClose()} className={styles.closeIcon}>
{isLoading &&
spinner diff --git a/ui-common/src/components/ServiceMapModal/assets/filter-icon-clicked.svg b/ui-common/src/components/ServiceMapModal/assets/filter-icon-clicked.svg new file mode 100644 index 000000000..a49091966 --- /dev/null +++ b/ui-common/src/components/ServiceMapModal/assets/filter-icon-clicked.svg @@ -0,0 +1,3 @@ + + + diff --git a/ui-common/src/components/ServiceMapModal/assets/filter-icon.svg b/ui-common/src/components/ServiceMapModal/assets/filter-icon.svg new file mode 100644 index 000000000..233bf80fb --- /dev/null +++ b/ui-common/src/components/ServiceMapModal/assets/filter-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/ui-common/src/components/UI/SelectList.tsx b/ui-common/src/components/UI/SelectList.tsx index 4687ba816..3875dedfd 100644 --- a/ui-common/src/components/UI/SelectList.tsx +++ b/ui-common/src/components/UI/SelectList.tsx @@ -72,7 +72,9 @@ const SelectList: React.FC = ({ items, tableName, checkedValues = [], mul const tableHead = multiSelect ?
- + : diff --git a/ui-common/src/components/UI/style/Resizeable.module.sass b/ui-common/src/components/UI/style/Resizeable.module.sass index ca21ffd97..159ae1338 100644 --- a/ui-common/src/components/UI/style/Resizeable.module.sass +++ b/ui-common/src/components/UI/style/Resizeable.module.sass @@ -5,7 +5,6 @@ align-items: center display: flex overflow: hidden - border-right: 1px solid $blue-color height: 100% width: 100% padding-right: 3px diff --git a/ui-common/src/helpers/commonStyle.ts b/ui-common/src/helpers/commonStyle.ts index ed0df460d..9d0ed9675 100644 --- a/ui-common/src/helpers/commonStyle.ts +++ b/ui-common/src/helpers/commonStyle.ts @@ -1,4 +1,5 @@ -import {makeStyles} from "@material-ui/core"; +import { makeStyles } from "@material-ui/core"; +import variables from "../variables.module.scss" // @ts-ignore export const useCommonStyles = makeStyles(() => ({ @@ -9,11 +10,10 @@ export const useCommonStyles = makeStyles(() => ({ fontSize: 12, padding: "9px 12px", borderRadius: "6px ! important", - "&:hover": { backgroundColor: "#205cf5", }, - "&:disabled":{ + "&:disabled": { backgroundColor: "rgba(0, 0, 0, 0.26)" } }, @@ -25,12 +25,17 @@ export const useCommonStyles = makeStyles(() => ({ padding: "8px 12px", border: "1px #205cf5 solid", borderRadius: "6px ! important", - "&:hover": { backgroundColor: "transparent", }, }, - + clickedButton: { + color: "white", + backgroundColor: "#205cf5", + "&:hover": { + backgroundColor: "#205cf5", + }, + }, imagedButton: { padding: "1px 14px" }, @@ -46,7 +51,7 @@ export const useCommonStyles = makeStyles(() => ({ height: "30px", boxSizing: "border-box" }, - modal :{ + modal: { position: 'absolute', top: '40%', left: '50%', diff --git a/ui-common/src/variables.module.scss b/ui-common/src/variables.module.scss index 8c9623ddb..6d78df7b6 100644 --- a/ui-common/src/variables.module.scss +++ b/ui-common/src/variables.module.scss @@ -7,6 +7,10 @@ $blue-color: #205CF5; $light-blue-color: #BCCEFD; $success-color: #27AE60; $failure-color: #EB5757; + +$header-section-color : #fbfcfe; +$content-section-color: #f8f9fc; + $blue-gray: #494677; $light-gray: #8F9BB2; From e24c18254c7b878944d3d98e9fa4377b4643270c Mon Sep 17 00:00:00 2001 From: leon-up9 <97597983+leon-up9@users.noreply.github.com> Date: Tue, 10 May 2022 13:49:46 +0300 Subject: [PATCH 5/9] UI/servicemap-dynamic-protocol-filters (#1072) * filters visble on click * servicemap layout * headers added Icon changed * flex removed , we have max size for filter * selection only from edges * caption changed * removed duplicated code * changes Co-authored-by: Leon <> --- .../ServiceMapModal/ServiceMapModal.tsx | 31 +++++++++++++------ 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/ui-common/src/components/ServiceMapModal/ServiceMapModal.tsx b/ui-common/src/components/ServiceMapModal/ServiceMapModal.tsx index 176075cb9..9ea86c681 100644 --- a/ui-common/src/components/ServiceMapModal/ServiceMapModal.tsx +++ b/ui-common/src/components/ServiceMapModal/ServiceMapModal.tsx @@ -47,14 +47,11 @@ const LegentLabel: React.FC = ({ color, name }) => { } -const protocols = [ - { key: "HTTP", value: "HTTP", component: }, - { key: "HTTP/2", value: "HTTP/2", component: }, - { key: "gRPC", value: "gRPC", component: }, - { key: "GQL", value: "GQL", component: }, - { key: "AMQP", value: "AMQP", component: }, - { key: "KAFKA", value: "KAFKA", component: }, - { key: "REDIS", value: "REDIS", component: },] +type ProtocolType = { + key: string; + value: string; + component: JSX.Element; +}; interface ServiceMapModalProps { @@ -68,7 +65,7 @@ export const ServiceMapModal: React.FC = ({ isOpen, onClos const commonClasses = useCommonStyles(); const [isLoading, setIsLoading] = useState(true); const [graphData, setGraphData] = useState({ nodes: [], edges: [] }); - const [checkedProtocols, setCheckedProtocols] = useState(protocols.map(x => x.key)) + const [checkedProtocols, setCheckedProtocols] = useState([]) const [checkedServices, setCheckedServices] = useState([]) const [serviceMapApiData, setServiceMapApiData] = useState({ edges: [], nodes: [] }) const [servicesSearchVal, setServicesSearchVal] = useState("") @@ -120,6 +117,14 @@ export const ServiceMapModal: React.FC = ({ isOpen, onClos .map((edge) => { return { key: edge.label, value: edge.label } }) .sort((a, b) => { return a.key.localeCompare(b.key) }), []) + const getProtocolsForFilter = useMemo(() => { + return serviceMapApiData.edges.reduce((returnArr, currentValue, currentIndex, array) => { + if (!returnArr.find(prot => prot.key === currentValue.protocol.abbr)) + returnArr.push({ key: currentValue.protocol.abbr, value: currentValue.protocol.abbr, component: }) + return returnArr + }, new Array()) + }, [serviceMapApiData]) + const getServicesForFilter = useMemo(() => { const resolved = mapToKeyValForFilter(serviceMapApiData.nodes?.filter(x => x.resolved)) const unResolved = mapToKeyValForFilter(serviceMapApiData.nodes?.filter(x => !x.resolved)) @@ -150,6 +155,12 @@ export const ServiceMapModal: React.FC = ({ isOpen, onClos // eslint-disable-next-line react-hooks/exhaustive-deps }, [getServicesForFilter]) + useEffect(() => { + if (checkedProtocols.length === 0) { + setCheckedProtocols(getProtocolsForFilter.map(x => x.key)) + } + }, [getProtocolsForFilter]) + useEffect(() => { getServiceMapData() }, [getServiceMapData]) @@ -212,7 +223,7 @@ export const ServiceMapModal: React.FC = ({ isOpen, onClos PROTOCOLS  ({checkedProtocols.length}) -
From ac53508ad7f68b642dd88ac63b37b37106727938 Mon Sep 17 00:00:00 2001 From: AmitUp9 <96980485+AmitUp9@users.noreply.github.com> Date: Wed, 11 May 2022 09:42:47 +0300 Subject: [PATCH 6/9] TRA-4513_grpc heading overlap request size (#1075) * screen resolution changes * fix window width to not overlap between headlines --- ui-common/src/hooks/WindowDimensionsHook.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ui-common/src/hooks/WindowDimensionsHook.tsx b/ui-common/src/hooks/WindowDimensionsHook.tsx index 0f9fa8315..27c774303 100644 --- a/ui-common/src/hooks/WindowDimensionsHook.tsx +++ b/ui-common/src/hooks/WindowDimensionsHook.tsx @@ -14,11 +14,11 @@ export function useRequestTextByWidth(windowWidth){ let responseText = "Response: " let elapsedTimeText = "Elapsed Time: " - if (windowWidth < 1078) { + if (windowWidth < 1436) { requestText = "" responseText = "" elapsedTimeText = "" - } else if (windowWidth < 1356) { + } else if (windowWidth < 1700) { requestText = "Req: " responseText = "Res: " elapsedTimeText = "ET: " @@ -38,6 +38,6 @@ export default function useWindowDimensions() { window.addEventListener('resize', handleResize); return () => window.removeEventListener('resize', handleResize); }, []); - + return windowDimensions; } From 36d59ede07dc6ec82f98412c1e865393337cf5ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=2E=20Mert=20Y=C4=B1ld=C4=B1ran?= Date: Wed, 11 May 2022 03:14:01 -0700 Subject: [PATCH 7/9] Fix acceptance tests failures caused by fetch 50 and a race in the tests (#1074) * #run_acceptance_tests * Wait 4 seconds after filter submission #run_acceptance_tests * Revert "Wait 4 seconds after filter submission #run_acceptance_tests" This reverts commit 3c20ccfcec752dae564a4a6b3f3eccf1cbd9212b. * Upgrade Basenine version to `v0.8.2` #run_acceptance_tests * #run_acceptance_tests * Revert "Revert "Wait 4 seconds after filter submission #run_acceptance_tests"" This reverts commit f0c595150d02b73c1e6b454b88985d6b419e4cb1. * Reduce the delay to 2 seconds #run_acceptance_tests * Use `cy.wait()` instead of `setTimeout` * #run_acceptance_tests * Increase it to 4 seconds #run_acceptance_tests * #run_acceptance_tests * Wait for a second and pause the stream to preserve the DOM #run_acceptance_tests * Wait in a better place #run_acceptance_tests * Wait `pause-icon` to disappear #run_acceptance_tests * Wait one more second #run_acceptance_tests * Fix `setup.sh` * #run_acceptance_tests * Fix the place of `npm i` call * #run_acceptance_tests * Fix the other workflow as well #run_acceptance_tests * Fix the workflows once more * #run_acceptance_tests * Don't ignore `*/cypress/support` #run_acceptance_tests * Do `npm i` in `setup.sh` #run_acceptance_tests * Wait for at least 4 seconds #run_acceptance_tests * #run_acceptance_tests * Fix #run_acceptance_tests * Comment #run_acceptance_tests * Fix `{alt+enter}` to `{ctrl+enter}` and update the `checkFilter` and `deeperCheck` method signatures #run_acceptance_tests * #run_acceptance_tests * #run_acceptance_tests * Extract it to a function #run_acceptance_tests * Remove `cypress-wait-until` * Revert `.gitignore` #run_acceptance_tests --- .gitignore | 2 +- Dockerfile | 4 +- .../cypress/integration/tests/UiTest.js | 59 +++++++++++-------- agent/go.mod | 2 +- agent/go.sum | 4 +- .../TrafficViewer/TrafficViewer.tsx | 15 +++-- 6 files changed, 51 insertions(+), 35 deletions(-) diff --git a/.gitignore b/.gitignore index 80ee94b3a..4169c6803 100644 --- a/.gitignore +++ b/.gitignore @@ -55,4 +55,4 @@ tap/extensions/*/expect *.editorconfig # Ignore *.log files -*.log \ No newline at end of file +*.log diff --git a/Dockerfile b/Dockerfile index 4923cc9ae..16f3dd8cd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -94,8 +94,8 @@ RUN go build -ldflags="-extldflags=-static -s -w \ -X 'github.com/up9inc/mizu/agent/pkg/version.Ver=${VER}'" -o mizuagent . # Download Basenine executable, verify the sha1sum -ADD https://github.com/up9inc/basenine/releases/download/v0.8.1/basenine_linux_${GOARCH} ./basenine_linux_${GOARCH} -ADD https://github.com/up9inc/basenine/releases/download/v0.8.1/basenine_linux_${GOARCH}.sha256 ./basenine_linux_${GOARCH}.sha256 +ADD https://github.com/up9inc/basenine/releases/download/v0.8.2/basenine_linux_${GOARCH} ./basenine_linux_${GOARCH} +ADD https://github.com/up9inc/basenine/releases/download/v0.8.2/basenine_linux_${GOARCH}.sha256 ./basenine_linux_${GOARCH}.sha256 RUN shasum -a 256 -c basenine_linux_"${GOARCH}".sha256 && \ chmod +x ./basenine_linux_"${GOARCH}" && \ diff --git a/acceptanceTests/cypress/integration/tests/UiTest.js b/acceptanceTests/cypress/integration/tests/UiTest.js index 6b9de5069..70bb39096 100644 --- a/acceptanceTests/cypress/integration/tests/UiTest.js +++ b/acceptanceTests/cypress/integration/tests/UiTest.js @@ -65,70 +65,70 @@ it('right side sanity test', function () { checkIllegalFilter('invalid filter'); checkFilter({ - name: 'http', + filter: 'http', leftSidePath: '> :nth-child(1) > :nth-child(1)', leftSideExpectedText: 'HTTP', rightSidePath: '[title=HTTP]', rightSideExpectedText: 'Hypertext Transfer Protocol -- HTTP/1.1', - applyByEnter: true + applyByCtrlEnter: true }); checkFilter({ - name: 'response.status == 200', + filter: 'response.status == 200', leftSidePath: '[title="Status Code"]', leftSideExpectedText: '200', rightSidePath: '> :nth-child(2) [title="Status Code"]', rightSideExpectedText: '200', - applyByEnter: false + applyByCtrlEnter: false }); if (Cypress.env('shouldCheckSrcAndDest')) { serviceMapCheck(); checkFilter({ - name: 'src.name == ""', + filter: 'src.name == ""', leftSidePath: '[title="Source Name"]', leftSideExpectedText: '[Unresolved]', rightSidePath: '> :nth-child(2) [title="Source Name"]', rightSideExpectedText: '[Unresolved]', - applyByEnter: false + applyByCtrlEnter: false }); checkFilter({ - name: `dst.name == "httpbin.mizu-tests"`, + filter: `dst.name == "httpbin.mizu-tests"`, leftSidePath: '> :nth-child(3) > :nth-child(2) > :nth-child(3) > :nth-child(2)', leftSideExpectedText: 'httpbin.mizu-tests', rightSidePath: '> :nth-child(2) > :nth-child(2) > :nth-child(2) > :nth-child(3) > :nth-child(2)', rightSideExpectedText: 'httpbin.mizu-tests', - applyByEnter: false + applyByCtrlEnter: false }); } checkFilter({ - name: 'request.method == "GET"', + filter: 'request.method == "GET"', leftSidePath: '> :nth-child(3) > :nth-child(1) > :nth-child(1) > :nth-child(2)', leftSideExpectedText: 'GET', rightSidePath: '> :nth-child(2) > :nth-child(2) > :nth-child(1) > :nth-child(1) > :nth-child(2)', rightSideExpectedText: 'GET', - applyByEnter: true + applyByCtrlEnter: true }); checkFilter({ - name: 'request.path == "/get"', + filter: 'request.path == "/get"', leftSidePath: '> :nth-child(3) > :nth-child(1) > :nth-child(2) > :nth-child(2)', leftSideExpectedText: '/get', rightSidePath: '> :nth-child(2) > :nth-child(2) > :nth-child(1) > :nth-child(2) > :nth-child(2)', rightSideExpectedText: '/get', - applyByEnter: false + applyByCtrlEnter: false }); checkFilter({ - name: 'src.ip == "127.0.0.1"', + filter: 'src.ip == "127.0.0.1"', leftSidePath: '[title="Source IP"]', leftSideExpectedText: '127.0.0.1', rightSidePath: '> :nth-child(2) [title="Source IP"]', rightSideExpectedText: '127.0.0.1', - applyByEnter: false + applyByCtrlEnter: false }); checkFilterNoResults('request.method == "POST"'); @@ -182,17 +182,19 @@ function checkIllegalFilter(illegalFilterName) { function checkFilter(filterDetails) { const { - name, + filter, leftSidePath, rightSidePath, rightSideExpectedText, leftSideExpectedText, - applyByEnter + applyByCtrlEnter } = filterDetails; const entriesForDeeperCheck = 5; - it(`checking the filter: ${name}`, function () { + it(`checking the filter: ${filter}`, function () { + waitForFetch50AndPause(); + cy.get('#total-entries').should('not.have.text', '0').then(number => { const totalEntries = number.text(); @@ -200,21 +202,23 @@ function checkFilter(filterDetails) { const element = elem[0]; const entryId = getEntryId(element.id); // checks the hover on the last entry (the only one in DOM at the beginning) - leftOnHoverCheck(entryId, leftSidePath, name); + leftOnHoverCheck(entryId, leftSidePath, filter); cy.get('.w-tc-editor-text').clear(); // applying the filter with alt+enter or with the button - cy.get('.w-tc-editor-text').type(`${name}${applyByEnter ? '{alt+enter}' : ''}`); + cy.get('.w-tc-editor-text').type(`${filter}${applyByCtrlEnter ? '{ctrl+enter}' : ''}`); cy.get('.w-tc-editor').should('have.attr', 'style').and('include', Cypress.env('greenFilterColor')); - if (!applyByEnter) + if (!applyByCtrlEnter) cy.get('[type="submit"]').click(); + waitForFetch50AndPause(); + // only one entry in DOM after filtering, checking all checks on it leftTextCheck(entryId, leftSidePath, leftSideExpectedText); - leftOnHoverCheck(entryId, leftSidePath, name); + leftOnHoverCheck(entryId, leftSidePath, filter); rightTextCheck(rightSidePath, rightSideExpectedText); - rightOnHoverCheck(rightSidePath, name); + rightOnHoverCheck(rightSidePath, filter); checkRightSideResponseBody(); }); @@ -228,7 +232,7 @@ function checkFilter(filterDetails) { }); // making the other 3 checks on the first X entries (longer time for each check) - deeperCheck(leftSidePath, rightSidePath, name, leftSideExpectedText, rightSideExpectedText, entriesForDeeperCheck); + deeperCheck(leftSidePath, rightSidePath, filter, rightSideExpectedText, entriesForDeeperCheck); // reloading then waiting for the entries number to load resizeToNormalMizu(); @@ -238,7 +242,14 @@ function checkFilter(filterDetails) { }); } -function deeperCheck(leftSidePath, rightSidePath, filterName, leftSideExpectedText, rightSideExpectedText, entriesNumToCheck) { +function waitForFetch50AndPause() { + // wait half a second and pause the stream to preserve the DOM + cy.wait(500); + cy.get('#pause-icon').click(); + cy.get('#pause-icon').should('not.be.visible'); +} + +function deeperCheck(leftSidePath, rightSidePath, filterName, rightSideExpectedText, entriesNumToCheck) { cy.get(`#list [id^=entry]`).each((element, index) => { if (index < entriesNumToCheck) { const entryId = getEntryId(element[0].id); diff --git a/agent/go.mod b/agent/go.mod index 37ba205a8..1f7dae7c8 100644 --- a/agent/go.mod +++ b/agent/go.mod @@ -20,7 +20,7 @@ require ( github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 github.com/orcaman/concurrent-map v1.0.0 github.com/stretchr/testify v1.7.0 - github.com/up9inc/basenine/client/go v0.0.0-20220508080324-c66c4e1b9337 + github.com/up9inc/basenine/client/go v0.0.0-20220509204026-c37adfc587f4 github.com/up9inc/mizu/logger v0.0.0 github.com/up9inc/mizu/shared v0.0.0 github.com/up9inc/mizu/tap v0.0.0 diff --git a/agent/go.sum b/agent/go.sum index a8a3bbdfc..4b78e088d 100644 --- a/agent/go.sum +++ b/agent/go.sum @@ -683,8 +683,8 @@ github.com/ugorji/go v1.2.6/go.mod h1:anCg0y61KIhDlPZmnH+so+RQbysYVyDko0IMgJv0Nn github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/ugorji/go/codec v1.2.6 h1:7kbGefxLoDBuYXOms4yD7223OpNMMPNPZxXk5TvFcyQ= github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxWFFpvxTw= -github.com/up9inc/basenine/client/go v0.0.0-20220508080324-c66c4e1b9337 h1:eRXRZnojrZyhbiSuGHl0EPvFtWvx1ZMrsY/bSoBzYNE= -github.com/up9inc/basenine/client/go v0.0.0-20220508080324-c66c4e1b9337/go.mod h1:SvJGPoa/6erhUQV7kvHBwM/0x5LyO6XaG2lUaCaKiUI= +github.com/up9inc/basenine/client/go v0.0.0-20220509204026-c37adfc587f4 h1:nNOrU1HVH0fnaG7GNhxCc8kNPVL035Iix7ihUF6lZT8= +github.com/up9inc/basenine/client/go v0.0.0-20220509204026-c37adfc587f4/go.mod h1:SvJGPoa/6erhUQV7kvHBwM/0x5LyO6XaG2lUaCaKiUI= github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg= github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= github.com/wI2L/jsondiff v0.1.1 h1:r2TkoEet7E4JMO5+s1RCY2R0LrNPNHY6hbDeow2hRHw= diff --git a/ui-common/src/components/TrafficViewer/TrafficViewer.tsx b/ui-common/src/components/TrafficViewer/TrafficViewer.tsx index f1eef2124..0506c62a6 100644 --- a/ui-common/src/components/TrafficViewer/TrafficViewer.tsx +++ b/ui-common/src/components/TrafficViewer/TrafficViewer.tsx @@ -245,13 +245,18 @@ export const TrafficViewer: React.FC = ({ {tappingStatus && isShowStatusBar && }
- pause - pause + play + src={playIcon} + onClick={toggleConnection}/>
{getConnectionTitle()} {getConnectionIndicator()} From 2fac0009ea14b594289069e2cb91c1b057906342 Mon Sep 17 00:00:00 2001 From: RoyUP9 <87927115+RoyUP9@users.noreply.github.com> Date: Wed, 11 May 2022 15:36:46 +0300 Subject: [PATCH 8/9] Fixed oas query (#1076) --- agent/pkg/oas/oas_generator.go | 2 +- agent/pkg/up9/main.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/agent/pkg/oas/oas_generator.go b/agent/pkg/oas/oas_generator.go index 5132d6e21..a78254802 100644 --- a/agent/pkg/oas/oas_generator.go +++ b/agent/pkg/oas/oas_generator.go @@ -104,7 +104,7 @@ func (g *defaultOasGenerator) runGenerator() { g.dbMutex.Lock() defer g.dbMutex.Unlock() logger.Log.Infof("Querying DB for OAS generator with query '%s'", g.entriesQuery) - if err := g.dbConn.Query("", g.entriesQuery, dataChan, metaChan); err != nil { + if err := g.dbConn.Query("latest", g.entriesQuery, dataChan, metaChan); err != nil { logger.Log.Errorf("Query mode call failed: %v", err) } diff --git a/agent/pkg/up9/main.go b/agent/pkg/up9/main.go index bdd44b476..0a9ff13ee 100644 --- a/agent/pkg/up9/main.go +++ b/agent/pkg/up9/main.go @@ -327,7 +327,7 @@ BasenineReconnect: go handleMetaChannel(&wg, connection, meta) wg.Add(2) - if err = connection.Query("", query, data, meta); err != nil { + if err = connection.Query("latest", query, data, meta); err != nil { logger.Log.Errorf("Query mode call failed: %v", err) connection.Close() time.Sleep(shared.BasenineReconnectInterval * time.Second) From 414e5cfe5aac4ce724923f52aaf445b9ec013de4 Mon Sep 17 00:00:00 2001 From: leon-up9 <97597983+leon-up9@users.noreply.github.com> Date: Wed, 11 May 2022 19:51:12 +0300 Subject: [PATCH 9/9] match selectlist ui (#1077) * insert filter and header to selectlist * handle single select * rename search var * font size changed --- .../ServiceMapModal.module.sass | 5 --- .../ServiceMapModal/ServiceMapModal.tsx | 21 ++++--------- ui-common/src/components/UI/SelectList.tsx | 31 +++++++++++++------ .../UI/style/SelectList.module.sass | 13 +++++++- 4 files changed, 39 insertions(+), 31 deletions(-) diff --git a/ui-common/src/components/ServiceMapModal/ServiceMapModal.module.sass b/ui-common/src/components/ServiceMapModal/ServiceMapModal.module.sass index a00abdf3f..b14c7e4f3 100644 --- a/ui-common/src/components/ServiceMapModal/ServiceMapModal.module.sass +++ b/ui-common/src/components/ServiceMapModal/ServiceMapModal.module.sass @@ -96,8 +96,3 @@ & .servicesFilterList height: calc(100% - 30px - 52px) - -.totalSelected - font-size: 12px - color: $light-blue-color - font-weight: 700 diff --git a/ui-common/src/components/ServiceMapModal/ServiceMapModal.tsx b/ui-common/src/components/ServiceMapModal/ServiceMapModal.tsx index 9ea86c681..2a7e99459 100644 --- a/ui-common/src/components/ServiceMapModal/ServiceMapModal.tsx +++ b/ui-common/src/components/ServiceMapModal/ServiceMapModal.tsx @@ -68,7 +68,6 @@ export const ServiceMapModal: React.FC = ({ isOpen, onClos const [checkedProtocols, setCheckedProtocols] = useState([]) const [checkedServices, setCheckedServices] = useState([]) const [serviceMapApiData, setServiceMapApiData] = useState({ edges: [], nodes: [] }) - const [servicesSearchVal, setServicesSearchVal] = useState("") const [graphOptions, setGraphOptions] = useState(ServiceMapOptions); const [isFilterClicked, setIsFilterClicked] = useState(true) @@ -219,22 +218,14 @@ export const ServiceMapModal: React.FC = ({ isOpen, onClos
-

- PROTOCOLS -  ({checkedProtocols.length}) -

- +
-

- SERVICES -  ({checkedServices.length}) -

- setServicesSearchVal(event.target.value)} /> -
- +
+
diff --git a/ui-common/src/components/UI/SelectList.tsx b/ui-common/src/components/UI/SelectList.tsx index 3875dedfd..8e7e03004 100644 --- a/ui-common/src/components/UI/SelectList.tsx +++ b/ui-common/src/components/UI/SelectList.tsx @@ -3,6 +3,7 @@ import Radio from "./Radio"; import styles from './style/SelectList.module.sass' import NoDataMessage from "./NoDataMessage"; import Checkbox from "./Checkbox"; +import { useCommonStyles } from "../../helpers/commonStyle"; export interface Props { @@ -10,14 +11,17 @@ export interface Props { tableName: string; checkedValues?: string[]; multiSelect: boolean; - searchValue?: string; setCheckedValues: (newValues) => void; - tableClassName? - checkBoxWidth?: string + tableClassName?; + checkBoxWidth?: string; + inputSearchClass? : string + isFilterable? : boolean } -const SelectList: React.FC = ({ items, tableName, checkedValues = [], multiSelect = true, searchValue = "", setCheckedValues, tableClassName, - checkBoxWidth = 50 }) => { +const SelectList: React.FC = ({ items, tableName, checkedValues = [], multiSelect = true, setCheckedValues, tableClassName, + checkBoxWidth = 50 ,inputSearchClass,isFilterable = true}) => { + const commonClasses = useCommonStyles(); + const [searchValue, setSearchValue] = useState("") const noItemsMessage = "No items to show"; const [headerChecked, setHeaderChecked] = useState(false) @@ -73,11 +77,10 @@ const SelectList: React.FC = ({ items, tableName, checkedValues = [], mul
: - - + const tableBody = filteredValues.length === 0 ? @@ -100,7 +103,14 @@ const SelectList: React.FC = ({ items, tableName, checkedValues = [], mul } ) - return
+ return +

+ {tableName} +  ({checkedValues.length}) +

+ {isFilterable && setSearchValue(event.target.value)} data-cy="searchInput" />} +
toggleAll(isChecked)} />{tableName} + {tableName} +
{tableName} toggleAll(isChecked)} /> - {tableName} + All
{tableName}
{tableHead} @@ -110,6 +120,7 @@ const SelectList: React.FC = ({ items, tableName, checkedValues = [], mul
+ } -export default SelectList; \ No newline at end of file +export default SelectList; diff --git a/ui-common/src/components/UI/style/SelectList.module.sass b/ui-common/src/components/UI/style/SelectList.module.sass index 02af14f07..0ce2d1fe9 100644 --- a/ui-common/src/components/UI/style/SelectList.module.sass +++ b/ui-common/src/components/UI/style/SelectList.module.sass @@ -1,4 +1,6 @@ @import '../../../variables.module' +@import '../../../components' + .selectListTable overflow: auto @@ -17,6 +19,7 @@ position: sticky top: 0 background: $main-background-color + font-size: 12px tr border-bottom-width: 1px @@ -27,7 +30,15 @@ td color: $light-gray padding: 10px - font-size: 16px + font-size: 11px + font-weight: 600 + padding-top: 5px + padding-bottom: 5px .nowrap white-space: nowrap + +.totalSelected + font-size: 12px + color: $light-blue-color + font-weight: 700