From 30124de40935c181e93c73bd6c86e032fa867a1d Mon Sep 17 00:00:00 2001 From: Palash gupta Date: Mon, 27 Dec 2021 13:07:10 +0530 Subject: [PATCH 01/28] fix: code vunbretality is fixed --- frontend/src/components/TextToolTip/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/components/TextToolTip/index.tsx b/frontend/src/components/TextToolTip/index.tsx index 83f162fac9..470e61a642 100644 --- a/frontend/src/components/TextToolTip/index.tsx +++ b/frontend/src/components/TextToolTip/index.tsx @@ -8,7 +8,7 @@ const TextToolTip = ({ text, url }: TextToolTipProps) => ( return (
{`${text} `} - + here
From 40c287028b3312ac26fbca2e17a906193ca28f23 Mon Sep 17 00:00:00 2001 From: Palash gupta Date: Mon, 27 Dec 2021 23:55:38 +0530 Subject: [PATCH 02/28] toggle tabs is updated --- frontend/src/components/RouteTab/index.tsx | 51 ++++++++++++++ .../src/container/EditAlertChannels/index.tsx | 22 +----- .../src/container/SettingsWrapper/index.tsx | 70 ------------------- .../src/pages/AlertChannelCreate/index.tsx | 28 ++++++-- frontend/src/pages/AllAlertChannels/index.tsx | 37 +++++++--- frontend/src/pages/Settings/index.tsx | 24 +++++-- frontend/src/store/actions/app/index.ts | 1 - .../store/actions/app/toggleSettingsTab.ts | 16 ----- frontend/src/store/reducers/app.ts | 15 +--- frontend/src/types/actions/app.ts | 12 +--- frontend/src/types/reducer/app.ts | 2 - 11 files changed, 123 insertions(+), 155 deletions(-) create mode 100644 frontend/src/components/RouteTab/index.tsx delete mode 100644 frontend/src/container/SettingsWrapper/index.tsx delete mode 100644 frontend/src/store/actions/app/toggleSettingsTab.ts diff --git a/frontend/src/components/RouteTab/index.tsx b/frontend/src/components/RouteTab/index.tsx new file mode 100644 index 0000000000..12ce2d2a70 --- /dev/null +++ b/frontend/src/components/RouteTab/index.tsx @@ -0,0 +1,51 @@ +import React from 'react'; +import { Tabs, TabsProps } from 'antd'; + +const { TabPane } = Tabs; +import history from 'lib/history'; + +const RouteTab = ({ + routes, + activeKey, + onChangeHandler, + ...rest +}: RouteTabProps & TabsProps): JSX.Element => { + const onChange = (activeRoute: string) => { + onChangeHandler && onChangeHandler(); + + const selectedRoute = routes.find((e) => e.name === activeRoute); + + if (selectedRoute) { + history.push(selectedRoute.route); + } + }; + + return ( + + {routes.map( + ({ Component, name }): JSX.Element => ( + + + + ), + )} + + ); +}; + +interface RouteTabProps { + routes: { + name: string; + route: string; + Component: () => JSX.Element; + }[]; + activeKey: TabsProps['activeKey']; + onChangeHandler?: VoidFunction; +} + +export default RouteTab; diff --git a/frontend/src/container/EditAlertChannels/index.tsx b/frontend/src/container/EditAlertChannels/index.tsx index e947f65dd2..bd707ee2b3 100644 --- a/frontend/src/container/EditAlertChannels/index.tsx +++ b/frontend/src/container/EditAlertChannels/index.tsx @@ -9,17 +9,10 @@ import FormAlertChannels from 'container/FormAlertChannels'; import history from 'lib/history'; import { Store } from 'rc-field-form/lib/interface'; import React, { useCallback, useState } from 'react'; -import { connect } from 'react-redux'; import { useParams } from 'react-router'; -import { bindActionCreators } from 'redux'; -import { ThunkDispatch } from 'redux-thunk'; -import { ToggleSettingsTab } from 'store/actions'; -import AppActions from 'types/actions'; -import { SettingTab } from 'types/reducer/app'; const EditAlertChannels = ({ initialValue, - toggleSettingsTab, }: EditAlertChannelsProps): JSX.Element => { const [formInstance] = Form.useForm(); const [selectedConfig, setSelectedConfig] = useState>({ @@ -52,7 +45,6 @@ const EditAlertChannels = ({ message: 'Success', description: 'Channels Edited Successfully', }); - toggleSettingsTab('Alert Channels'); setTimeout(() => { history.replace(ROUTES.SETTINGS); @@ -100,18 +92,8 @@ const EditAlertChannels = ({ ); }; -interface DispatchProps { - toggleSettingsTab: (props: SettingTab) => void; -} - -const mapDispatchToProps = ( - dispatch: ThunkDispatch, -): DispatchProps => ({ - toggleSettingsTab: bindActionCreators(ToggleSettingsTab, dispatch), -}); - -interface EditAlertChannelsProps extends DispatchProps { +interface EditAlertChannelsProps { initialValue: Store; } -export default connect(null, mapDispatchToProps)(EditAlertChannels); +export default EditAlertChannels; diff --git a/frontend/src/container/SettingsWrapper/index.tsx b/frontend/src/container/SettingsWrapper/index.tsx deleted file mode 100644 index afe59fe7bd..0000000000 --- a/frontend/src/container/SettingsWrapper/index.tsx +++ /dev/null @@ -1,70 +0,0 @@ -import { Tabs } from 'antd'; -import ROUTES from 'constants/routes'; -import history from 'lib/history'; -import React, { useCallback } from 'react'; -import { connect, useSelector } from 'react-redux'; -import { bindActionCreators } from 'redux'; -import { ThunkDispatch } from 'redux-thunk'; -import { ToggleSettingsTab } from 'store/actions'; -import { AppState } from 'store/reducers'; -import AppActions from 'types/actions'; -import AppReducer, { SettingTab } from 'types/reducer/app'; -const { TabPane } = Tabs; - -const SettingsWrapper = ({ - AlertChannels, - General, - toggleSettingsTab, - defaultRoute, -}: SettingsWrapperProps): JSX.Element => { - const { settingsActiveTab } = useSelector( - (state) => state.app, - ); - - const onChangeHandler = useCallback( - (value: SettingTab) => { - toggleSettingsTab(value); - if (value === 'General') { - history.push(ROUTES.SETTINGS); - } - - if (value === 'Alert Channels') { - history.push(ROUTES.ALL_CHANNELS); - } - }, - [toggleSettingsTab], - ); - - return ( - onChangeHandler(value as SettingTab)} - activeKey={defaultRoute || settingsActiveTab} - > - - - - - - - - ); -}; - -interface DispatchProps { - toggleSettingsTab: (props: SettingTab) => void; -} - -const mapDispatchToProps = ( - dispatch: ThunkDispatch, -): DispatchProps => ({ - toggleSettingsTab: bindActionCreators(ToggleSettingsTab, dispatch), -}); - -interface SettingsWrapperProps extends DispatchProps { - General: () => JSX.Element; - AlertChannels: () => JSX.Element; - defaultRoute?: SettingTab; -} - -export default connect(null, mapDispatchToProps)(SettingsWrapper); diff --git a/frontend/src/pages/AlertChannelCreate/index.tsx b/frontend/src/pages/AlertChannelCreate/index.tsx index e7063085d2..226f2ca2c2 100644 --- a/frontend/src/pages/AlertChannelCreate/index.tsx +++ b/frontend/src/pages/AlertChannelCreate/index.tsx @@ -1,18 +1,32 @@ +import RouteTab from 'components/RouteTab'; +import ROUTES from 'constants/routes'; import CreateAlertChannels from 'container/CreateAlertChannels'; import GeneralSettings from 'container/GeneralSettings'; -import SettingsWrapper from 'container/SettingsWrapper'; +import history from 'lib/history'; import React from 'react'; const SettingsPage = (): JSX.Element => { - const AlertChannels = (): JSX.Element => { - return ; - }; + const pathName = history.location.pathname; return ( - { + return ; + }, + name: 'Alert Channels', + route: ROUTES.ALL_CHANNELS, + }, + ], + activeKey: + pathName === ROUTES.SETTINGS ? 'General Settings' : 'Alert Channels', }} /> ); diff --git a/frontend/src/pages/AllAlertChannels/index.tsx b/frontend/src/pages/AllAlertChannels/index.tsx index 716795500c..e557f4e861 100644 --- a/frontend/src/pages/AllAlertChannels/index.tsx +++ b/frontend/src/pages/AllAlertChannels/index.tsx @@ -1,16 +1,33 @@ import AlertChannels from 'container/AllAlertChannels'; import GeneralSettings from 'container/GeneralSettings'; -import SettingsWrapper from 'container/SettingsWrapper'; import React from 'react'; +import RouteTab from 'components/RouteTab'; +import ROUTES from 'constants/routes'; +import history from 'lib/history'; -const AllAlertChannels = (): JSX.Element => ( - -); +const AllAlertChannels = (): JSX.Element => { + const pathName = history.location.pathname; + + return ( + + ); +}; export default AllAlertChannels; diff --git a/frontend/src/pages/Settings/index.tsx b/frontend/src/pages/Settings/index.tsx index 3a8687c48a..c5310107f3 100644 --- a/frontend/src/pages/Settings/index.tsx +++ b/frontend/src/pages/Settings/index.tsx @@ -1,14 +1,30 @@ import AlertChannels from 'container/AllAlertChannels'; import GeneralSettings from 'container/GeneralSettings'; -import SettingsWrapper from 'container/SettingsWrapper'; import React from 'react'; +import RouteTab from 'components/RouteTab'; +import ROUTES from 'constants/routes'; +import history from 'lib/history'; const SettingsPage = (): JSX.Element => { + const pathName = history.location.pathname; + return ( - ); diff --git a/frontend/src/store/actions/app/index.ts b/frontend/src/store/actions/app/index.ts index e6c98da1d9..7a067e8542 100644 --- a/frontend/src/store/actions/app/index.ts +++ b/frontend/src/store/actions/app/index.ts @@ -1,3 +1,2 @@ export * from './toggleDarkMode'; -export * from './toggleSettingsTab'; export * from './userLoggedIn'; diff --git a/frontend/src/store/actions/app/toggleSettingsTab.ts b/frontend/src/store/actions/app/toggleSettingsTab.ts deleted file mode 100644 index d60ee26afe..0000000000 --- a/frontend/src/store/actions/app/toggleSettingsTab.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { Dispatch } from 'redux'; -import AppActions from 'types/actions'; -import { SettingTab } from 'types/reducer/app'; - -export const ToggleSettingsTab = ( - props: SettingTab, -): ((dispatch: Dispatch) => void) => { - return (dispatch: Dispatch): void => { - dispatch({ - type: 'TOGGLE_SETTINGS_TABS', - payload: { - activeTab: props, - }, - }); - }; -}; diff --git a/frontend/src/store/reducers/app.ts b/frontend/src/store/reducers/app.ts index d0ab0fef79..8a786919b9 100644 --- a/frontend/src/store/reducers/app.ts +++ b/frontend/src/store/reducers/app.ts @@ -1,10 +1,5 @@ import { IS_LOGGED_IN } from 'constants/auth'; -import { - AppAction, - LOGGED_IN, - SWITCH_DARK_MODE, - TOGGLE_SETTINGS_TABS, -} from 'types/actions/app'; +import { AppAction, LOGGED_IN, SWITCH_DARK_MODE } from 'types/actions/app'; import getTheme from 'lib/theme/getTheme'; import InitialValueTypes from 'types/reducer/app'; import getLocalStorageKey from 'api/browser/localstorage/get'; @@ -12,7 +7,6 @@ import getLocalStorageKey from 'api/browser/localstorage/get'; const InitialValue: InitialValueTypes = { isDarkMode: getTheme() === 'darkMode' ? true : false, isLoggedIn: getLocalStorageKey(IS_LOGGED_IN) === 'yes', - settingsActiveTab: 'General', }; const appReducer = ( @@ -34,13 +28,6 @@ const appReducer = ( }; } - case TOGGLE_SETTINGS_TABS: { - return { - ...state, - settingsActiveTab: action.payload.activeTab, - }; - } - default: return state; } diff --git a/frontend/src/types/actions/app.ts b/frontend/src/types/actions/app.ts index 968ee5f89f..4a8495aafe 100644 --- a/frontend/src/types/actions/app.ts +++ b/frontend/src/types/actions/app.ts @@ -1,8 +1,5 @@ -import { SettingTab } from 'types/reducer/app'; - export const SWITCH_DARK_MODE = 'SWITCH_DARK_MODE'; export const LOGGED_IN = 'LOGGED_IN'; -export const TOGGLE_SETTINGS_TABS = 'TOGGLE_SETTINGS_TABS'; export interface SwitchDarkMode { type: typeof SWITCH_DARK_MODE; @@ -12,11 +9,4 @@ export interface LoggedInUser { type: typeof LOGGED_IN; } -export interface ToggleSettingsTab { - type: typeof TOGGLE_SETTINGS_TABS; - payload: { - activeTab: SettingTab; - }; -} - -export type AppAction = SwitchDarkMode | LoggedInUser | ToggleSettingsTab; +export type AppAction = SwitchDarkMode | LoggedInUser; diff --git a/frontend/src/types/reducer/app.ts b/frontend/src/types/reducer/app.ts index d0e82f0153..2ec974c399 100644 --- a/frontend/src/types/reducer/app.ts +++ b/frontend/src/types/reducer/app.ts @@ -1,6 +1,4 @@ -export type SettingTab = 'General' | 'Alert Channels'; export default interface AppReducer { isDarkMode: boolean; isLoggedIn: boolean; - settingsActiveTab: SettingTab; } From dddba68bfd0b4de984868c382850667630ae76ce Mon Sep 17 00:00:00 2001 From: Palash gupta Date: Tue, 28 Dec 2021 20:51:36 +0530 Subject: [PATCH 03/28] fix: webpack config is updated --- frontend/webpack.config.prod.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/frontend/webpack.config.prod.js b/frontend/webpack.config.prod.js index 4e5db8bbf5..52693e368d 100644 --- a/frontend/webpack.config.prod.js +++ b/frontend/webpack.config.prod.js @@ -115,8 +115,4 @@ const config = { }, }; -if (process.env.BUNDLE_ANALYSER === 'true') { - config.plugins.push(new BundleAnalyzerPlugin({ analyzerMode: 'server' })); -} - module.exports = config; From e7253b7ca62e3b139485898c0e4821e6d4a0656d Mon Sep 17 00:00:00 2001 From: Siddhant Parekh Date: Tue, 4 Jan 2022 13:40:03 +0530 Subject: [PATCH 04/28] fix(FE) Removed refresh time filter from trace-detail page --- frontend/src/container/Header/index.tsx | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/frontend/src/container/Header/index.tsx b/frontend/src/container/Header/index.tsx index 967ddbea74..8884b2231b 100644 --- a/frontend/src/container/Header/index.tsx +++ b/frontend/src/container/Header/index.tsx @@ -2,14 +2,17 @@ import { Col } from 'antd'; import ROUTES from 'constants/routes'; import history from 'lib/history'; import React from 'react'; -import { useLocation } from 'react-router-dom'; +import { useLocation, matchPath } from 'react-router-dom'; import ShowBreadcrumbs from './Breadcrumbs'; import DateTimeSelector from './DateTimeSelection'; import { Container } from './styles'; -const routesToSkip = [ROUTES.SETTINGS, ROUTES.LIST_ALL_ALERT]; - +const routesToSkip = [ + ROUTES.SETTINGS, + ROUTES.LIST_ALL_ALERT, + ROUTES.TRACE_GRAPH, +]; const TopNav = (): JSX.Element | null => { const { pathname } = useLocation(); @@ -18,13 +21,24 @@ const TopNav = (): JSX.Element | null => { return null; } + const checkRouteExists = (currentPath: string) => { + for (let i = 0; i < routesToSkip.length; ++i) { + if ( + matchPath(currentPath, { path: routesToSkip[i], exact: true, strict: true }) + ) { + return true; + } + } + return false; + }; + return ( - {!routesToSkip.includes(pathname) && ( + {!checkRouteExists(pathname) && ( From 9a00dca749ec68ba8d41269ce08852a10676dde7 Mon Sep 17 00:00:00 2001 From: Vishal Sharma Date: Tue, 8 Feb 2022 23:05:50 +0530 Subject: [PATCH 05/28] feat: tag value suggestion API --- .../app/clickhouseReader/reader.go | 73 +++++++++++++++++++ pkg/query-service/app/druidReader/reader.go | 4 + pkg/query-service/app/http_handler.go | 17 +++++ pkg/query-service/app/interface.go | 1 + pkg/query-service/app/parser.go | 25 +++++++ pkg/query-service/model/queryParams.go | 1 + pkg/query-service/model/response.go | 4 + 7 files changed, 125 insertions(+) diff --git a/pkg/query-service/app/clickhouseReader/reader.go b/pkg/query-service/app/clickhouseReader/reader.go index ba20131876..1ce7c066c5 100644 --- a/pkg/query-service/app/clickhouseReader/reader.go +++ b/pkg/query-service/app/clickhouseReader/reader.go @@ -1839,6 +1839,79 @@ func excludeTags(ctx context.Context, tags []model.TagFilters) []model.TagFilter return newTags } +func (r *ClickHouseReader) GetTagValues(ctx context.Context, queryParams *model.TagFilterParams) (*[]model.TagValues, *model.ApiError) { + + excludeMap := make(map[string]struct{}) + for _, e := range queryParams.Exclude { + if e == constants.OperationRequest { + excludeMap[constants.OperationDB] = struct{}{} + continue + } + excludeMap[e] = struct{}{} + } + + var query string + args := []interface{}{queryParams.TagKey, strconv.FormatInt(queryParams.Start.UnixNano(), 10), strconv.FormatInt(queryParams.End.UnixNano(), 10)} + if len(queryParams.ServiceName) > 0 { + args = buildFilterArrayQuery(ctx, excludeMap, queryParams.ServiceName, constants.ServiceName, &query, args) + } + if len(queryParams.HttpRoute) > 0 { + args = buildFilterArrayQuery(ctx, excludeMap, queryParams.HttpRoute, constants.HttpRoute, &query, args) + } + if len(queryParams.HttpCode) > 0 { + args = buildFilterArrayQuery(ctx, excludeMap, queryParams.HttpCode, constants.HttpCode, &query, args) + } + if len(queryParams.HttpHost) > 0 { + args = buildFilterArrayQuery(ctx, excludeMap, queryParams.HttpHost, constants.HttpHost, &query, args) + } + if len(queryParams.HttpMethod) > 0 { + args = buildFilterArrayQuery(ctx, excludeMap, queryParams.HttpMethod, constants.HttpMethod, &query, args) + } + if len(queryParams.HttpUrl) > 0 { + args = buildFilterArrayQuery(ctx, excludeMap, queryParams.HttpUrl, constants.HttpUrl, &query, args) + } + if len(queryParams.Component) > 0 { + args = buildFilterArrayQuery(ctx, excludeMap, queryParams.Component, constants.Component, &query, args) + } + if len(queryParams.Operation) > 0 { + args = buildFilterArrayQuery(ctx, excludeMap, queryParams.Operation, constants.OperationDB, &query, args) + } + if len(queryParams.MinDuration) != 0 { + query = query + " AND durationNano >= ?" + args = append(args, queryParams.MinDuration) + } + if len(queryParams.MaxDuration) != 0 { + query = query + " AND durationNano <= ?" + args = append(args, queryParams.MaxDuration) + } + + query = getStatusFilters(query, queryParams.Status, excludeMap) + + tagValues := []model.TagValues{} + + finalQuery := fmt.Sprintf(`SELECT tagMap[?] as tagValues FROM %s WHERE timestamp >= ? AND timestamp <= ?`, r.indexTable) + finalQuery += query + fmt.Println(finalQuery) + finalQuery += "GROUP BY tagMap[?]" + args = append(args, queryParams.TagKey) + err := r.db.Select(&tagValues, finalQuery, args...) + + zap.S().Info(query) + + if err != nil { + zap.S().Debug("Error in processing sql query: ", err) + return nil, &model.ApiError{model.ErrorExec, fmt.Errorf("Error in processing sql query")} + } + + cleanedTagValues := []model.TagValues{} + for _, e := range tagValues { + if e.TagValues != "" { + cleanedTagValues = append(cleanedTagValues, e) + } + } + return &cleanedTagValues, nil +} + func (r *ClickHouseReader) GetServiceDBOverview(ctx context.Context, queryParams *model.GetServiceOverviewParams) (*[]model.ServiceDBOverviewItem, error) { var serviceDBOverviewItems []model.ServiceDBOverviewItem diff --git a/pkg/query-service/app/druidReader/reader.go b/pkg/query-service/app/druidReader/reader.go index bd44ad2670..de390d98e2 100644 --- a/pkg/query-service/app/druidReader/reader.go +++ b/pkg/query-service/app/druidReader/reader.go @@ -173,6 +173,10 @@ func (druid *DruidReader) GetTagFilters(_ context.Context, _ *model.TagFilterPar return nil, &model.ApiError{model.ErrorNotImplemented, fmt.Errorf("druid does not support getting tagFilters")} } +func (druid *DruidReader) GetTagValues(_ context.Context, _ *model.TagFilterParams) (*[]model.TagValues, *model.ApiError) { + return nil, &model.ApiError{model.ErrorNotImplemented, fmt.Errorf("druid does not support getting tagValues")} +} + func (druid *DruidReader) GetFilteredSpans(_ context.Context, _ *model.GetFilteredSpansParams) (*model.GetFilterSpansResponse, *model.ApiError) { return nil, &model.ApiError{model.ErrorNotImplemented, fmt.Errorf("druid does not support getting FilteredSpans")} } diff --git a/pkg/query-service/app/http_handler.go b/pkg/query-service/app/http_handler.go index d76e8c6ca1..54e740577f 100644 --- a/pkg/query-service/app/http_handler.go +++ b/pkg/query-service/app/http_handler.go @@ -214,6 +214,7 @@ func (aH *APIHandler) RegisterRoutes(router *mux.Router) { router.HandleFunc("/api/v1/getFilteredSpans", aH.getFilteredSpans).Methods(http.MethodPost) router.HandleFunc("/api/v1/getFilteredSpans/aggregates", aH.getFilteredSpanAggregates).Methods(http.MethodPost) + router.HandleFunc("/api/v1/getTagValues", aH.getTagValues).Methods(http.MethodPost) router.HandleFunc("/api/v1/errors", aH.getErrors).Methods(http.MethodGet) router.HandleFunc("/api/v1/errorWithId", aH.getErrorForId).Methods(http.MethodGet) router.HandleFunc("/api/v1/errorWithType", aH.getErrorForType).Methods(http.MethodGet) @@ -1040,6 +1041,22 @@ func (aH *APIHandler) getTagFilters(w http.ResponseWriter, r *http.Request) { aH.writeJSON(w, r, result) } +func (aH *APIHandler) getTagValues(w http.ResponseWriter, r *http.Request) { + + query, err := parseTagValueRequest(r) + if aH.handleError(w, err, http.StatusBadRequest) { + return + } + + result, apiErr := (*aH.reader).GetTagValues(context.Background(), query) + + if apiErr != nil && aH.handleError(w, apiErr.Err, http.StatusInternalServerError) { + return + } + + aH.writeJSON(w, r, result) +} + func (aH *APIHandler) setTTL(w http.ResponseWriter, r *http.Request) { ttlParams, err := parseDuration(r) if aH.handleError(w, err, http.StatusBadRequest) { diff --git a/pkg/query-service/app/interface.go b/pkg/query-service/app/interface.go index de5bdec35b..158a900215 100644 --- a/pkg/query-service/app/interface.go +++ b/pkg/query-service/app/interface.go @@ -39,6 +39,7 @@ type Reader interface { GetTTL(ctx context.Context, ttlParams *model.GetTTLParams) (*model.GetTTLResponseItem, *model.ApiError) GetSpanFilters(ctx context.Context, query *model.SpanFilterParams) (*model.SpanFiltersResponse, *model.ApiError) GetTagFilters(ctx context.Context, query *model.TagFilterParams) (*[]model.TagFilters, *model.ApiError) + GetTagValues(ctx context.Context, query *model.TagFilterParams) (*[]model.TagValues, *model.ApiError) GetFilteredSpans(ctx context.Context, query *model.GetFilteredSpansParams) (*model.GetFilterSpansResponse, *model.ApiError) GetFilteredSpansAggregates(ctx context.Context, query *model.GetFilteredSpanAggregatesParams) (*model.GetFilteredSpansAggregatesResponse, *model.ApiError) diff --git a/pkg/query-service/app/parser.go b/pkg/query-service/app/parser.go index 89d1a6c07f..b329c85a34 100644 --- a/pkg/query-service/app/parser.go +++ b/pkg/query-service/app/parser.go @@ -650,6 +650,31 @@ func parseTagFilterRequest(r *http.Request) (*model.TagFilterParams, error) { return postData, nil } + +func parseTagValueRequest(r *http.Request) (*model.TagFilterParams, error) { + var postData *model.TagFilterParams + err := json.NewDecoder(r.Body).Decode(&postData) + + if err != nil { + return nil, err + } + if postData.TagKey == "" { + return nil, fmt.Errorf("%s param missing in query", postData.TagKey) + } + + postData.Start, err = parseTimeStr(postData.StartStr, "start") + if err != nil { + return nil, err + } + postData.End, err = parseTimeMinusBufferStr(postData.EndStr, "end") + if err != nil { + return nil, err + } + + return postData, nil + +} + func parseErrorsRequest(r *http.Request) (*model.GetErrorsParams, error) { startTime, err := parseTime("start", r) diff --git a/pkg/query-service/model/queryParams.go b/pkg/query-service/model/queryParams.go index 8ceaddd9a6..d5ba693855 100644 --- a/pkg/query-service/model/queryParams.go +++ b/pkg/query-service/model/queryParams.go @@ -201,6 +201,7 @@ type TagFilterParams struct { MaxDuration string `json:"maxDuration"` StartStr string `json:"start"` EndStr string `json:"end"` + TagKey string `json:"tagKey"` Start *time.Time End *time.Time } diff --git a/pkg/query-service/model/response.go b/pkg/query-service/model/response.go index d3e15490f1..67fea82df8 100644 --- a/pkg/query-service/model/response.go +++ b/pkg/query-service/model/response.go @@ -267,6 +267,10 @@ type TagItem struct { type TagFilters struct { TagKeys string `json:"tagKeys" db:"tagKeys"` } + +type TagValues struct { + TagValues string `json:"tagValues" db:"tagValues"` +} type ServiceMapDependencyResponseItem struct { Parent string `json:"parent,omitempty" db:"parent,omitempty"` Child string `json:"child,omitempty" db:"child,omitempty"` From 0d98a4fd0c46598509e115021418749882de7a75 Mon Sep 17 00:00:00 2001 From: Palash gupta Date: Thu, 10 Feb 2022 22:00:35 +0530 Subject: [PATCH 06/28] bug: useDebounce function is fixed --- frontend/src/hooks/useDebouncedFunction.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/frontend/src/hooks/useDebouncedFunction.ts b/frontend/src/hooks/useDebouncedFunction.ts index 4a26fbc46f..e63b8c6021 100644 --- a/frontend/src/hooks/useDebouncedFunction.ts +++ b/frontend/src/hooks/useDebouncedFunction.ts @@ -1,4 +1,4 @@ -import { useCallback } from 'react'; +import { useMemo, useRef } from 'react'; import debounce from 'lodash-es/debounce'; export interface DebouncedFunc any> { @@ -26,9 +26,13 @@ const useDebouncedFn = any>( options: DebounceOptions = defaultOptions, dependencies?: ReadonlyArray, ): DebouncedFunc => { - const debounced = debounce(fn, wait, options); + const fnRef = useRef(fn); + fnRef.current = fn; - return useCallback(debounced, dependencies || []); + return useMemo( + () => debounce(((...args) => fnRef.current(...args)) as T, wait, options), + [...(dependencies || [])], + ); }; export default useDebouncedFn; From bad14a7d09380d91558452e7902f067a3f85f656 Mon Sep 17 00:00:00 2001 From: Palash gupta Date: Sat, 12 Feb 2022 15:01:38 +0530 Subject: [PATCH 07/28] feat: slack community link is updated --- frontend/src/container/SideNav/Slack.tsx | 48 ++++++++++++++++++++++++ frontend/src/container/SideNav/index.tsx | 17 ++++++++- frontend/src/container/SideNav/styles.ts | 17 ++++++++- 3 files changed, 79 insertions(+), 3 deletions(-) create mode 100644 frontend/src/container/SideNav/Slack.tsx diff --git a/frontend/src/container/SideNav/Slack.tsx b/frontend/src/container/SideNav/Slack.tsx new file mode 100644 index 0000000000..d0cc536e38 --- /dev/null +++ b/frontend/src/container/SideNav/Slack.tsx @@ -0,0 +1,48 @@ +import React from 'react'; + +const Slack = (): JSX.Element => { + return ( + + + + + + + + + + + ); +}; + +export default Slack; diff --git a/frontend/src/container/SideNav/index.tsx b/frontend/src/container/SideNav/index.tsx index c96e46b18d..64da5b5a44 100644 --- a/frontend/src/container/SideNav/index.tsx +++ b/frontend/src/container/SideNav/index.tsx @@ -1,5 +1,5 @@ import { Menu, Typography } from 'antd'; -import { ToggleButton } from './styles'; +import { MenuItem, SlackButton, ToggleButton } from './styles'; import ROUTES from 'constants/routes'; import history from 'lib/history'; import React, { useCallback, useState } from 'react'; @@ -17,6 +17,7 @@ import setTheme from 'lib/theme/setTheme'; import menus from './menuItems'; import { Logo, Sider, ThemeSwitcherWrapper } from './styles'; +import Slack from './Slack'; const SideNav = ({ toggleDarkMode }: Props): JSX.Element => { const [collapsed, setCollapsed] = useState(false); @@ -57,10 +58,18 @@ const SideNav = ({ toggleDarkMode }: Props): JSX.Element => { [pathname], ); + const onClickSlackHandler = () => { + window.open('https://signoz.io/slack', '_blank'); + }; + return ( - + @@ -81,6 +90,10 @@ const SideNav = ({ toggleDarkMode }: Props): JSX.Element => { {name} ))} + + }> + Slack + ); diff --git a/frontend/src/container/SideNav/styles.ts b/frontend/src/container/SideNav/styles.ts index 11583359e1..47d452f55d 100644 --- a/frontend/src/container/SideNav/styles.ts +++ b/frontend/src/container/SideNav/styles.ts @@ -1,4 +1,4 @@ -import { Layout, Switch } from 'antd'; +import { Layout, Menu, Switch, Typography } from 'antd'; import styled from 'styled-components'; const { Sider: SiderComponent } = Layout; @@ -36,3 +36,18 @@ export const ToggleButton = styled(Switch)` } `; +export const SlackButton = styled(Typography)` + &&& { + margin-left: 1rem; + } +`; + +export const MenuItem = styled(Menu.Item)` + &&& { + position: fixed; + bottom: 48px; + width: 100%; + height: 48px; + background: #262626; + } +`; From 31f0a9f0b6eb6df54b95c5b07c605ec53648f14a Mon Sep 17 00:00:00 2001 From: Palash gupta Date: Sat, 12 Feb 2022 15:17:40 +0530 Subject: [PATCH 08/28] feat: slack community link is updated --- frontend/src/container/SideNav/index.tsx | 15 ++++++++++---- frontend/src/container/SideNav/styles.ts | 25 +++++++++++++++++++++++- 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/frontend/src/container/SideNav/index.tsx b/frontend/src/container/SideNav/index.tsx index 64da5b5a44..472ee6f2ae 100644 --- a/frontend/src/container/SideNav/index.tsx +++ b/frontend/src/container/SideNav/index.tsx @@ -1,5 +1,10 @@ import { Menu, Typography } from 'antd'; -import { MenuItem, SlackButton, ToggleButton } from './styles'; +import { + MenuItem, + SlackButton, + SlackMenuItemContainer, + ToggleButton, +} from './styles'; import ROUTES from 'constants/routes'; import history from 'lib/history'; import React, { useCallback, useState } from 'react'; @@ -91,9 +96,11 @@ const SideNav = ({ toggleDarkMode }: Props): JSX.Element => { ))} - }> - Slack - + + }> + Slack + + ); diff --git a/frontend/src/container/SideNav/styles.ts b/frontend/src/container/SideNav/styles.ts index 47d452f55d..a4790e84a0 100644 --- a/frontend/src/container/SideNav/styles.ts +++ b/frontend/src/container/SideNav/styles.ts @@ -1,5 +1,5 @@ import { Layout, Menu, Switch, Typography } from 'antd'; -import styled from 'styled-components'; +import styled, { css } from 'styled-components'; const { Sider: SiderComponent } = Layout; export const ThemeSwitcherWrapper = styled.div` @@ -51,3 +51,26 @@ export const MenuItem = styled(Menu.Item)` background: #262626; } `; + +export const SlackMenuItemContainer = styled.div` + &&& { + li { + ${({ collapsed }) => + collapsed && + css` + padding-left: 24px; + `} + } + + svg { + margin-left: ${({ collapsed }) => (collapsed ? '0' : '24px')}; + + ${({ collapsed }) => + collapsed && + css` + height: 100%; + margin: 0 auto; + `} + } + } +`; From 567c81c0f9bf646e123513df3333ab8384a80883 Mon Sep 17 00:00:00 2001 From: Palash gupta Date: Sun, 13 Feb 2022 12:05:20 +0530 Subject: [PATCH 09/28] chore:button text is updated --- frontend/src/container/SideNav/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/container/SideNav/index.tsx b/frontend/src/container/SideNav/index.tsx index 472ee6f2ae..6e203d4ab2 100644 --- a/frontend/src/container/SideNav/index.tsx +++ b/frontend/src/container/SideNav/index.tsx @@ -98,7 +98,7 @@ const SideNav = ({ toggleDarkMode }: Props): JSX.Element => { }> - Slack + Support From 00cefe230614aef88b790a9ab4c1e2f027846792 Mon Sep 17 00:00:00 2001 From: Palash gupta Date: Wed, 16 Feb 2022 08:13:54 +0530 Subject: [PATCH 10/28] bug: clear all now moves with selected filter rather than user selected filter --- .../src/container/Trace/Filters/Panel/PanelHeading/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/container/Trace/Filters/Panel/PanelHeading/index.tsx b/frontend/src/container/Trace/Filters/Panel/PanelHeading/index.tsx index 96fc5d5dc7..785362c25c 100644 --- a/frontend/src/container/Trace/Filters/Panel/PanelHeading/index.tsx +++ b/frontend/src/container/Trace/Filters/Panel/PanelHeading/index.tsx @@ -164,7 +164,7 @@ const PanelHeading = (props: PanelHeadingProps): JSX.Element => { end: String(global.maxTime), start: String(global.minTime), getFilters: filterToFetchData, - other: Object.fromEntries(preUserSelected), + other: Object.fromEntries(updatedFilter), isFilterExclude: postIsFilterExclude, }); From 5405f0d9edcdf3a116f51c3659c622c755021e0e Mon Sep 17 00:00:00 2001 From: Palash gupta Date: Wed, 16 Feb 2022 09:00:41 +0530 Subject: [PATCH 11/28] chore: initial response for the trace api is added --- .../fixtures/trace/initialAggregates.json | 35 ++++++ .../fixtures/trace/initialSpanFilter.json | 19 ++++ .../cypress/fixtures/trace/initialSpans.json | 105 ++++++++++++++++++ 3 files changed, 159 insertions(+) create mode 100644 frontend/cypress/fixtures/trace/initialAggregates.json create mode 100644 frontend/cypress/fixtures/trace/initialSpanFilter.json create mode 100644 frontend/cypress/fixtures/trace/initialSpans.json diff --git a/frontend/cypress/fixtures/trace/initialAggregates.json b/frontend/cypress/fixtures/trace/initialAggregates.json new file mode 100644 index 0000000000..b029e9de64 --- /dev/null +++ b/frontend/cypress/fixtures/trace/initialAggregates.json @@ -0,0 +1,35 @@ +{ + "items": { + "1644926280000000000": { "timestamp": 1644926280000000000, "value": 787 }, + "1644926340000000000": { "timestamp": 1644926340000000000, "value": 2798 }, + "1644926400000000000": { "timestamp": 1644926400000000000, "value": 2828 }, + "1644926460000000000": { "timestamp": 1644926460000000000, "value": 2926 }, + "1644926520000000000": { "timestamp": 1644926520000000000, "value": 2932 }, + "1644926580000000000": { "timestamp": 1644926580000000000, "value": 2842 }, + "1644926640000000000": { "timestamp": 1644926640000000000, "value": 2966 }, + "1644926700000000000": { "timestamp": 1644926700000000000, "value": 2782 }, + "1644926760000000000": { "timestamp": 1644926760000000000, "value": 2843 }, + "1644926820000000000": { "timestamp": 1644926820000000000, "value": 2864 }, + "1644926880000000000": { "timestamp": 1644926880000000000, "value": 2777 }, + "1644926940000000000": { "timestamp": 1644926940000000000, "value": 2820 }, + "1644927000000000000": { "timestamp": 1644927000000000000, "value": 2579 }, + "1644927060000000000": { "timestamp": 1644927060000000000, "value": 2681 }, + "1644927120000000000": { "timestamp": 1644927120000000000, "value": 2828 }, + "1644927180000000000": { "timestamp": 1644927180000000000, "value": 2975 }, + "1644927240000000000": { "timestamp": 1644927240000000000, "value": 2934 }, + "1644927300000000000": { "timestamp": 1644927300000000000, "value": 2793 }, + "1644927360000000000": { "timestamp": 1644927360000000000, "value": 2913 }, + "1644927420000000000": { "timestamp": 1644927420000000000, "value": 2621 }, + "1644927480000000000": { "timestamp": 1644927480000000000, "value": 2631 }, + "1644927540000000000": { "timestamp": 1644927540000000000, "value": 2924 }, + "1644927600000000000": { "timestamp": 1644927600000000000, "value": 2576 }, + "1644927660000000000": { "timestamp": 1644927660000000000, "value": 2878 }, + "1644927720000000000": { "timestamp": 1644927720000000000, "value": 2737 }, + "1644927780000000000": { "timestamp": 1644927780000000000, "value": 2621 }, + "1644927840000000000": { "timestamp": 1644927840000000000, "value": 2823 }, + "1644927900000000000": { "timestamp": 1644927900000000000, "value": 3081 }, + "1644927960000000000": { "timestamp": 1644927960000000000, "value": 2883 }, + "1644928020000000000": { "timestamp": 1644928020000000000, "value": 2823 }, + "1644928080000000000": { "timestamp": 1644928080000000000, "value": 455 } + } +} diff --git a/frontend/cypress/fixtures/trace/initialSpanFilter.json b/frontend/cypress/fixtures/trace/initialSpanFilter.json new file mode 100644 index 0000000000..26bed66ae9 --- /dev/null +++ b/frontend/cypress/fixtures/trace/initialSpanFilter.json @@ -0,0 +1,19 @@ +{ + "serviceName": { + "customer": 1642, + "driver": 1642, + "frontend": 39408, + "mysql": 1642, + "redis": 22167, + "route": 16420 + }, + "status": { "error": 4105, "ok": 78816 }, + "duration": { "maxDuration": 1253979000, "minDuration": 415000 }, + "operation": {}, + "httpCode": {}, + "httpUrl": {}, + "httpMethod": {}, + "httpRoute": {}, + "httpHost": {}, + "component": {} +} diff --git a/frontend/cypress/fixtures/trace/initialSpans.json b/frontend/cypress/fixtures/trace/initialSpans.json new file mode 100644 index 0000000000..9b15100752 --- /dev/null +++ b/frontend/cypress/fixtures/trace/initialSpans.json @@ -0,0 +1,105 @@ +{ + "spans": [ + { + "timestamp": "2022-02-15T12:16:09.542074Z", + "spanID": "303b39065c6f5df5", + "traceID": "00000000000000007fc49fab3cb75958", + "serviceName": "customer", + "operation": "HTTP GET /customer", + "durationNano": 313418000, + "httpCode": "200", + "httpMethod": "GET" + }, + { + "timestamp": "2022-02-15T12:16:08.84038Z", + "spanID": "557e8303bc802992", + "traceID": "000000000000000079310bd1d435a92b", + "serviceName": "customer", + "operation": "HTTP GET /customer", + "durationNano": 318203000, + "httpCode": "200", + "httpMethod": "GET" + }, + { + "timestamp": "2022-02-15T12:16:08.867689Z", + "spanID": "347113dd916dd20e", + "traceID": "00000000000000004c22c0409cee0f66", + "serviceName": "customer", + "operation": "HTTP GET /customer", + "durationNano": 512810000, + "httpCode": "200", + "httpMethod": "GET" + }, + { + "timestamp": "2022-02-15T12:16:07.060882Z", + "spanID": "0a8d07f72aa1339b", + "traceID": "0000000000000000488e11a35959de96", + "serviceName": "customer", + "operation": "HTTP GET /customer", + "durationNano": 588705000, + "httpCode": "200", + "httpMethod": "GET" + }, + { + "timestamp": "2022-02-15T12:16:07.134107Z", + "spanID": "0acd4ec344675998", + "traceID": "00000000000000000292efc7945d9bfa", + "serviceName": "customer", + "operation": "HTTP GET /customer", + "durationNano": 801632000, + "httpCode": "200", + "httpMethod": "GET" + }, + { + "timestamp": "2022-02-15T12:16:06.474095Z", + "spanID": "3ae72e433301822a", + "traceID": "00000000000000001ac3004ff1b7eefe", + "serviceName": "customer", + "operation": "HTTP GET /customer", + "durationNano": 306650000, + "httpCode": "200", + "httpMethod": "GET" + }, + { + "timestamp": "2022-02-15T12:16:06.996246Z", + "spanID": "1d765427af673039", + "traceID": "00000000000000002e78f59fabbcdecf", + "serviceName": "customer", + "operation": "HTTP GET /customer", + "durationNano": 311469000, + "httpCode": "200", + "httpMethod": "GET" + }, + { + "timestamp": "2022-02-15T12:16:05.324296Z", + "spanID": "0987c90d83298a1d", + "traceID": "0000000000000000077bcb960609a350", + "serviceName": "customer", + "operation": "HTTP GET /customer", + "durationNano": 290680000, + "httpCode": "200", + "httpMethod": "GET" + }, + { + "timestamp": "2022-02-15T12:16:02.458221Z", + "spanID": "5b0d0d403dd9acf4", + "traceID": "00000000000000007ae5b0aa69242556", + "serviceName": "customer", + "operation": "HTTP GET /customer", + "durationNano": 262763000, + "httpCode": "200", + "httpMethod": "GET" + }, + { + "timestamp": "2022-02-15T12:16:00.584939Z", + "spanID": "3beafb277a76b9b4", + "traceID": "00000000000000000ab44953c2fd949e", + "serviceName": "customer", + "operation": "HTTP GET /customer", + "durationNano": 302851000, + "httpCode": "200", + "httpMethod": "GET" + } + ], + "totalSpans": 82921 +} From a07b8999c0f0c745678dec42d9000772e2995cd8 Mon Sep 17 00:00:00 2001 From: Palash gupta Date: Wed, 16 Feb 2022 09:27:06 +0530 Subject: [PATCH 12/28] test: initial test is updated --- .../cypress/integration/trace/index.spec.ts | 126 ++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 frontend/cypress/integration/trace/index.spec.ts diff --git a/frontend/cypress/integration/trace/index.spec.ts b/frontend/cypress/integration/trace/index.spec.ts new file mode 100644 index 0000000000..82ac93f104 --- /dev/null +++ b/frontend/cypress/integration/trace/index.spec.ts @@ -0,0 +1,126 @@ +import ROUTES from 'constants/routes'; +import { TraceFilterEnum } from 'types/reducer/trace'; +import TableInitialResponse from '../../fixtures/trace/initialSpans.json'; +import FilterInitialResponse from '../../fixtures/trace/initialSpanFilter.json'; +import GraphInitialResponse from '../../fixtures/trace/initialAggregates.json'; +import { AppState } from 'store/reducers'; + +describe('Trace', () => { + beforeEach(() => { + window.localStorage.setItem('isLoggedIn', 'yes'); + + cy + .intercept('POST', '**/aggregates', { + fixture: 'trace/initialAggregates', + }) + .as('Graph'); + + cy + .intercept('POST', '**/getFilteredSpans', { + fixture: 'trace/initialSpans', + }) + .as('Table'); + + cy + .intercept('POST', '**/api/v1/getSpanFilters', { + fixture: 'trace/initialSpanFilter', + }) + .as('Filters'); + + cy.visit(Cypress.env('baseUrl') + `${ROUTES.TRACE}`); + }); + + // it('First Initial Load should go with 3 AJAX request', () => { + // cy.wait(['@Filters', '@Graph', '@Table']).then((e) => { + // const [filter, graph, table] = e; + + // const { body: filterBody } = filter.request; + // const { body: graphBody } = graph.request; + // const { body: tableBody } = table.request; + + // expect(filterBody.exclude.length).to.equal(0); + // expect(filterBody.getFilters.length).to.equal(3); + // filterBody.getFilters.forEach((filter: TraceFilterEnum) => { + // expect(filter).to.be.oneOf(['duration', 'status', 'serviceName']); + // }); + + // expect(graphBody.function).to.be.equal('count'); + // expect(graphBody.exclude.length).to.be.equal(0); + // expect(typeof graphBody.exclude).to.be.equal('object'); + + // expect(tableBody.tags.length).to.be.equal(0); + // expect(typeof tableBody.tags).equal('object'); + + // expect(tableBody.exclude.length).equals(0); + // }); + // }); + + // it('Render Time Request Response In All 3 Request', () => { + // cy.wait(['@Filters', '@Graph', '@Table']).then((e) => { + // const [filter, graph, table] = e; + + // expect(filter.response?.body).to.be.not.undefined; + // expect(filter.response?.body).to.be.not.NaN; + + // expect(JSON.stringify(filter.response?.body)).to.be.equals( + // JSON.stringify(FilterInitialResponse), + // ); + + // expect(JSON.stringify(graph.response?.body)).to.be.equals( + // JSON.stringify(GraphInitialResponse), + // ); + + // expect(JSON.stringify(table.response?.body)).to.be.equals( + // JSON.stringify(TableInitialResponse), + // ); + // }); + // cy.get('@Filters.all').should('have.length', 1); + // cy.get('@Graph.all').should('have.length', 1); + // cy.get('@Table.all').should('have.length', 1); + // }); + + // it('Clear All', () => { + // cy.wait(['@Filters', '@Graph', '@Table']); + + // expect(cy.findAllByText('Clear All')).not.to.be.undefined; + + // cy + // .window() + // .its('store') + // .invoke('getState') + // .then((e: AppState) => { + // const { traces } = e; + // expect(traces.isFilterExclude.get('status')).to.be.undefined; + // expect(traces.selectedFilter.size).to.be.equals(0); + // }); + + // cy.findAllByText('Clear All').then((e) => { + // const [firstStatusClear] = e; + + // firstStatusClear.click(); + + // cy.wait(['@Filters', '@Graph', '@Table']); + + // // insuring the api get call + // cy.get('@Filters.all').should('have.length', 2); + // cy.get('@Graph.all').should('have.length', 2); + // cy.get('@Table.all').should('have.length', 2); + + // cy + // .window() + // .its('store') + // .invoke('getState') + // .then((e: AppState) => { + // const { traces } = e; + + // expect(traces.isFilterExclude.get('status')).to.be.equals(false); + // expect(traces.userSelectedFilter.get('status')).to.be.undefined; + // expect(traces.selectedFilter.size).to.be.equals(0); + // }); + // }); + // }); + + it('Un Selecting one option from status', () => { + cy.wait(['@Filters', '@Graph', '@Table']); + }); +}); From 0514c5035e1f278090515f5604ff0e10ea511e39 Mon Sep 17 00:00:00 2001 From: Palash gupta Date: Wed, 16 Feb 2022 14:20:48 +0530 Subject: [PATCH 13/28] test: trace test is updated --- .../cypress/integration/trace/index.spec.ts | 168 ++++++++++-------- 1 file changed, 98 insertions(+), 70 deletions(-) diff --git a/frontend/cypress/integration/trace/index.spec.ts b/frontend/cypress/integration/trace/index.spec.ts index 82ac93f104..3ca79ecdce 100644 --- a/frontend/cypress/integration/trace/index.spec.ts +++ b/frontend/cypress/integration/trace/index.spec.ts @@ -30,97 +30,125 @@ describe('Trace', () => { cy.visit(Cypress.env('baseUrl') + `${ROUTES.TRACE}`); }); - // it('First Initial Load should go with 3 AJAX request', () => { - // cy.wait(['@Filters', '@Graph', '@Table']).then((e) => { - // const [filter, graph, table] = e; + it('First Initial Load should go with 3 AJAX request', () => { + cy.wait(['@Filters', '@Graph', '@Table']).then((e) => { + const [filter, graph, table] = e; - // const { body: filterBody } = filter.request; - // const { body: graphBody } = graph.request; - // const { body: tableBody } = table.request; + const { body: filterBody } = filter.request; + const { body: graphBody } = graph.request; + const { body: tableBody } = table.request; - // expect(filterBody.exclude.length).to.equal(0); - // expect(filterBody.getFilters.length).to.equal(3); - // filterBody.getFilters.forEach((filter: TraceFilterEnum) => { - // expect(filter).to.be.oneOf(['duration', 'status', 'serviceName']); - // }); + expect(filterBody.exclude.length).to.equal(0); + expect(filterBody.getFilters.length).to.equal(3); + filterBody.getFilters.forEach((filter: TraceFilterEnum) => { + expect(filter).to.be.oneOf(['duration', 'status', 'serviceName']); + }); - // expect(graphBody.function).to.be.equal('count'); - // expect(graphBody.exclude.length).to.be.equal(0); - // expect(typeof graphBody.exclude).to.be.equal('object'); + expect(graphBody.function).to.be.equal('count'); + expect(graphBody.exclude.length).to.be.equal(0); + expect(typeof graphBody.exclude).to.be.equal('object'); - // expect(tableBody.tags.length).to.be.equal(0); - // expect(typeof tableBody.tags).equal('object'); + expect(tableBody.tags.length).to.be.equal(0); + expect(typeof tableBody.tags).equal('object'); - // expect(tableBody.exclude.length).equals(0); - // }); - // }); + expect(tableBody.exclude.length).equals(0); + }); + }); - // it('Render Time Request Response In All 3 Request', () => { - // cy.wait(['@Filters', '@Graph', '@Table']).then((e) => { - // const [filter, graph, table] = e; + it('Render Time Request Response In All 3 Request', () => { + cy.wait(['@Filters', '@Graph', '@Table']).then((e) => { + const [filter, graph, table] = e; - // expect(filter.response?.body).to.be.not.undefined; - // expect(filter.response?.body).to.be.not.NaN; + expect(filter.response?.body).to.be.not.undefined; + expect(filter.response?.body).to.be.not.NaN; - // expect(JSON.stringify(filter.response?.body)).to.be.equals( - // JSON.stringify(FilterInitialResponse), - // ); + expect(JSON.stringify(filter.response?.body)).to.be.equals( + JSON.stringify(FilterInitialResponse), + ); - // expect(JSON.stringify(graph.response?.body)).to.be.equals( - // JSON.stringify(GraphInitialResponse), - // ); + expect(JSON.stringify(graph.response?.body)).to.be.equals( + JSON.stringify(GraphInitialResponse), + ); - // expect(JSON.stringify(table.response?.body)).to.be.equals( - // JSON.stringify(TableInitialResponse), - // ); - // }); - // cy.get('@Filters.all').should('have.length', 1); - // cy.get('@Graph.all').should('have.length', 1); - // cy.get('@Table.all').should('have.length', 1); - // }); + expect(JSON.stringify(table.response?.body)).to.be.equals( + JSON.stringify(TableInitialResponse), + ); + }); + cy.get('@Filters.all').should('have.length', 1); + cy.get('@Graph.all').should('have.length', 1); + cy.get('@Table.all').should('have.length', 1); + }); - // it('Clear All', () => { - // cy.wait(['@Filters', '@Graph', '@Table']); + it('Clear All', () => { + cy.wait(['@Filters', '@Graph', '@Table']); - // expect(cy.findAllByText('Clear All')).not.to.be.undefined; + expect(cy.findAllByText('Clear All')).not.to.be.undefined; - // cy - // .window() - // .its('store') - // .invoke('getState') - // .then((e: AppState) => { - // const { traces } = e; - // expect(traces.isFilterExclude.get('status')).to.be.undefined; - // expect(traces.selectedFilter.size).to.be.equals(0); - // }); + cy + .window() + .its('store') + .invoke('getState') + .then((e: AppState) => { + const { traces } = e; + expect(traces.isFilterExclude.get('status')).to.be.undefined; + expect(traces.selectedFilter.size).to.be.equals(0); + }); - // cy.findAllByText('Clear All').then((e) => { - // const [firstStatusClear] = e; + cy.findAllByText('Clear All').then((e) => { + const [firstStatusClear] = e; - // firstStatusClear.click(); + firstStatusClear.click(); - // cy.wait(['@Filters', '@Graph', '@Table']); + cy.wait(['@Filters', '@Graph', '@Table']); - // // insuring the api get call - // cy.get('@Filters.all').should('have.length', 2); - // cy.get('@Graph.all').should('have.length', 2); - // cy.get('@Table.all').should('have.length', 2); + // insuring the api get call + cy.get('@Filters.all').should('have.length', 2); + cy.get('@Graph.all').should('have.length', 2); + cy.get('@Table.all').should('have.length', 2); - // cy - // .window() - // .its('store') - // .invoke('getState') - // .then((e: AppState) => { - // const { traces } = e; + cy + .window() + .its('store') + .invoke('getState') + .then((e: AppState) => { + const { traces } = e; - // expect(traces.isFilterExclude.get('status')).to.be.equals(false); - // expect(traces.userSelectedFilter.get('status')).to.be.undefined; - // expect(traces.selectedFilter.size).to.be.equals(0); - // }); - // }); - // }); + expect(traces.isFilterExclude.get('status')).to.be.equals(false); + expect(traces.userSelectedFilter.get('status')).to.be.undefined; + expect(traces.selectedFilter.size).to.be.equals(0); + }); + }); + }); it('Un Selecting one option from status', () => { cy.wait(['@Filters', '@Graph', '@Table']); + + cy.get('input[type="checkbox"]').then((e) => { + const [errorCheckbox] = e; + errorCheckbox.click(); + + cy.wait(['@Filters', '@Graph', '@Table']).then((e) => { + const [filter, graph, table] = e; + const filterBody = filter.request.body; + const graphBody = graph.request.body; + const tableBody = table.request.body; + + expect(filterBody.exclude).not.to.be.undefined; + expect(filterBody.exclude.length).not.to.be.equal(0); + expect(filterBody.exclude[0] === 'status').to.be.true; + + expect(graphBody.exclude).not.to.be.undefined; + expect(graphBody.exclude.length).not.to.be.equal(0); + expect(graphBody.exclude[0] === 'status').to.be.true; + + expect(tableBody.exclude).not.to.be.undefined; + expect(tableBody.exclude.length).not.to.be.equal(0); + expect(tableBody.exclude[0] === 'status').to.be.true; + }); + + cy.get('@Filters.all').should('have.length', 2); + cy.get('@Graph.all').should('have.length', 2); + cy.get('@Table.all').should('have.length', 2); + }); }); }); From a6da00f801945a3544f80ce63c2b28daed1a84bc Mon Sep 17 00:00:00 2001 From: Palash gupta Date: Wed, 16 Feb 2022 15:36:20 +0530 Subject: [PATCH 14/28] test: trace test is updated --- .../cypress/CustomFunctions/uncaughtExpection.ts | 14 ++++++++++++++ frontend/src/container/Trace/Graph/index.tsx | 2 +- .../src/container/Trace/TraceGraphFilter/index.tsx | 2 ++ 3 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 frontend/cypress/CustomFunctions/uncaughtExpection.ts diff --git a/frontend/cypress/CustomFunctions/uncaughtExpection.ts b/frontend/cypress/CustomFunctions/uncaughtExpection.ts new file mode 100644 index 0000000000..341ddd8cee --- /dev/null +++ b/frontend/cypress/CustomFunctions/uncaughtExpection.ts @@ -0,0 +1,14 @@ +const resizeObserverLoopErrRe = /ResizeObserver loop limit exceeded/; + +const unCaughtExpection = () => { + cy.on('uncaught:exception', (err) => { + if (resizeObserverLoopErrRe.test(err.message)) { + // returning false here prevents Cypress from + // failing the test + return false; + } + return true; + }); +}; + +export default unCaughtExpection; diff --git a/frontend/src/container/Trace/Graph/index.tsx b/frontend/src/container/Trace/Graph/index.tsx index a91fe78930..efc8a9d137 100644 --- a/frontend/src/container/Trace/Graph/index.tsx +++ b/frontend/src/container/Trace/Graph/index.tsx @@ -40,7 +40,7 @@ const TraceGraph = () => { return ( - + ); }; diff --git a/frontend/src/container/Trace/TraceGraphFilter/index.tsx b/frontend/src/container/Trace/TraceGraphFilter/index.tsx index bd06764aad..e6aad7374a 100644 --- a/frontend/src/container/Trace/TraceGraphFilter/index.tsx +++ b/frontend/src/container/Trace/TraceGraphFilter/index.tsx @@ -56,6 +56,7 @@ const TraceGraphFilter = () => { selectedFunction === e.key)?.displayValue} onChange={onClickSelectedFunctionHandler} > @@ -69,6 +70,7 @@ const TraceGraphFilter = () => { selectedGroupBy === e.key)?.displayValue} onChange={onClickSelectedGroupByHandler} > From 05c79b71190decb76bee79e535ef3251090a0cd7 Mon Sep 17 00:00:00 2001 From: Pranay Prateek Date: Sun, 20 Feb 2022 18:03:54 +0530 Subject: [PATCH 15/28] Update .gitpod.yml --- .gitpod.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitpod.yml b/.gitpod.yml index db4801ba35..1771de8779 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -11,7 +11,7 @@ tasks: - name: Run Docker Images init: | cd ./deploy - sudo docker-compose --env-file ./docker/clickhouse-setup/env/x86_64.env -f docker/clickhouse-setup/docker-compose.yaml up -d + sudo docker-compose -f docker/clickhouse-setup/docker-compose.yaml up -d # command: - name: Run Frontend @@ -22,7 +22,7 @@ tasks: yarn dev ports: - - port: 3000 + - port: 3301 onOpen: open-browser - port: 8080 onOpen: ignore From 56c9ea5430a2284c01da7da982cfd5461914232f Mon Sep 17 00:00:00 2001 From: makeavish Date: Tue, 22 Feb 2022 17:49:02 +0530 Subject: [PATCH 16/28] fix: avoid panic by handling getOutboundIP() error --- pkg/query-service/telemetry/telemetry.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkg/query-service/telemetry/telemetry.go b/pkg/query-service/telemetry/telemetry.go index 90632784e7..eaaf098cc3 100644 --- a/pkg/query-service/telemetry/telemetry.go +++ b/pkg/query-service/telemetry/telemetry.go @@ -61,6 +61,10 @@ func getOutboundIP() string { ip := []byte("NA") resp, err := http.Get("https://api.ipify.org?format=text") + if err != nil { + return "" + } + defer resp.Body.Close() if err == nil { ipBody, err := ioutil.ReadAll(resp.Body) From 3beb7f1843fde48b1131a8b044b8796ab5258932 Mon Sep 17 00:00:00 2001 From: Udasi Tharani Date: Tue, 22 Feb 2022 22:35:29 +0530 Subject: [PATCH 17/28] removing feedback fab button --- .../container/AppLayout/FeedBack/index.tsx | 127 ------------------ .../container/AppLayout/FeedBack/styles.ts | 64 --------- frontend/src/container/AppLayout/index.tsx | 3 - 3 files changed, 194 deletions(-) delete mode 100644 frontend/src/container/AppLayout/FeedBack/index.tsx delete mode 100644 frontend/src/container/AppLayout/FeedBack/styles.ts diff --git a/frontend/src/container/AppLayout/FeedBack/index.tsx b/frontend/src/container/AppLayout/FeedBack/index.tsx deleted file mode 100644 index 13e0279806..0000000000 --- a/frontend/src/container/AppLayout/FeedBack/index.tsx +++ /dev/null @@ -1,127 +0,0 @@ -import { CloseCircleOutlined, CommentOutlined } from '@ant-design/icons'; -import { Button, Divider, Form, Input, notification, Typography } from 'antd'; -import { Callbacks } from 'rc-field-form/lib/interface'; -import React, { useCallback, useState } from 'react'; - -import { - Button as IconButton, - ButtonContainer, - Card, - CenterText, - Container, - TitleContainer, - FormItem, -} from './styles'; -const { Title } = Typography; -const { TextArea } = Input; -import sendFeedbackApi from 'api/userFeedback/sendFeedback'; - -const Feedback = (): JSX.Element => { - const [isOpen, setisOpen] = useState(false); - const [form] = Form.useForm(); - const [isLoading, setIsLoading] = useState(false); - - const [notifications, Element] = notification.useNotification(); - - const isToggleHandler = useCallback(() => { - setisOpen((state) => !state); - }, []); - - const onFinishHandler: Callbacks['onFinish'] = async ( - value: Feedback, - ): Promise => { - try { - setIsLoading(true); - const { feedback, email = '' } = value; - - const response = await sendFeedbackApi({ - email, - message: feedback, - }); - - if (response === 200) { - notifications.success({ - message: 'Thanks for your feedback!', - description: - 'We have noted down your feedback and will work on improving SIgNoz based on that!', - }); - - isToggleHandler(); - } else { - notifications.error({ - message: 'Error!', - description: 'Something went wrong', - }); - } - setIsLoading(false); - } catch (error) { - notifications.error({ - message: 'Something went wrong', - }); - setIsLoading(false); - } - }; - - return ( - - {!isOpen && ( - - - - )} - - {Element} - - {isOpen && ( -
- - - - How can we improve SigNoz? - - - - - - - -