diff --git a/.erda/migrations/qa/20211201-auto-test-exec-history-index.sql b/.erda/migrations/qa/20211201-auto-test-exec-history-index.sql new file mode 100644 index 00000000000..c975417ab59 --- /dev/null +++ b/.erda/migrations/qa/20211201-auto-test-exec-history-index.sql @@ -0,0 +1,3 @@ +ALTER TABLE `dice_autotest_exec_history` ADD INDEX `idx_step_id` (`step_id`); +ALTER TABLE `dice_autotest_exec_history` ADD INDEX `idx_scene_id` (`scene_id`); +ALTER TABLE `dice_autotest_exec_history` ADD INDEX `idx_project_id_iteration_id_type_execute_time` (`project_id`, `iteration_id`, `type`, `execute_time`); \ No newline at end of file diff --git a/apistructs/autotest_exec_history.go b/apistructs/autotest_exec_history.go index a4cde180ca9..86b3a25c82d 100644 --- a/apistructs/autotest_exec_history.go +++ b/apistructs/autotest_exec_history.go @@ -51,10 +51,12 @@ type AutoTestExecHistoryResp struct { type ExecHistorySceneAvgCostTime struct { SceneID uint64 `json:"sceneID" gorm:"scene_id"` Avg float64 `json:"avg" gorm:"avg"` + Name string `json:"name" gorm:"name"` } type ExecHistorySceneStatusCount struct { SceneID uint64 `json:"sceneID" gorm:"scene_id"` + Name string `json:"name" gorm:"name"` SuccessCount uint64 `json:"successCount" gorm:"success_count"` FailCount uint64 `json:"failCount" gorm:"fail_count"` FailRate float64 `json:"failRate"` @@ -64,18 +66,21 @@ type ExecHistorySceneApiStatusCount struct { SceneID uint64 `json:"sceneID" gorm:"scene_id"` SuccessCount uint64 `json:"successCount" gorm:"success_count"` TotalCount uint64 `json:"failCount" gorm:"total_count"` + Name string `json:"name" gorm:"name"` PassRate float64 `json:"passRate"` } type ExecHistoryApiAvgCostTime struct { StepID uint64 `json:"stepID" gorm:"step_id"` Avg float64 `json:"avg" gorm:"avg"` + Name string `json:"name" gorm:"name"` } type ExecHistoryApiStatusCount struct { StepID uint64 `json:"stepID" gorm:"step_id"` SuccessCount uint64 `json:"successCount" gorm:"success_count"` FailCount uint64 `json:"failCount" gorm:"fail_count"` + Name string `json:"name" gorm:"name"` FailRate float64 `json:"failRate"` } diff --git a/apistructs/autotest_space.go b/apistructs/autotest_space.go index 5bd03978739..f751f474d53 100644 --- a/apistructs/autotest_space.go +++ b/apistructs/autotest_space.go @@ -234,3 +234,11 @@ type AutoTestSpaceStats struct { SceneNum int StepNum int } + +type AutoTestSceneCount struct { + Count int +} + +type AutoTestSceneStepCount struct { + Count int +} diff --git a/modules/dop/component-protocol/components/test-dashboard/at_api_chart_group/at_api_avg_cost_chart/render.go b/modules/dop/component-protocol/components/test-dashboard/at_api_chart_group/at_api_avg_cost_chart/render.go index 66b43730875..98edea30c9b 100644 --- a/modules/dop/component-protocol/components/test-dashboard/at_api_chart_group/at_api_avg_cost_chart/render.go +++ b/modules/dop/component-protocol/components/test-dashboard/at_api_chart_group/at_api_avg_cost_chart/render.go @@ -16,7 +16,6 @@ package at_api_avg_cost_chart import ( "context" - "sort" "strconv" "github.com/erda-project/erda-infra/base/servicehub" @@ -47,17 +46,6 @@ func (f *Chart) Render(ctx context.Context, c *cptype.Component, scenario cptype h := gshelper.NewGSHelper(gs) atSvc := ctx.Value(types.AutoTestPlanService).(*autotestv2.Service) - sceneSteps, err := atSvc.ListAutoTestSceneSteps(h.GetGlobalAtSceneIDs()) - if err != nil { - return err - } - sceneStepIDs := make([]uint64, 0, len(sceneSteps)) - sceneStepMap := make(map[uint64]string, 0) - for _, v := range sceneSteps { - sceneStepMap[v.ID] = v.Name - sceneStepIDs = append(sceneStepIDs, v.ID) - } - timeFilter := h.GetAtSceneAndApiTimeFilter() projectID, _ := strconv.ParseUint(cputil.GetInParamByKey(ctx, "projectId").(string), 10, 64) costTimeAvg, err := atSvc.ExecHistoryApiAvgCostTime(apistructs.StatisticsExecHistoryRequest{ @@ -73,20 +61,17 @@ func (f *Chart) Render(ctx context.Context, c *cptype.Component, scenario cptype if err != nil { return err } - sort.Slice(costTimeAvg, func(i, j int) bool { - return costTimeAvg[i].Avg > costTimeAvg[j].Avg - }) var ( values []int64 categories []string ) for _, v := range costTimeAvg { - if _, ok := sceneStepMap[v.StepID]; !ok { - continue + if v.Avg <= 0 { + v.Avg = 0 } values = append(values, int64(v.Avg)) - categories = append(categories, sceneStepMap[v.StepID]) + categories = append(categories, v.Name) } c.Props = common.NewBarProps(values, categories, cputil.I18n(ctx, "api-avg-cost"), "{value}s") diff --git a/modules/dop/component-protocol/components/test-dashboard/at_api_chart_group/at_api_rate_failed_chart/render.go b/modules/dop/component-protocol/components/test-dashboard/at_api_chart_group/at_api_rate_failed_chart/render.go index 08c9fd4f338..0048e34d920 100644 --- a/modules/dop/component-protocol/components/test-dashboard/at_api_chart_group/at_api_rate_failed_chart/render.go +++ b/modules/dop/component-protocol/components/test-dashboard/at_api_chart_group/at_api_rate_failed_chart/render.go @@ -47,17 +47,6 @@ func (f *Chart) Render(ctx context.Context, c *cptype.Component, scenario cptype h := gshelper.NewGSHelper(gs) atSvc := ctx.Value(types.AutoTestPlanService).(*autotestv2.Service) - sceneSteps, err := atSvc.ListAutoTestSceneSteps(h.GetGlobalAtSceneIDs()) - if err != nil { - return err - } - sceneStepIDs := make([]uint64, 0, len(sceneSteps)) - sceneStepMap := make(map[uint64]string, 0) - for _, v := range sceneSteps { - sceneStepMap[v.ID] = v.Name - sceneStepIDs = append(sceneStepIDs, v.ID) - } - timeFilter := h.GetAtSceneAndApiTimeFilter() projectID, _ := strconv.ParseUint(cputil.GetInParamByKey(ctx, "projectId").(string), 10, 64) statusCounts, err := atSvc.ExecHistoryApiStatusCount(apistructs.StatisticsExecHistoryRequest{ @@ -89,12 +78,12 @@ func (f *Chart) Render(ctx context.Context, c *cptype.Component, scenario cptype values []int64 categories []string ) - for _, v := range statusCounts { - if _, ok := sceneStepMap[v.StepID]; !ok { - continue + for i, v := range statusCounts { + if i == 500 { + break } values = append(values, int64(v.FailRate)) - categories = append(categories, sceneStepMap[v.StepID]) + categories = append(categories, v.Name) } c.Props = common.NewBarProps(values, categories, cputil.I18n(ctx, "api-failed-rate"), "{value}%") diff --git a/modules/dop/component-protocol/components/test-dashboard/common/gshelper/helper.go b/modules/dop/component-protocol/components/test-dashboard/common/gshelper/helper.go index 4ce91f189e2..81bcafa6de9 100644 --- a/modules/dop/component-protocol/components/test-dashboard/common/gshelper/helper.go +++ b/modules/dop/component-protocol/components/test-dashboard/common/gshelper/helper.go @@ -216,22 +216,6 @@ func (h *GSHelper) GetGlobalAtStep() []apistructs.TestPlanV2Step { return res } -func (h *GSHelper) SetGlobalAtSceneIDs(ids []uint64) { - if h.gs == nil { - return - } - (*h.gs)["GlobalAtSceneIDs"] = ids -} - -func (h *GSHelper) GetGlobalAtSceneIDs() []uint64 { - if h.gs == nil { - return nil - } - res := make([]uint64, 0) - _ = assign((*h.gs)["GlobalAtSceneIDs"], &res) - return res -} - type AtSceneAndApiTimeFilter struct { TimeStart string `json:"timeStart"` TimeEnd string `json:"timeEnd"` diff --git a/modules/dop/component-protocol/components/test-dashboard/filter/render.go b/modules/dop/component-protocol/components/test-dashboard/filter/render.go index 834ed9f5dcd..8a964ffcb4f 100644 --- a/modules/dop/component-protocol/components/test-dashboard/filter/render.go +++ b/modules/dop/component-protocol/components/test-dashboard/filter/render.go @@ -142,7 +142,7 @@ func (f *Filter) Render(ctx context.Context, c *cptype.Component, scenario cptyp }()) // set global auto test scene and step - if err = f.SetGlobalAtSceneAndStep(h); err != nil { + if err = f.SetGlobalAtStep(h); err != nil { return err } @@ -158,30 +158,13 @@ func (f *Filter) Render(ctx context.Context, c *cptype.Component, scenario cptyp return nil } -func (f *Filter) SetGlobalAtSceneAndStep(h *gshelper.GSHelper) error { +func (f *Filter) SetGlobalAtStep(h *gshelper.GSHelper) error { steps, err := f.atTestPlan.ListStepByPlanID(h.GetGlobalAutoTestPlanIDs()...) if err != nil { return err } - scenes, _, err := f.atTestPlan.ListSceneBySceneSetID(func() []uint64 { - setIDs := make([]uint64, 0, len(steps)) - for _, v := range steps { - setIDs = append(setIDs, v.SceneSetID) - } - return setIDs - }()...) - if err != nil { - return err - } - - sceneIDs := make([]uint64, 0, len(scenes)) - for _, v := range scenes { - sceneIDs = append(sceneIDs, v.ID) - } - h.SetGlobalAtStep(steps) - h.SetGlobalAtSceneIDs(sceneIDs) return nil } diff --git a/modules/dop/component-protocol/components/test-dashboard/overview_group/blocks/at/at_num_api/render.go b/modules/dop/component-protocol/components/test-dashboard/overview_group/blocks/at/at_num_api/render.go index 34d2d7e97d4..36ee744c02c 100644 --- a/modules/dop/component-protocol/components/test-dashboard/overview_group/blocks/at/at_num_api/render.go +++ b/modules/dop/component-protocol/components/test-dashboard/overview_group/blocks/at/at_num_api/render.go @@ -43,35 +43,20 @@ func (t *Text) Render(ctx context.Context, c *cptype.Component, scenario cptype. h := gshelper.NewGSHelper(gs) atSvc := ctx.Value(types.AutoTestPlanService).(*autotestv2.Service) - scenes, _, err := atSvc.ListSceneBySceneSetID(func() []uint64 { - setIDs := make([]uint64, 0, len(h.GetBlockAtStep())) - for _, v := range h.GetBlockAtStep() { - setIDs = append(setIDs, v.SceneSetID) + stepCount, err := atSvc.CountAutoTestSceneSteps(func() []uint64 { + selectPlans := h.GetAtBlockFilterTestPlanList() + selectPlanIDs := make([]uint64, 0, len(selectPlans)) + for _, v := range selectPlans { + selectPlanIDs = append(selectPlanIDs, v.ID) } - return setIDs - }()...) - if err != nil { - return err - } - sceneSteps, err := atSvc.ListAutoTestSceneSteps(func() []uint64 { - sceneIDs := make([]uint64, 0, len(scenes)) - for _, v := range scenes { - sceneIDs = append(sceneIDs, v.ID) - } - return sceneIDs + return selectPlanIDs }()) if err != nil { return err } tv := pkg.TextValue{ Value: strutil.String(func() int { - var count int - for _, v := range sceneSteps { - if v.Type.IsEffectiveStepType() && v.Name != "" { - count++ - } - } - return count + return stepCount.Count }()), Kind: cputil.I18n(ctx, "auto-test-api-num"), } diff --git a/modules/dop/component-protocol/components/test-dashboard/overview_group/blocks/at/at_num_scene/render.go b/modules/dop/component-protocol/components/test-dashboard/overview_group/blocks/at/at_num_scene/render.go index fca61ba5b78..b401268b6c9 100644 --- a/modules/dop/component-protocol/components/test-dashboard/overview_group/blocks/at/at_num_scene/render.go +++ b/modules/dop/component-protocol/components/test-dashboard/overview_group/blocks/at/at_num_scene/render.go @@ -43,12 +43,13 @@ func (t *Text) Render(ctx context.Context, c *cptype.Component, scenario cptype. h := gshelper.NewGSHelper(gs) atSvc := ctx.Value(types.AutoTestPlanService).(*autotestv2.Service) - _, total, err := atSvc.ListSceneBySceneSetID(func() []uint64 { - setIDs := make([]uint64, 0, len(h.GetBlockAtStep())) - for _, v := range h.GetBlockAtStep() { - setIDs = append(setIDs, v.SceneSetID) + sceneCount, err := atSvc.CountSceneByPlanIDs(func() []uint64 { + selectPlans := h.GetAtBlockFilterTestPlanList() + selectPlanIDs := make([]uint64, 0, len(selectPlans)) + for _, v := range selectPlans { + selectPlanIDs = append(selectPlanIDs, v.ID) } - return setIDs + return selectPlanIDs }()...) if err != nil { return err @@ -56,7 +57,7 @@ func (t *Text) Render(ctx context.Context, c *cptype.Component, scenario cptype. tv := pkg.TextValue{ Value: strutil.String(func() int { - return int(total) + return sceneCount.Count }()), Kind: cputil.I18n(ctx, "auto-test-scene-num"), } diff --git a/modules/dop/component-protocol/components/test-dashboard/scene_chart_group/scene_avg_cost_chart/render.go b/modules/dop/component-protocol/components/test-dashboard/scene_chart_group/scene_avg_cost_chart/render.go index 80db88e90c6..d3a1515d525 100644 --- a/modules/dop/component-protocol/components/test-dashboard/scene_chart_group/scene_avg_cost_chart/render.go +++ b/modules/dop/component-protocol/components/test-dashboard/scene_chart_group/scene_avg_cost_chart/render.go @@ -16,7 +16,6 @@ package scene_avg_cost_chart import ( "context" - "sort" "strconv" "time" @@ -48,25 +47,7 @@ func (f *Chart) Render(ctx context.Context, c *cptype.Component, scenario cptype h := gshelper.NewGSHelper(gs) atSvc := ctx.Value(types.AutoTestPlanService).(*autotestv2.Service) - scenes, _, err := atSvc.ListSceneBySceneSetID(func() []uint64 { - setIDs := make([]uint64, 0, len(h.GetGlobalAtStep())) - for _, v := range h.GetGlobalAtStep() { - setIDs = append(setIDs, v.SceneSetID) - } - return setIDs - }()...) - if err != nil { - return err - } - sceneIDs := make([]uint64, 0, len(scenes)) - sceneMap := make(map[uint64]string, 0) - for _, v := range scenes { - sceneMap[v.ID] = v.Name - sceneIDs = append(sceneIDs, v.ID) - } - timeFilter := h.GetAtSceneAndApiTimeFilter() - projectID, _ := strconv.ParseUint(cputil.GetInParamByKey(ctx, "projectId").(string), 10, 64) costTimeAvg, err := atSvc.ExecHistorySceneAvgCostTime(apistructs.StatisticsExecHistoryRequest{ TimeStart: timeFilter.TimeStart, @@ -81,20 +62,17 @@ func (f *Chart) Render(ctx context.Context, c *cptype.Component, scenario cptype if err != nil { return err } - sort.Slice(costTimeAvg, func(i, j int) bool { - return costTimeAvg[i].Avg > costTimeAvg[j].Avg - }) var ( values []int64 categories []string ) for _, v := range costTimeAvg { - if _, ok := sceneMap[v.SceneID]; !ok { - continue + if v.Avg <= 0 { + v.Avg = 0 } values = append(values, int64(v.Avg)) - categories = append(categories, sceneMap[v.SceneID]) + categories = append(categories, v.Name) } c.Props = common.NewBarProps(values, categories, cputil.I18n(ctx, "scene-avg-cost"), "{value}s") diff --git a/modules/dop/component-protocol/components/test-dashboard/scene_chart_group/scene_rate_failed_chart/render.go b/modules/dop/component-protocol/components/test-dashboard/scene_chart_group/scene_rate_failed_chart/render.go index 51e9035fe80..86ae8450c9f 100644 --- a/modules/dop/component-protocol/components/test-dashboard/scene_chart_group/scene_rate_failed_chart/render.go +++ b/modules/dop/component-protocol/components/test-dashboard/scene_chart_group/scene_rate_failed_chart/render.go @@ -47,23 +47,6 @@ func (f *Chart) Render(ctx context.Context, c *cptype.Component, scenario cptype h := gshelper.NewGSHelper(gs) atSvc := ctx.Value(types.AutoTestPlanService).(*autotestv2.Service) - scenes, _, err := atSvc.ListSceneBySceneSetID(func() []uint64 { - setIDs := make([]uint64, 0, len(h.GetGlobalAtStep())) - for _, v := range h.GetGlobalAtStep() { - setIDs = append(setIDs, v.SceneSetID) - } - return setIDs - }()...) - if err != nil { - return err - } - sceneIDs := make([]uint64, 0, len(scenes)) - sceneMap := make(map[uint64]string, 0) - for _, v := range scenes { - sceneMap[v.ID] = v.Name - sceneIDs = append(sceneIDs, v.ID) - } - timeFilter := h.GetAtSceneAndApiTimeFilter() projectID, _ := strconv.ParseUint(cputil.GetInParamByKey(ctx, "projectId").(string), 10, 64) statusCounts, err := atSvc.ExecHistorySceneStatusCount(apistructs.StatisticsExecHistoryRequest{ @@ -95,12 +78,12 @@ func (f *Chart) Render(ctx context.Context, c *cptype.Component, scenario cptype values []int64 categories []string ) - for _, v := range statusCounts { - if _, ok := sceneMap[v.SceneID]; !ok { - continue + for i, v := range statusCounts { + if i == 500 { + break } values = append(values, int64(v.FailRate)) - categories = append(categories, sceneMap[v.SceneID]) + categories = append(categories, v.Name) } c.Props = common.NewBarProps(values, categories, cputil.I18n(ctx, "scene-failed-rate"), "{value}%") diff --git a/modules/dop/component-protocol/components/test-dashboard/scene_chart_group/scene_rate_passed_chart/render.go b/modules/dop/component-protocol/components/test-dashboard/scene_chart_group/scene_rate_passed_chart/render.go index 5b98af467b7..97300699496 100644 --- a/modules/dop/component-protocol/components/test-dashboard/scene_chart_group/scene_rate_passed_chart/render.go +++ b/modules/dop/component-protocol/components/test-dashboard/scene_chart_group/scene_rate_passed_chart/render.go @@ -47,23 +47,6 @@ func (f *Chart) Render(ctx context.Context, c *cptype.Component, scenario cptype h := gshelper.NewGSHelper(gs) atSvc := ctx.Value(types.AutoTestPlanService).(*autotestv2.Service) - scenes, _, err := atSvc.ListSceneBySceneSetID(func() []uint64 { - setIDs := make([]uint64, 0, len(h.GetGlobalAtStep())) - for _, v := range h.GetGlobalAtStep() { - setIDs = append(setIDs, v.SceneSetID) - } - return setIDs - }()...) - if err != nil { - return err - } - sceneIDs := make([]uint64, 0, len(scenes)) - sceneMap := make(map[uint64]string, 0) - for _, v := range scenes { - sceneMap[v.ID] = v.Name - sceneIDs = append(sceneIDs, v.ID) - } - timeFilter := h.GetAtSceneAndApiTimeFilter() projectID, _ := strconv.ParseUint(cputil.GetInParamByKey(ctx, "projectId").(string), 10, 64) statusCounts, err := atSvc.ExecHistorySceneApiStatusCount(apistructs.StatisticsExecHistoryRequest{ @@ -94,12 +77,12 @@ func (f *Chart) Render(ctx context.Context, c *cptype.Component, scenario cptype values []int64 categories []string ) - for _, v := range statusCounts { - if _, ok := sceneMap[v.SceneID]; !ok { - continue + for i, v := range statusCounts { + if i == 500 { + break } values = append(values, int64(v.PassRate)) - categories = append(categories, sceneMap[v.SceneID]) + categories = append(categories, v.Name) } c.Props = common.NewBarProps(values, categories, cputil.I18n(ctx, "scene-passed-rate"), "{value}%") diff --git a/modules/dop/dao/autotest_exec_history.go b/modules/dop/dao/autotest_exec_history.go index 08a0d4edd69..38f4f08e1bd 100644 --- a/modules/dop/dao/autotest_exec_history.go +++ b/modules/dop/dao/autotest_exec_history.go @@ -109,88 +109,94 @@ func (client *DBClient) GetAutoTestExecHistoryByPipelineID(pipelineID uint64) (A // ExecHistorySceneAvgCostTime . func (client *DBClient) ExecHistorySceneAvgCostTime(req apistructs.StatisticsExecHistoryRequest) (list []apistructs.ExecHistorySceneAvgCostTime, err error) { - db := client.Table("dice_autotest_exec_history").Select("scene_id,AVG(cost_time_sec) AS avg"). - Where("project_id = ?", req.ProjectID). - Where("plan_id IN (?)", req.PlanIDs). - Where("type = ?", apistructs.StepTypeScene) + db := client.Table("dice_autotest_scene AS s"). + Select("s.id AS scene_id,s.`name`,AVG(cost_time_sec) AS avg"). + Joins("LEFT JOIN dice_autotest_exec_history AS h FORCE INDEX(`idx_project_id_iteration_id_type_execute_time`) ON s.id = h.scene_id "). + Where("h.project_id = ?", req.ProjectID). + Where("h.iteration_id IN (?)", req.IterationIDs). + Where("h.type = ?", apistructs.StepTypeScene) if req.TimeStart != "" { - db = db.Where("execute_time >= ?", req.TimeStart) + db = db.Where("h.execute_time >= ?", req.TimeStart) } if req.TimeEnd != "" { - db = db.Where("execute_time <= ?", req.TimeEnd) + db = db.Where("h.execute_time <= ?", req.TimeEnd) } - err = db.Group("scene_id").Find(&list).Error + err = db.Group("s.id").Order("avg DESC").Limit(500).Find(&list).Error return } // ExecHistorySceneStatusCount . func (client *DBClient) ExecHistorySceneStatusCount(req apistructs.StatisticsExecHistoryRequest) (list []apistructs.ExecHistorySceneStatusCount, err error) { - db := client.Table("dice_autotest_exec_history"). - Select("scene_id,sum( CASE WHEN `status` = 'Failed' THEN 1 ELSE 0 END ) AS 'fail_count',"+ - "sum( CASE WHEN `status` = 'Success' THEN 1 ELSE 0 END ) AS 'success_count'"). - Where("project_id = ?", req.ProjectID). - Where("plan_id IN (?)", req.PlanIDs). - Where("type = ?", apistructs.StepTypeScene) + db := client.Table("dice_autotest_scene AS s"). + Select("s.id AS scene_id,s.`name`,sum( CASE WHEN h.`status` = 'Failed' THEN 1 ELSE 0 END ) AS 'fail_count',"+ + "sum( CASE WHEN h.`status` = 'Success' THEN 1 ELSE 0 END ) AS 'success_count'"). + Joins("LEFT JOIN dice_autotest_exec_history AS h FORCE INDEX(`idx_project_id_iteration_id_type_execute_time`) ON s.id = h.scene_id "). + Where("h.project_id = ?", req.ProjectID). + Where("h.iteration_id IN (?)", req.IterationIDs). + Where("h.type = ?", apistructs.StepTypeScene) if req.TimeStart != "" { - db = db.Where("execute_time >= ?", req.TimeStart) + db = db.Where("h.execute_time >= ?", req.TimeStart) } if req.TimeEnd != "" { - db = db.Where("execute_time <= ?", req.TimeEnd) + db = db.Where("h.execute_time <= ?", req.TimeEnd) } - err = db.Group("scene_id").Find(&list).Error + err = db.Group("s.id").Find(&list).Error return } // ExecHistorySceneApiStatusCount . func (client *DBClient) ExecHistorySceneApiStatusCount(req apistructs.StatisticsExecHistoryRequest) (list []apistructs.ExecHistorySceneApiStatusCount, err error) { - db := client.Table("dice_autotest_exec_history"). - Select("scene_id,SUM(`success_api_num`) AS 'success_count',"+ - "SUM(`total_api_num`) AS 'total_count'"). - Where("project_id = ?", req.ProjectID). - Where("plan_id IN (?)", req.PlanIDs). - Where("type = ?", apistructs.StepTypeScene) + db := client.Table("dice_autotest_scene AS s"). + Select("s.id AS scene_id,s.`name`,SUM(h.`success_api_num`) AS 'success_count',"+ + "SUM(h.`total_api_num`) AS 'total_count'"). + Joins("LEFT JOIN dice_autotest_exec_history AS h FORCE INDEX(`idx_project_id_iteration_id_type_execute_time`) ON s.id = h.scene_id "). + Where("h.project_id = ?", req.ProjectID). + Where("h.iteration_id IN (?)", req.IterationIDs). + Where("h.type = ?", apistructs.StepTypeScene) if req.TimeStart != "" { - db = db.Where("execute_time >= ?", req.TimeStart) + db = db.Where("h.execute_time >= ?", req.TimeStart) } if req.TimeEnd != "" { - db = db.Where("execute_time <= ?", req.TimeEnd) + db = db.Where("h.execute_time <= ?", req.TimeEnd) } - err = db.Group("scene_id").Find(&list).Error + err = db.Group("s.id").Find(&list).Error return } // ExecHistoryApiAvgCostTime . func (client *DBClient) ExecHistoryApiAvgCostTime(req apistructs.StatisticsExecHistoryRequest) (list []apistructs.ExecHistoryApiAvgCostTime, err error) { - db := client.Table("dice_autotest_exec_history"). - Select("step_id,AVG(cost_time_sec) AS avg"). - Where("project_id = ?", req.ProjectID). - Where("plan_id IN (?)", req.PlanIDs). - Where("type IN (?)", apistructs.EffectiveStepType) + db := client.Table("dice_autotest_scene_step AS s"). + Select("s.id AS step_id,s.`name`,AVG( h.cost_time_sec ) AS avg"). + Joins("LEFT JOIN dice_autotest_exec_history AS h FORCE INDEX(`idx_project_id_iteration_id_type_execute_time`) ON s.id = h.step_id "). + Where("h.project_id = ?", req.ProjectID). + Where("h.iteration_id IN (?)", req.IterationIDs). + Where("h.type IN (?)", apistructs.EffectiveStepType) if req.TimeStart != "" { - db = db.Where("execute_time >= ?", req.TimeStart) + db = db.Where("h.execute_time >= ?", req.TimeStart) } if req.TimeEnd != "" { - db = db.Where("execute_time <= ?", req.TimeEnd) + db = db.Where("h.execute_time <= ?", req.TimeEnd) } - err = db.Group("step_id").Find(&list).Error + err = db.Group("s.id").Order("avg DESC").Limit(500).Find(&list).Error return } // ExecHistoryApiStatusCount . func (client *DBClient) ExecHistoryApiStatusCount(req apistructs.StatisticsExecHistoryRequest) (list []apistructs.ExecHistoryApiStatusCount, err error) { - db := client.Table("dice_autotest_exec_history"). - Select("step_id,sum( CASE WHEN `status` = 'Failed' THEN 1 ELSE 0 END ) AS 'fail_count',"+ - "sum( CASE WHEN `status` = 'Success' THEN 1 ELSE 0 END ) AS 'success_count'"). - Where("project_id = ?", req.ProjectID). - Where("plan_id IN (?)", req.PlanIDs). - Where("type IN (?)", apistructs.EffectiveStepType) + db := client.Table("dice_autotest_scene_step AS s"). + Select("s.id AS step_id,s.`name`,sum( CASE WHEN h.`status` = 'Failed' THEN 1 ELSE 0 END ) AS 'fail_count',"+ + "sum( CASE WHEN h.`status` = 'Success' THEN 1 ELSE 0 END ) AS 'success_count'"). + Joins("LEFT JOIN dice_autotest_exec_history AS h FORCE INDEX(`idx_project_id_iteration_id_type_execute_time`) ON s.id = h.step_id "). + Where("h.project_id = ?", req.ProjectID). + Where("h.iteration_id IN (?)", req.IterationIDs). + Where("h.type IN (?)", apistructs.EffectiveStepType) if req.TimeStart != "" { - db = db.Where("execute_time >= ?", req.TimeStart) + db = db.Where("h.execute_time >= ?", req.TimeStart) } if req.TimeEnd != "" { - db = db.Where("execute_time <= ?", req.TimeEnd) + db = db.Where("h.execute_time <= ?", req.TimeEnd) } - err = db.Group("step_id").Find(&list).Error + err = db.Group("s.id").Find(&list).Error return } diff --git a/modules/dop/dao/autotest_scene.go b/modules/dop/dao/autotest_scene.go index fe3e3af9b18..faff6a578b5 100644 --- a/modules/dop/dao/autotest_scene.go +++ b/modules/dop/dao/autotest_scene.go @@ -663,6 +663,15 @@ func (db *DBClient) ListSceneBySceneSetID(setIDs ...uint64) ([]AutoTestScene, in return scenes, total, err } +func (db *DBClient) CountSceneByPlanIDs(planIDs ...uint64) (sceneCount apistructs.AutoTestSceneCount, err error) { + err = db.Table("dice_autotest_scene AS scene"). + Select("COUNT(DISTINCT(scene.id)) AS count"). + Joins("LEFT JOIN dice_autotest_scene_set AS `set` ON scene.set_id = `set`.id"). + Joins("LEFT JOIN dice_autotest_plan_step AS step ON `set`.id = step.scene_set_id"). + Where("step.plan_id IN (?)", planIDs).Find(&sceneCount).Error + return +} + // ListAutotestSceneByGroupID . func (db *DBClient) ListAutotestSceneByGroupID(setID, groupID uint64) (scenes []AutoTestScene, err error) { err = db.Model(&AutoTestScene{}). diff --git a/modules/dop/dao/autotest_scene_step.go b/modules/dop/dao/autotest_scene_step.go index 800a9a87f05..e49ea30464b 100644 --- a/modules/dop/dao/autotest_scene_step.go +++ b/modules/dop/dao/autotest_scene_step.go @@ -123,6 +123,19 @@ func (db *DBClient) ListAutoTestSceneSteps(sceneID []uint64) ([]AutoTestSceneSte return steps, nil } +func (db *DBClient) CountAutoTestSceneSteps(planIDs []uint64) (stepCount apistructs.AutoTestSceneStepCount, err error) { + err = db.Table("dice_autotest_scene_step AS step"). + Select("COUNT(DISTINCT(step.id)) AS count"). + Joins("LEFT JOIN dice_autotest_scene AS scene ON step.scene_id = scene.id"). + Joins("LEFT JOIN dice_autotest_scene_set AS `set` ON scene.set_id = `set`.id"). + Joins("LEFT JOIN dice_autotest_plan_step AS plan_step ON `set`.id = plan_step.scene_set_id"). + Where("plan_step.plan_id IN (?)", planIDs). + Where("step.type IN (?)", apistructs.EffectiveStepType). + Where("step.name != ''"). + Find(&stepCount).Error + return +} + func (db *DBClient) GetAutoTestSceneStepNumber(sceneID uint64) (uint64, error) { var total uint64 if err := db.Table("dice_autotest_scene_step").Where("scene_id = ?", sceneID).Count(&total).Error; err != nil { diff --git a/modules/dop/dao/testplan_v2_step.go b/modules/dop/dao/testplan_v2_step.go index 1dc905a5d58..b2f28a64d87 100644 --- a/modules/dop/dao/testplan_v2_step.go +++ b/modules/dop/dao/testplan_v2_step.go @@ -319,7 +319,7 @@ func (client *DBClient) CheckRelatedSceneSet(setId uint64) (bool, error) { // ListStepByPlanID . func (client *DBClient) ListStepByPlanID(planIDs ...uint64) ([]TestPlanV2StepJoin, error) { var steps []TestPlanV2StepJoin - err := client.Debug().Table("dice_autotest_plan_step"). + err := client.Table("dice_autotest_plan_step"). Select("dice_autotest_plan_step.*,dice_autotest_scene_set.name"). Joins("LEFT JOIN dice_autotest_scene_set ON dice_autotest_plan_step.scene_set_id = dice_autotest_scene_set.id"). Where("dice_autotest_plan_step.plan_id IN (?)", planIDs). diff --git a/modules/dop/services/autotest_v2/scene.go b/modules/dop/services/autotest_v2/scene.go index fd69705843c..8b84b695f22 100644 --- a/modules/dop/services/autotest_v2/scene.go +++ b/modules/dop/services/autotest_v2/scene.go @@ -1497,6 +1497,11 @@ func (svc *Service) ListSceneBySceneSetID(setIDs ...uint64) (scenes []apistructs return } +// CountSceneByPlanIDs . +func (svc *Service) CountSceneByPlanIDs(planIDs ...uint64) (count apistructs.AutoTestSceneCount, err error) { + return svc.db.CountSceneByPlanIDs(planIDs...) +} + // ListAutoTestSceneSteps . func (svc *Service) ListAutoTestSceneSteps(sceneIDs []uint64) (sceneSteps []apistructs.AutoTestSceneStep, err error) { list, err := svc.db.ListAutoTestSceneSteps(sceneIDs) @@ -1509,6 +1514,11 @@ func (svc *Service) ListAutoTestSceneSteps(sceneIDs []uint64) (sceneSteps []apis return } +// CountAutoTestSceneSteps . +func (svc *Service) CountAutoTestSceneSteps(planIDs []uint64) (stepCount apistructs.AutoTestSceneStepCount, err error) { + return svc.db.CountAutoTestSceneSteps(planIDs) +} + // ListAutotestSceneByGroupID . func (svc *Service) ListAutotestSceneByGroupID(setID, groupID uint64) (scenes []apistructs.AutoTestScene, err error) { list, err := svc.db.ListAutotestSceneByGroupID(setID, groupID)