From efeb6588962bad9415ff334e33b3d51616a37ffd Mon Sep 17 00:00:00 2001 From: nolouch Date: Wed, 7 Feb 2024 02:39:32 +0800 Subject: [PATCH] feat(statements): support slow query search by resource group Signed-off-by: nolouch --- pkg/apiserver/statement/queries.go | 6 +++- pkg/apiserver/statement/service.go | 15 ++++---- .../src/client/api/api/default-api.ts | 26 ++++++++++---- .../statement-get-statements-request.ts | 6 ++++ .../tidb-dashboard-client/swagger/spec.json | 15 ++++++++ .../src/apps/Statement/context.ts | 2 ++ .../src/apps/Statement/context.ts | 2 ++ .../src/apps/SlowQuery/pages/List/index.tsx | 3 +- .../src/apps/Statement/context/index.ts | 2 ++ .../src/apps/Statement/pages/List/index.tsx | 35 ++++++++++++++++++- .../src/apps/Statement/translations/en.yaml | 4 +++ .../src/apps/Statement/translations/zh.yaml | 4 +++ .../utils/useStatementTableController.ts | 24 +++++++++++++ .../tidb-dashboard-lib/src/client/models.ts | 6 ++++ 14 files changed, 135 insertions(+), 15 deletions(-) diff --git a/pkg/apiserver/statement/queries.go b/pkg/apiserver/statement/queries.go index 65f375ad7a..16deb6a0a3 100644 --- a/pkg/apiserver/statement/queries.go +++ b/pkg/apiserver/statement/queries.go @@ -38,7 +38,7 @@ func queryStmtTypes(db *gorm.DB) (result []string, err error) { func (s *Service) queryStatements( db *gorm.DB, beginTime, endTime int, - schemas, stmtTypes []string, + schemas, resourceGroups, stmtTypes []string, text string, reqFields []string, ) (result []Model, err error) { @@ -69,6 +69,10 @@ func (s *Service) queryStatements( query = query.Where("table_names REGEXP ?", regexAll) } + if len(resourceGroups) > 0 { + query = query.Where("resource_group in (?)", resourceGroups) + } + if len(stmtTypes) > 0 { query = query.Where("stmt_type in (?)", stmtTypes) } diff --git a/pkg/apiserver/statement/service.go b/pkg/apiserver/statement/service.go index e89bb9131d..64169b7246 100644 --- a/pkg/apiserver/statement/service.go +++ b/pkg/apiserver/statement/service.go @@ -141,12 +141,13 @@ func (s *Service) stmtTypesHandler(c *gin.Context) { } type GetStatementsRequest struct { - Schemas []string `json:"schemas" form:"schemas"` - StmtTypes []string `json:"stmt_types" form:"stmt_types"` - BeginTime int `json:"begin_time" form:"begin_time"` - EndTime int `json:"end_time" form:"end_time"` - Text string `json:"text" form:"text"` - Fields string `json:"fields" form:"fields"` + Schemas []string `json:"schemas" form:"schemas"` + ResourceGroups []string `json:"resource_groups" form:"resource_groups"` + StmtTypes []string `json:"stmt_types" form:"stmt_types"` + BeginTime int `json:"begin_time" form:"begin_time"` + EndTime int `json:"end_time" form:"end_time"` + Text string `json:"text" form:"text"` + Fields string `json:"fields" form:"fields"` } // @Summary Get a list of statements @@ -171,6 +172,7 @@ func (s *Service) listHandler(c *gin.Context) { db, req.BeginTime, req.EndTime, req.Schemas, + req.ResourceGroups, req.StmtTypes, req.Text, fields) @@ -360,6 +362,7 @@ func (s *Service) downloadTokenHandler(c *gin.Context) { db, req.BeginTime, req.EndTime, req.Schemas, + req.ResourceGroups, req.StmtTypes, req.Text, fields) diff --git a/ui/packages/tidb-dashboard-client/src/client/api/api/default-api.ts b/ui/packages/tidb-dashboard-client/src/client/api/api/default-api.ts index ec429bee4f..e1ea55320f 100644 --- a/ui/packages/tidb-dashboard-client/src/client/api/api/default-api.ts +++ b/ui/packages/tidb-dashboard-client/src/client/api/api/default-api.ts @@ -3144,13 +3144,14 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati * @param {number} [beginTime] * @param {number} [endTime] * @param {string} [fields] + * @param {Array} [resourceGroups] * @param {Array} [schemas] * @param {Array} [stmtTypes] * @param {string} [text] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - statementsListGet: async (beginTime?: number, endTime?: number, fields?: string, schemas?: Array, stmtTypes?: Array, text?: string, options: AxiosRequestConfig = {}): Promise => { + statementsListGet: async (beginTime?: number, endTime?: number, fields?: string, resourceGroups?: Array, schemas?: Array, stmtTypes?: Array, text?: string, options: AxiosRequestConfig = {}): Promise => { const localVarPath = `/statements/list`; // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); @@ -3178,6 +3179,10 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati localVarQueryParameter['fields'] = fields; } + if (resourceGroups) { + localVarQueryParameter['resource_groups'] = resourceGroups; + } + if (schemas) { localVarQueryParameter['schemas'] = schemas; } @@ -4945,14 +4950,15 @@ export const DefaultApiFp = function(configuration?: Configuration) { * @param {number} [beginTime] * @param {number} [endTime] * @param {string} [fields] + * @param {Array} [resourceGroups] * @param {Array} [schemas] * @param {Array} [stmtTypes] * @param {string} [text] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async statementsListGet(beginTime?: number, endTime?: number, fields?: string, schemas?: Array, stmtTypes?: Array, text?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise>> { - const localVarAxiosArgs = await localVarAxiosParamCreator.statementsListGet(beginTime, endTime, fields, schemas, stmtTypes, text, options); + async statementsListGet(beginTime?: number, endTime?: number, fields?: string, resourceGroups?: Array, schemas?: Array, stmtTypes?: Array, text?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise>> { + const localVarAxiosArgs = await localVarAxiosParamCreator.statementsListGet(beginTime, endTime, fields, resourceGroups, schemas, stmtTypes, text, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, /** @@ -5998,14 +6004,15 @@ export const DefaultApiFactory = function (configuration?: Configuration, basePa * @param {number} [beginTime] * @param {number} [endTime] * @param {string} [fields] + * @param {Array} [resourceGroups] * @param {Array} [schemas] * @param {Array} [stmtTypes] * @param {string} [text] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - statementsListGet(beginTime?: number, endTime?: number, fields?: string, schemas?: Array, stmtTypes?: Array, text?: string, options?: any): AxiosPromise> { - return localVarFp.statementsListGet(beginTime, endTime, fields, schemas, stmtTypes, text, options).then((request) => request(axios, basePath)); + statementsListGet(beginTime?: number, endTime?: number, fields?: string, resourceGroups?: Array, schemas?: Array, stmtTypes?: Array, text?: string, options?: any): AxiosPromise> { + return localVarFp.statementsListGet(beginTime, endTime, fields, resourceGroups, schemas, stmtTypes, text, options).then((request) => request(axios, basePath)); }, /** * @@ -7106,6 +7113,13 @@ export interface DefaultApiStatementsListGetRequest { */ readonly fields?: string + /** + * + * @type {Array} + * @memberof DefaultApiStatementsListGet + */ + readonly resourceGroups?: Array + /** * * @type {Array} @@ -8404,7 +8418,7 @@ export class DefaultApi extends BaseAPI { * @memberof DefaultApi */ public statementsListGet(requestParameters: DefaultApiStatementsListGetRequest = {}, options?: AxiosRequestConfig) { - return DefaultApiFp(this.configuration).statementsListGet(requestParameters.beginTime, requestParameters.endTime, requestParameters.fields, requestParameters.schemas, requestParameters.stmtTypes, requestParameters.text, options).then((request) => request(this.axios, this.basePath)); + return DefaultApiFp(this.configuration).statementsListGet(requestParameters.beginTime, requestParameters.endTime, requestParameters.fields, requestParameters.resourceGroups, requestParameters.schemas, requestParameters.stmtTypes, requestParameters.text, options).then((request) => request(this.axios, this.basePath)); } /** diff --git a/ui/packages/tidb-dashboard-client/src/client/api/models/statement-get-statements-request.ts b/ui/packages/tidb-dashboard-client/src/client/api/models/statement-get-statements-request.ts index e3bf30e085..cb9105b101 100644 --- a/ui/packages/tidb-dashboard-client/src/client/api/models/statement-get-statements-request.ts +++ b/ui/packages/tidb-dashboard-client/src/client/api/models/statement-get-statements-request.ts @@ -38,6 +38,12 @@ export interface StatementGetStatementsRequest { * @memberof StatementGetStatementsRequest */ 'fields'?: string; + /** + * + * @type {Array} + * @memberof StatementGetStatementsRequest + */ + 'resource_groups'?: Array; /** * * @type {Array} diff --git a/ui/packages/tidb-dashboard-client/swagger/spec.json b/ui/packages/tidb-dashboard-client/swagger/spec.json index be088ed271..d30a3d71fc 100644 --- a/ui/packages/tidb-dashboard-client/swagger/spec.json +++ b/ui/packages/tidb-dashboard-client/swagger/spec.json @@ -2753,6 +2753,15 @@ "name": "fields", "in": "query" }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "multi", + "name": "resource_groups", + "in": "query" + }, { "type": "array", "items": { @@ -5330,6 +5339,12 @@ "fields": { "type": "string" }, + "resource_groups": { + "type": "array", + "items": { + "type": "string" + } + }, "schemas": { "type": "array", "items": { diff --git a/ui/packages/tidb-dashboard-for-clinic-cloud/src/apps/Statement/context.ts b/ui/packages/tidb-dashboard-for-clinic-cloud/src/apps/Statement/context.ts index 2afa64756c..fa182f884c 100644 --- a/ui/packages/tidb-dashboard-for-clinic-cloud/src/apps/Statement/context.ts +++ b/ui/packages/tidb-dashboard-for-clinic-cloud/src/apps/Statement/context.ts @@ -49,6 +49,7 @@ class DataSource implements IStatementDataSource { endTime?: number, fields?: string, schemas?: Array, + resourceGroups?: Array, stmtTypes?: Array, text?: string, options?: ReqConfig @@ -59,6 +60,7 @@ class DataSource implements IStatementDataSource { endTime, fields, schemas, + resourceGroups, stmtTypes, text }, diff --git a/ui/packages/tidb-dashboard-for-op/src/apps/Statement/context.ts b/ui/packages/tidb-dashboard-for-op/src/apps/Statement/context.ts index ff46c15b61..c5baf81e4f 100644 --- a/ui/packages/tidb-dashboard-for-op/src/apps/Statement/context.ts +++ b/ui/packages/tidb-dashboard-for-op/src/apps/Statement/context.ts @@ -49,6 +49,7 @@ class DataSource implements IStatementDataSource { endTime?: number, fields?: string, schemas?: Array, + resourceGroups?: Array, stmtTypes?: Array, text?: string, options?: ReqConfig @@ -59,6 +60,7 @@ class DataSource implements IStatementDataSource { endTime, fields, schemas, + resourceGroups, stmtTypes, text }, diff --git a/ui/packages/tidb-dashboard-lib/src/apps/SlowQuery/pages/List/index.tsx b/ui/packages/tidb-dashboard-lib/src/apps/SlowQuery/pages/List/index.tsx index 1dc0b48aff..003bbf9c42 100644 --- a/ui/packages/tidb-dashboard-lib/src/apps/SlowQuery/pages/List/index.tsx +++ b/ui/packages/tidb-dashboard-lib/src/apps/SlowQuery/pages/List/index.tsx @@ -178,6 +178,7 @@ function List() { begin_time: timeRangeValue[0], end_time: timeRangeValue[1], db: controller.queryOptions.schemas, + resource_group: controller.queryOptions.groups, text: controller.queryOptions.searchText, orderBy: controller.orderOptions.orderBy, desc: controller.orderOptions.desc, @@ -243,7 +244,7 @@ function List() { /> )} {ctx!.cfg.showResourceGroupFilter && - controller.allGroups.length > 1 && ( + controller.allGroups?.length > 1 && ( , + resourceGroups?: Array, stmtTypes?: Array, text?: string, options?: ReqConfig @@ -91,6 +92,7 @@ export interface IStatementConfig extends IContextConfig { enableExport?: boolean showConfig?: boolean // default is true showDBFilter?: boolean // default is true + showResourceGroupFilter?: boolean // default is true showHelp?: boolean // default is true // control whether show statement actual time range diff --git a/ui/packages/tidb-dashboard-lib/src/apps/Statement/pages/List/index.tsx b/ui/packages/tidb-dashboard-lib/src/apps/Statement/pages/List/index.tsx index 0e9eafc8e3..3234eded30 100644 --- a/ui/packages/tidb-dashboard-lib/src/apps/Statement/pages/List/index.tsx +++ b/ui/packages/tidb-dashboard-lib/src/apps/Statement/pages/List/index.tsx @@ -98,6 +98,7 @@ export default function StatementsOverview() { cacheMgr, showFullSQL, fetchSchemas: ctx?.cfg.showDBFilter, + fetchGroups: ctx?.cfg.showResourceGroupFilter, fetchConfig: ctx?.cfg.showConfig, initialQueryOptions: { ...DEF_STMT_QUERY_OPTIONS, @@ -146,6 +147,9 @@ export default function StatementsOverview() { const [filterSchema, setFilterSchema] = useState( controller.queryOptions.schemas ) + const [filterGroup, setFilterGroup] = useState( + controller.queryOptions.groups + ) const [filterStmtType, setFilterStmtType] = useState( controller.queryOptions.stmtTypes ) @@ -158,6 +162,7 @@ export default function StatementsOverview() { controller.setQueryOptions({ timeRange, schemas: filterSchema, + groups: filterGroup, stmtTypes: filterStmtType, searchText: filterText, visibleColumnKeys @@ -179,7 +184,14 @@ export default function StatementsOverview() { return } sendQueryDebounced() - }, [timeRange, filterSchema, filterStmtType, filterText, visibleColumnKeys]) + }, [ + timeRange, + filterSchema, + filterGroup, + filterStmtType, + filterText, + visibleColumnKeys + ]) const downloadCSV = useMemoizedFn(async () => { // use last effective query options @@ -191,6 +203,7 @@ export default function StatementsOverview() { end_time: timeRangeValue[1], fields: '*', schemas: controller.queryOptions.schemas, + resource_groups: controller.queryOptions.groups, stmt_types: controller.queryOptions.stmtTypes, text: controller.queryOptions.searchText }) @@ -251,6 +264,26 @@ export default function StatementsOverview() { data-e2e="execution_database_name" /> )} + + {(ctx?.cfg.showResourceGroupFilter ?? true) && + controller.allGroups?.length > 1 && ( + { + setFilterGroup(d) + }} + items={controller.allGroups} + data-e2e="resource_group_name_select" + /> + )} ([]) + const [allGroups, setAllGroups] = useState([]) const [allStmtTypes, setAllStmtTypes] = useState([]) const [isOptionsLoading, setOptionsLoading] = useState(true) const [data, setData] = useState(undefined) @@ -217,6 +223,20 @@ export default function useStatementTableController({ } } + async function queryGroups() { + if (!fetchGroups) { + return + } + try { + const res = await ds.infoListResourceGroupNames({ + handleError: 'custom' + }) + setAllGroups(res?.data || []) + } catch (e) { + setErrors((prev) => prev.concat(e as Error)) + } + } + async function queryStmtTypes() { try { const res = await ds.statementsStmtTypesGet({ handleError: 'custom' }) @@ -233,6 +253,7 @@ export default function useStatementTableController({ await Promise.all([ queryStatementStatus(), querySchemas(), + queryGroups(), queryStmtTypes() ]) } finally { @@ -287,11 +308,13 @@ export default function useStatementTableController({ } try { + console.log('queryOptions', queryOptions) const res = await ds.statementsListGet( timeRange[0], timeRange[1], actualVisibleColumnKeys, queryOptions.schemas, + queryOptions.groups, queryOptions.stmtTypes, queryOptions.searchText, { handleError: 'custom' } @@ -345,6 +368,7 @@ export default function useStatementTableController({ data, isDataLoadedSlowly, allSchemas, + allGroups, allStmtTypes, errors, diff --git a/ui/packages/tidb-dashboard-lib/src/client/models.ts b/ui/packages/tidb-dashboard-lib/src/client/models.ts index 4dfd927fb7..9c5acf4d5a 100644 --- a/ui/packages/tidb-dashboard-lib/src/client/models.ts +++ b/ui/packages/tidb-dashboard-lib/src/client/models.ts @@ -2791,6 +2791,12 @@ export interface StatementGetStatementsRequest { * @memberof StatementGetStatementsRequest */ 'fields'?: string; + /** + * + * @type {Array} + * @memberof StatementGetStatementsRequest + */ + 'resource_groups'?: Array; /** * * @type {Array}