diff --git a/backend/core/models/domainlayer/crossdomain/project_pr_metric.go b/backend/core/models/domainlayer/crossdomain/project_pr_metric.go index 3ddafb2ee7b..1d0adc3416a 100644 --- a/backend/core/models/domainlayer/crossdomain/project_pr_metric.go +++ b/backend/core/models/domainlayer/crossdomain/project_pr_metric.go @@ -40,6 +40,8 @@ type ProjectPrMetric struct { PrCreatedDate *time.Time PrMergedDate *time.Time PrDeployedDate *time.Time + + IsAuthoredByBot bool } func (ProjectPrMetric) TableName() string { diff --git a/backend/core/models/migrationscripts/20250605_add_is_authored_by_bot_to_project_pr_metrics.go b/backend/core/models/migrationscripts/20250605_add_is_authored_by_bot_to_project_pr_metrics.go new file mode 100644 index 00000000000..674ca5926dc --- /dev/null +++ b/backend/core/models/migrationscripts/20250605_add_is_authored_by_bot_to_project_pr_metrics.go @@ -0,0 +1,52 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package migrationscripts + +import ( + "github.com/apache/incubator-devlake/core/context" + "github.com/apache/incubator-devlake/core/errors" + "github.com/apache/incubator-devlake/core/plugin" +) + +var _ plugin.MigrationScript = (*addDateFieldsToProjectPrMetric)(nil) + +type projectPrMetric20250617 struct { + IsAuthoredByBot bool +} + +func (projectPrMetric20250617) TableName() string { + return "project_pr_metrics" +} + +type addIsAuthoredByBotToProjectPrMetric struct{} + +func (*addIsAuthoredByBotToProjectPrMetric) Up(basicRes context.BasicRes) errors.Error { + db := basicRes.GetDal() + if err := db.AutoMigrate(&projectPrMetric20250617{}); err != nil { + return err + } + return nil +} + +func (*addIsAuthoredByBotToProjectPrMetric) Version() uint64 { + return 20250617123431 +} + +func (*addIsAuthoredByBotToProjectPrMetric) Name() string { + return "add is_authored_by_bot to project_pr_metrics according to #8381" +} diff --git a/backend/core/models/migrationscripts/register.go b/backend/core/models/migrationscripts/register.go index fd90c8fd24e..e5b52703c0e 100644 --- a/backend/core/models/migrationscripts/register.go +++ b/backend/core/models/migrationscripts/register.go @@ -138,5 +138,6 @@ func All() []plugin.MigrationScript { new(createQaTables), new(increaseCqIssueComponentLength), new(extendFieldSizeForCq), + new(addIsAuthoredByBotToProjectPrMetric), } } diff --git a/backend/plugins/dora/e2e/calculate_change_lead_time_test.go b/backend/plugins/dora/e2e/calculate_change_lead_time_test.go index e37cd635b5f..9d59597e80c 100644 --- a/backend/plugins/dora/e2e/calculate_change_lead_time_test.go +++ b/backend/plugins/dora/e2e/calculate_change_lead_time_test.go @@ -33,6 +33,9 @@ func TestCalculateCLTimeDataFlow(t *testing.T) { var plugin impl.Dora dataflowTester := e2ehelper.NewDataFlowTester(t, "dora", plugin) + t.Setenv("ENABLE_BOT_FILTERING", "true") + t.Setenv("BOT_FILTERING_PATTERN", ".*Renovate|Dependabot.*") + taskData := &tasks.DoraTaskData{ Options: &tasks.DoraOptions{ ProjectName: "project1", diff --git a/backend/plugins/dora/e2e/change_lead_time/project_pr_metrics.csv b/backend/plugins/dora/e2e/change_lead_time/project_pr_metrics.csv index 1c1e045f5ec..45bda3daa78 100644 --- a/backend/plugins/dora/e2e/change_lead_time/project_pr_metrics.csv +++ b/backend/plugins/dora/e2e/change_lead_time/project_pr_metrics.csv @@ -1,7 +1,7 @@ -id,project_name,first_commit_sha,pr_coding_time,first_review_id,pr_pickup_time,pr_review_time,deployment_commit_id,pr_deploy_time,pr_cycle_time,first_commit_authored_date,first_comment_date,pr_created_date,pr_merged_date,pr_deployed_date -pr0,project1,pr0_commit0,1440,,,,,,44640,2022-01-10T04:51:47.000+00:00,,2022-01-11T04:51:47.000+00:00,2022-02-10T04:51:47.000+00:00, -pr1,project1,08d2f2b6de0fa8de4d0e2b55b4b9a2e244214029,1440,comment02,5,55,5,2978,4478,2023-04-10T04:51:47.000+00:00,2023-04-11T04:56:47.000+00:00,2023-04-11T04:51:47.000+00:00,2023-04-11T05:51:47.000+00:00,2023-04-13T07:29:14.000+00:00 -pr2,project1,2537845559d8db99e9cda6190f32b50ec979c722,,comment04,1,60,5,1538,1598,2023-04-13T04:51:47.000+00:00,2023-04-12T04:51:49.000+00:00,2023-04-12T04:51:47.000+00:00,2023-04-12T05:51:47.000+00:00,2023-04-13T07:29:14.000+00:00 -pr3,project1,55f445997abbd5918da59d202d28762cd56fbd44,5883,comment07,,5760,6,,10203,2023-04-07T04:51:47.000+00:00,2023-04-10T06:53:51.000+00:00,2023-04-11T06:53:51.000+00:00,2023-04-14T06:53:51.000+00:00,2023-04-13T07:30:34.000+00:00 -pr4,project1,5ad0c09c447c19338f1dfbb65d89a3728962b3b7,11704,comment10,1500,,,,11764,2023-04-05T04:51:47.000+00:00,2023-04-14T08:55:01.000+00:00,2023-04-13T07:55:01.000+00:00,2023-04-13T08:55:01.000+00:00, -pr5,project1,62535543802631a0d3daf0b0b78c6a7e05e508fb,13144,comment12,,313068,,,13204,2023-04-04T04:51:47.000+00:00,2022-09-07T23:07:13.000+00:00,2023-04-13T07:55:01.000+00:00,2023-04-13T08:55:01.000+00:00, +id,project_name,first_commit_sha,pr_coding_time,first_review_id,pr_pickup_time,pr_review_time,deployment_commit_id,pr_deploy_time,pr_cycle_time,first_commit_authored_date,first_comment_date,pr_created_date,pr_merged_date,pr_deployed_date,is_authored_by_bot +pr0,project1,pr0_commit0,1440,,,,,,44640,2022-01-10T04:51:47.000+00:00,,2022-01-11T04:51:47.000+00:00,2022-02-10T04:51:47.000+00:00,,0 +pr1,project1,08d2f2b6de0fa8de4d0e2b55b4b9a2e244214029,1440,comment02,5,55,5,2978,4478,2023-04-10T04:51:47.000+00:00,2023-04-11T04:56:47.000+00:00,2023-04-11T04:51:47.000+00:00,2023-04-11T05:51:47.000+00:00,2023-04-13T07:29:14.000+00:00,0 +pr2,project1,2537845559d8db99e9cda6190f32b50ec979c722,,comment04,1,60,5,1538,1598,2023-04-13T04:51:47.000+00:00,2023-04-12T04:51:49.000+00:00,2023-04-12T04:51:47.000+00:00,2023-04-12T05:51:47.000+00:00,2023-04-13T07:29:14.000+00:00,1 +pr3,project1,55f445997abbd5918da59d202d28762cd56fbd44,5883,comment07,,5760,6,,10203,2023-04-07T04:51:47.000+00:00,2023-04-10T06:53:51.000+00:00,2023-04-11T06:53:51.000+00:00,2023-04-14T06:53:51.000+00:00,2023-04-13T07:30:34.000+00:00,1 +pr4,project1,5ad0c09c447c19338f1dfbb65d89a3728962b3b7,11704,comment10,1500,,,,11764,2023-04-05T04:51:47.000+00:00,2023-04-14T08:55:01.000+00:00,2023-04-13T07:55:01.000+00:00,2023-04-13T08:55:01.000+00:00,,0 +pr5,project1,62535543802631a0d3daf0b0b78c6a7e05e508fb,13144,comment12,,313068,,,13204,2023-04-04T04:51:47.000+00:00,2022-09-07T23:07:13.000+00:00,2023-04-13T07:55:01.000+00:00,2023-04-13T08:55:01.000+00:00,,0 diff --git a/backend/plugins/dora/e2e/change_lead_time/pull_requests.csv b/backend/plugins/dora/e2e/change_lead_time/pull_requests.csv index 46a2050777d..59e1acd2299 100644 --- a/backend/plugins/dora/e2e/change_lead_time/pull_requests.csv +++ b/backend/plugins/dora/e2e/change_lead_time/pull_requests.csv @@ -1,8 +1,8 @@ -id,base_repo_id,author_id,merge_commit_sha,created_date,merged_date,_raw_data_remark,base_commit_sha,head_commit_sha -pr0,repo1,a,pr_merge_commit0,2022-1-11 4:51:47,2022-2-10 4:51:47,deployment_commit 0,, -pr1,repo1,a,pr_merge_commit1,2023-4-11 4:51:47,2023-4-11 5:51:47,deployment_commit 5,, -pr2,repo1,a,pr_merge_commit2,2023-4-12 4:51:47,2023-4-12 5:51:47,deployment_commit 5,, -pr3,repo1,a,pr_merge_commit3,2023-4-11 6:53:51,2023-4-14 6:53:51,deployment_commit 6,, -pr4,repo1,,pr_merge_commit4,2023-4-13 7:55:01,2023-4-13 8:55:01,,, -pr5,repo1,,pr_merge_commit5,2023-4-13 7:55:01,2023-4-13 8:55:01,,, -pr6,repo1,,pr_merge_commit6,2023-4-13 7:55:01,,,, +id,base_repo_id,author_id,author_name,merge_commit_sha,created_date,merged_date,_raw_data_remark,base_commit_sha,head_commit_sha +pr0,repo1,a,John Doe,pr_merge_commit0,2022-1-11 4:51:47,2022-2-10 4:51:47,deployment_commit 0,, +pr1,repo1,a,John Doe,pr_merge_commit1,2023-4-11 4:51:47,2023-4-11 5:51:47,deployment_commit 5,, +pr2,repo1,a,Renovate,pr_merge_commit2,2023-4-12 4:51:47,2023-4-12 5:51:47,deployment_commit 5,, +pr3,repo1,a,Dependabot,pr_merge_commit3,2023-4-11 6:53:51,2023-4-14 6:53:51,deployment_commit 6,, +pr4,repo1,,,pr_merge_commit4,2023-4-13 7:55:01,2023-4-13 8:55:01,,, +pr5,repo1,,,pr_merge_commit5,2023-4-13 7:55:01,2023-4-13 8:55:01,,, +pr6,repo1,,,pr_merge_commit6,2023-4-13 7:55:01,,,, diff --git a/backend/plugins/dora/tasks/change_lead_time_calculator.go b/backend/plugins/dora/tasks/change_lead_time_calculator.go index d559ac39a3a..a07afc7a09a 100644 --- a/backend/plugins/dora/tasks/change_lead_time_calculator.go +++ b/backend/plugins/dora/tasks/change_lead_time_calculator.go @@ -20,8 +20,10 @@ package tasks import ( "math" "reflect" + "regexp" "time" + "github.com/apache/incubator-devlake/core/config" "github.com/apache/incubator-devlake/core/dal" "github.com/apache/incubator-devlake/core/errors" "github.com/apache/incubator-devlake/core/models/domainlayer/code" @@ -52,9 +54,25 @@ func CalculateChangeLeadTime(taskCtx plugin.SubTaskContext) errors.Error { return errors.Default.Wrap(err, "error deleting previous project_pr_metrics") } + // Get env vars + cfg := config.GetConfig() + enableBotFiltering := cfg.GetBool("ENABLE_BOT_FILTERING") + botFilteringPattern := cfg.GetString("BOT_FILTERING_PATTERN") + + // Precompile bot filtering regex if enabled and pattern is set + var botFilteringRegex *regexp.Regexp + if enableBotFiltering && botFilteringPattern != "" { + var err error + botFilteringRegex, err = regexp.Compile(botFilteringPattern) + if err != nil { + logger.Warn(err, "Invalid bot filtering pattern: %s", botFilteringPattern) + botFilteringRegex = nil + } + } + // Get pull requests by repo project_name var clauses = []dal.Clause{ - dal.Select("pr.id, pr.pull_request_key, pr.author_id, pr.merge_commit_sha, pr.created_date, pr.merged_date"), + dal.Select("pr.id, pr.pull_request_key, pr.author_id, pr.author_name, pr.merge_commit_sha, pr.created_date, pr.merged_date"), dal.From("pull_requests pr"), dal.Join(`LEFT JOIN project_mapping pm ON (pm.row_id = pr.base_repo_id)`), dal.Where("pr.merged_date IS NOT NULL AND pm.project_name = ? AND pm.table = 'repos'", data.Options.ProjectName), @@ -95,6 +113,7 @@ func CalculateChangeLeadTime(taskCtx plugin.SubTaskContext) errors.Error { projectPrMetric.FirstCommitSha = firstCommit.CommitSha projectPrMetric.FirstCommitAuthoredDate = &firstCommit.CommitAuthoredDate } + projectPrMetric.IsAuthoredByBot = matchesBotFilter(botFilteringRegex, pr.AuthorName) // Get the first review for the PR firstReview, err := getFirstReview(pr.Id, pr.AuthorId, db) @@ -244,3 +263,10 @@ func computeTimeSpan(start, end *time.Time) *int64 { } return &minutes } + +func matchesBotFilter(botFilterRegex *regexp.Regexp, name string) bool { + if botFilterRegex == nil { + return false + } + return botFilterRegex.MatchString(name) +} diff --git a/env.example b/env.example index 44604913aa0..31a407c3d74 100755 --- a/env.example +++ b/env.example @@ -82,4 +82,10 @@ SKIP_COMMIT_FILES=true WRAP_RESPONSE_ERROR= # Enable subtasks by default: plugin_name:subtask_name:enabled -ENABLE_SUBTASKS_BY_DEFAULT="jira:collectIssueChangelogs:true,jira:extractIssueChangelogs:true,jira:convertIssueChangelogs:true,tapd:collectBugChangelogs:true,tapd:extractBugChangelogs:true,tapd:convertBugChangelogs:true,zentao:collectBugRepoCommits:true,zentao:extractBugRepoCommits:true,zentao:convertBugRepoCommits:true,zentao:collectStoryRepoCommits:true,zentao:extractStoryRepoCommits:true,zentao:convertStoryRepoCommits:true,zentao:collectTaskRepoCommits:true,zentao:extractTaskRepoCommits:true,zentao:convertTaskRepoCommits:true" \ No newline at end of file +ENABLE_SUBTASKS_BY_DEFAULT="jira:collectIssueChangelogs:true,jira:extractIssueChangelogs:true,jira:convertIssueChangelogs:true,tapd:collectBugChangelogs:true,tapd:extractBugChangelogs:true,tapd:convertBugChangelogs:true,zentao:collectBugRepoCommits:true,zentao:extractBugRepoCommits:true,zentao:convertBugRepoCommits:true,zentao:collectStoryRepoCommits:true,zentao:extractStoryRepoCommits:true,zentao:convertStoryRepoCommits:true,zentao:collectTaskRepoCommits:true,zentao:extractTaskRepoCommits:true,zentao:convertTaskRepoCommits:true" + +# Enable filtering of bot-authored changes in DORA metrics (e.g., to exclude commits from Renovate, Dependabot) +ENABLE_BOT_FILTERING= + +# Regex pattern to identify bot users by display name or username in DORA plugin +BOT_FILTERING_PATTERN= \ No newline at end of file diff --git a/grafana/dashboards/DORA.json b/grafana/dashboards/DORA.json index 3d3fdaa0983..fc8877ae1e2 100644 --- a/grafana/dashboards/DORA.json +++ b/grafana/dashboards/DORA.json @@ -233,7 +233,7 @@ "metricColumn": "none", "queryType": "randomWalk", "rawQuery": true, - "rawSql": "-- Metric 1: Deployment Frequency\nwith last_few_calendar_months as(\n -- construct the last few calendar months within the selected time period in the top-right corner\n SELECT\n CAST(($__timeTo() - INTERVAL (H + T + U) DAY) AS date) day\n FROM\n (\n SELECT\n 0 H\n UNION\n ALL\n SELECT\n 100\n UNION\n ALL\n SELECT\n 200\n UNION\n ALL\n SELECT\n 300\n ) H\n CROSS JOIN (\n SELECT\n 0 T\n UNION\n ALL\n SELECT\n 10\n UNION\n ALL\n SELECT\n 20\n UNION\n ALL\n SELECT\n 30\n UNION\n ALL\n SELECT\n 40\n UNION\n ALL\n SELECT\n 50\n UNION\n ALL\n SELECT\n 60\n UNION\n ALL\n SELECT\n 70\n UNION\n ALL\n SELECT\n 80\n UNION\n ALL\n SELECT\n 90\n ) T\n CROSS JOIN (\n SELECT\n 0 U\n UNION\n ALL\n SELECT\n 1\n UNION\n ALL\n SELECT\n 2\n UNION\n ALL\n SELECT\n 3\n UNION\n ALL\n SELECT\n 4\n UNION\n ALL\n SELECT\n 5\n UNION\n ALL\n SELECT\n 6\n UNION\n ALL\n SELECT\n 7\n UNION\n ALL\n SELECT\n 8\n UNION\n ALL\n SELECT\n 9\n ) U\n WHERE\n ($__timeTo() - INTERVAL (H + T + U) DAY) > $__timeFrom()\n),\n_production_deployment_days as(\n -- When deploying multiple commits in one pipeline, GitLab and BitBucket may generate more than one deployment. However, DevLake consider these deployments as ONE production deployment and use the last one's finished_date as the finished date.\n SELECT\n cdc.cicd_deployment_id as deployment_id,\n max(DATE(cdc.finished_date)) as day\n FROM\n cicd_deployment_commits cdc\n JOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id\n and pm.`table` = 'cicd_scopes'\n WHERE\n pm.project_name in (${project})\n and cdc.result = 'SUCCESS'\n and cdc.environment = 'PRODUCTION'\n GROUP BY\n 1\n),\n_days_weekly_deploy as(\n -- calculate the number of deployment days every week\n SELECT\n date(\n DATE_ADD(\n last_few_calendar_months.day,\n INTERVAL - WEEKDAY(last_few_calendar_months.day) DAY\n )\n ) as week,\n MAX(\n if(\n _production_deployment_days.day is not null,\n 1,\n 0\n )\n ) as weeks_deployed,\n COUNT(distinct _production_deployment_days.day) as days_deployed\n FROM\n last_few_calendar_months\n LEFT JOIN _production_deployment_days ON _production_deployment_days.day = last_few_calendar_months.day\n GROUP BY\n week\n),\n_days_monthly_deploy as(\n -- calculate the number of deployment days every month\n SELECT\n date(\n DATE_ADD(\n last_few_calendar_months.day,\n INTERVAL - DAY(last_few_calendar_months.day) + 1 DAY\n )\n ) as month,\n MAX(\n if(\n _production_deployment_days.day is not null,\n 1,\n null\n )\n ) as months_deployed,\n COUNT(distinct _production_deployment_days.day) as days_deployed\n FROM\n last_few_calendar_months\n LEFT JOIN _production_deployment_days ON _production_deployment_days.day = last_few_calendar_months.day\n GROUP BY\n month\n),\n_days_six_months_deploy AS (\n SELECT\n month,\n SUM(days_deployed) OVER (\n ORDER BY\n month ROWS BETWEEN 5 PRECEDING\n AND CURRENT ROW\n ) AS days_deployed_per_six_months,\n COUNT(months_deployed) OVER (\n ORDER BY\n month ROWS BETWEEN 5 PRECEDING\n AND CURRENT ROW\n ) AS months_deployed_count,\n ROW_NUMBER() OVER (\n PARTITION BY DATE_FORMAT(month, '%Y-%m') DIV 6\n ORDER BY\n month DESC\n ) AS rn\n FROM\n _days_monthly_deploy\n),\n_median_number_of_deployment_days_per_week_ranks as(\n SELECT\n *,\n percent_rank() over(\n order by\n days_deployed\n ) as ranks\n FROM\n _days_weekly_deploy\n),\n_median_number_of_deployment_days_per_week as(\n SELECT\n max(days_deployed) as median_number_of_deployment_days_per_week\n FROM\n _median_number_of_deployment_days_per_week_ranks\n WHERE\n ranks <= 0.5\n),\n_median_number_of_deployment_days_per_month_ranks as(\n SELECT\n *,\n percent_rank() over(\n order by\n days_deployed\n ) as ranks\n FROM\n _days_monthly_deploy\n),\n_median_number_of_deployment_days_per_month as(\n SELECT\n max(days_deployed) as median_number_of_deployment_days_per_month\n FROM\n _median_number_of_deployment_days_per_month_ranks\n WHERE\n ranks <= 0.5\n),\n_days_per_six_months_deploy_by_filter AS (\n SELECT\n month,\n days_deployed_per_six_months,\n months_deployed_count\n FROM\n _days_six_months_deploy\n WHERE\n rn % 6 = 1\n),\n_median_number_of_deployment_days_per_six_months_ranks as(\n SELECT\n *,\n percent_rank() over(\n order by\n days_deployed_per_six_months\n ) as ranks\n FROM\n _days_per_six_months_deploy_by_filter\n),\n_median_number_of_deployment_days_per_six_months as(\n SELECT\n min(days_deployed_per_six_months) as median_number_of_deployment_days_per_six_months,\n min(months_deployed_count) as is_collected\n FROM\n _median_number_of_deployment_days_per_six_months_ranks\n WHERE\n ranks >= 0.5\n),\n_metric_deployment_frequency as (\n SELECT\n 'Deployment frequency' as metric,\n CASE\n WHEN ('$dora_report') = '2023' THEN CASE\n WHEN median_number_of_deployment_days_per_week >= 5 THEN 'On-demand(elite)'\n WHEN median_number_of_deployment_days_per_week >= 1 THEN 'Between once per day and once per week(high)'\n WHEN median_number_of_deployment_days_per_month >= 1 THEN 'Between once per week and once per month(medium)'\n WHEN median_number_of_deployment_days_per_month < 1\n and is_collected is not null THEN 'Fewer than once per month(low)'\n ELSE \"N/A. Please check if you have collected deployments.\"\n END\n WHEN ('$dora_report') = '2021' THEN CASE\n WHEN median_number_of_deployment_days_per_week >= 5 THEN 'On-demand(elite)'\n WHEN median_number_of_deployment_days_per_month >= 1 THEN 'Between once per day and once per month(high)'\n WHEN median_number_of_deployment_days_per_six_months >= 1 THEN 'Between once per month and once every 6 months(medium)'\n WHEN median_number_of_deployment_days_per_six_months < 1\n and is_collected is not null THEN 'Fewer than once per six months(low)'\n ELSE \"N/A. Please check if you have collected deployments.\"\n END\n ELSE 'Invalid dora report'\n END AS value\n FROM\n _median_number_of_deployment_days_per_week,\n _median_number_of_deployment_days_per_month,\n _median_number_of_deployment_days_per_six_months\n),\n-- Metric 2: median lead time for changes\n_pr_stats as (\n -- get the cycle time of PRs deployed by the deployments finished in the selected period\n SELECT\n distinct pr.id,\n ppm.pr_cycle_time\n FROM\n pull_requests pr\n join project_pr_metrics ppm on ppm.id = pr.id\n join project_mapping pm on pr.base_repo_id = pm.row_id\n and pm.`table` = 'repos'\n join cicd_deployment_commits cdc on ppm.deployment_commit_id = cdc.id\n WHERE\n pm.project_name in (${project})\n and pr.merged_date is not null\n and ppm.pr_cycle_time is not null\n and $__timeFilter(cdc.finished_date)\n),\n_median_change_lead_time_ranks as(\n SELECT\n *,\n percent_rank() over(\n order by\n pr_cycle_time\n ) as ranks\n FROM\n _pr_stats\n),\n_median_change_lead_time as(\n -- use median PR cycle time as the median change lead time\n SELECT\n max(pr_cycle_time) as median_change_lead_time\n FROM\n _median_change_lead_time_ranks\n WHERE\n ranks <= 0.5\n),\n_metric_change_lead_time as (\n SELECT\n 'Lead time for changes' as metric,\n CASE\n WHEN ('$dora_report') = '2023' THEN CASE\n WHEN median_change_lead_time < 24 * 60 THEN \"Less than one day(elite)\"\n WHEN median_change_lead_time < 7 * 24 * 60 THEN \"Between one day and one week(high)\"\n WHEN median_change_lead_time < 30 * 24 * 60 THEN \"Between one week and one month(medium)\"\n WHEN median_change_lead_time >= 30 * 24 * 60 THEN \"More than one month(low)\"\n ELSE \"N/A. Please check if you have collected deployments/pull_requests.\"\n END\n WHEN ('$dora_report') = '2021' THEN CASE\n WHEN median_change_lead_time < 60 THEN \"Less than one hour(elite)\"\n WHEN median_change_lead_time < 7 * 24 * 60 THEN \"Less than one week(high)\"\n WHEN median_change_lead_time < 180 * 24 * 60 THEN \"Between one week and six months(medium)\"\n WHEN median_change_lead_time >= 180 * 24 * 60 THEN \"More than six months(low)\"\n ELSE \"N/A. Please check if you have collected deployments/pull_requests.\"\n END\n ELSE 'Invalid dora report'\n END AS value\n FROM\n _median_change_lead_time\n),\n-- Metric 3: change failure rate\n_deployments as (\n -- When deploying multiple commits in one pipeline, GitLab and BitBucket may generate more than one deployment. However, DevLake consider these deployments as ONE production deployment and use the last one's finished_date as the finished date.\n SELECT\n cdc.cicd_deployment_id as deployment_id,\n max(cdc.finished_date) as deployment_finished_date\n FROM\n cicd_deployment_commits cdc\n JOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id\n and pm.`table` = 'cicd_scopes'\n WHERE\n pm.project_name in (${project})\n and cdc.result = 'SUCCESS'\n and cdc.environment = 'PRODUCTION'\n GROUP BY\n 1\n HAVING\n $__timeFilter(max(cdc.finished_date))\n),\n_failure_caused_by_deployments as (\n -- calculate the number of incidents caused by each deployment\n SELECT\n d.deployment_id,\n d.deployment_finished_date,\n count(\n distinct case\n when i.id is not null then d.deployment_id\n else null\n end\n ) as has_incident\n FROM\n _deployments d\n left join project_incident_deployment_relationships pim on d.deployment_id = pim.deployment_id\n left join incidents i on pim.id = i.id\n GROUP BY\n 1,\n 2\n),\n_change_failure_rate as (\n SELECT\n case\n when count(deployment_id) is null then null\n else sum(has_incident) / count(deployment_id)\n end as change_failure_rate\n FROM\n _failure_caused_by_deployments\n),\n_is_collected_data as(\n SELECT\n CASE\n WHEN COUNT(i.id) = 0\n AND COUNT(cdc.id) = 0 THEN 'No All'\n WHEN COUNT(i.id) = 0 THEN 'No Incidents'\n WHEN COUNT(cdc.id) = 0 THEN 'No Deployments'\n END AS is_collected\n FROM\n (\n SELECT\n 1\n ) AS dummy\n LEFT JOIN incidents i ON 1 = 1\n LEFT JOIN cicd_deployment_commits cdc ON 1 = 1\n),\n_metric_cfr as (\n SELECT\n 'Change failure rate' as metric,\n CASE\n WHEN ('$dora_report') = '2023' THEN CASE\n WHEN is_collected = \"No All\" THEN \"N/A. Please check if you have collected deployments/incidents.\"\n WHEN is_collected = \"No Incidents\" THEN \"N/A. Please check if you have collected incidents.\"\n WHEN is_collected = \"No Deployments\" THEN \"N/A. Please check if you have collected deployments.\"\n WHEN change_failure_rate <=.05 THEN \"0-5%(elite)\"\n WHEN change_failure_rate <=.10 THEN \"5%-10%(high)\"\n WHEN change_failure_rate <=.15 THEN \"10%-15%(medium)\"\n WHEN change_failure_rate >.15 THEN \"> 15%(low)\"\n ELSE \"N/A. Please check if you have collected deployments/incidents.\"\n END\n WHEN ('$dora_report') = '2021' THEN CASE\n WHEN is_collected = \"No All\" THEN \"N/A. Please check if you have collected deployments/incidents.\"\n WHEN is_collected = \"No Incidents\" THEN \"N/A. Please check if you have collected incidents.\"\n WHEN is_collected = \"No Deployments\" THEN \"N/A. Please check if you have collected deployments.\"\n WHEN change_failure_rate <=.15 THEN \"0-15%(elite)\"\n WHEN change_failure_rate <=.20 THEN \"16%-20%(high)\"\n WHEN change_failure_rate <=.30 THEN \"21%-30%(medium)\"\n WHEN change_failure_rate >.30 THEN \"> 30%(low)\"\n ELSE \"N/A. Please check if you have collected deployments/incidents.\"\n END\n ELSE 'Invalid dora report'\n END AS value\n FROM\n _change_failure_rate,\n _is_collected_data\n),\n-- ***** 2023 report ***** --\n-- Metric 4: Failed deployment recovery time\n_incidents_for_deployments as (\n SELECT\n i.id as incident_id,\n i.created_date as incident_create_date,\n i.resolution_date as incident_resolution_date,\n fd.deployment_id as caused_by_deployment,\n fd.deployment_finished_date,\n date_format(fd.deployment_finished_date, '%y/%m') as deployment_finished_month\n FROM\n incidents i\n left join project_incident_deployment_relationships pim on i.id = pim.id\n join _deployments fd on pim.deployment_id = fd.deployment_id\n WHERE\n $__timeFilter(i.resolution_date)\n),\n_recovery_time_ranks as (\n SELECT\n *,\n percent_rank() over(\n order by\n TIMESTAMPDIFF(\n MINUTE,\n deployment_finished_date,\n incident_resolution_date\n )\n ) as ranks\n FROM\n _incidents_for_deployments\n),\n_median_recovery_time as (\n SELECT\n max(\n TIMESTAMPDIFF(\n MINUTE,\n deployment_finished_date,\n incident_resolution_date\n )\n ) as median_recovery_time\n FROM\n _recovery_time_ranks\n WHERE\n ranks <= 0.5\n),\n_metric_recovery_time_2023_report as(\n SELECT\n \"Failed deployment recovery time\" as metric,\n CASE\n WHEN ('$dora_report') = '2023' THEN CASE\n WHEN median_recovery_time < 60 THEN \"Less than one hour(elite)\"\n WHEN median_recovery_time < 24 * 60 THEN \"Less than one day(high)\"\n WHEN median_recovery_time < 7 * 24 * 60 THEN \"Between one day and one week(medium)\"\n WHEN median_recovery_time >= 7 * 24 * 60 THEN \"More than one week(low)\"\n ELSE \"N/A. Please check if you have collected deployments or incidents.\"\n END\n END AS median_recovery_time\n FROM\n _median_recovery_time\n),\n-- ***** 2021 report ***** --\n-- Metric 4: Median time to restore service \n_incidents as (\n -- get the incidents created within the selected time period in the top-right corner\n SELECT\n distinct i.id,\n cast(lead_time_minutes as signed) as lead_time_minutes\n FROM\n incidents i\n join project_mapping pm on i.scope_id = pm.row_id\n and pm.`table` = i.`table`\n WHERE\n pm.project_name in (${project})\n and $__timeFilter(i.resolution_date)\n),\n_median_mttr_ranks as(\n SELECT\n *,\n percent_rank() over(\n order by\n lead_time_minutes\n ) as ranks\n FROM\n _incidents\n),\n_median_mttr as(\n SELECT\n max(lead_time_minutes) as median_time_to_resolve\n FROM\n _median_mttr_ranks\n WHERE\n ranks <= 0.5\n),\n_metric_mttr_2021_report as(\n SELECT\n \"Time to restore service\" as metric,\n CASE\n WHEN ('$dora_report') = '2021' THEN CASE\n WHEN median_time_to_resolve < 60 THEN \"Less than one hour(elite)\"\n WHEN median_time_to_resolve < 24 * 60 THEN \"Less than one day(high)\"\n WHEN median_time_to_resolve < 7 * 24 * 60 THEN \"Between one day and one week(medium)\"\n WHEN median_time_to_resolve >= 7 * 24 * 60 THEN \"More than one week(low)\"\n ELSE \"N/A. Please check if you have collected incidents.\"\n END\n END AS median_time_to_resolve\n FROM\n _median_mttr\n),\n_metric_mrt_or_mm as(\n SELECT\n metric,\n median_recovery_time AS value\n FROM\n _metric_recovery_time_2023_report\n WHERE\n ('$dora_report') = '2023'\n UNION\n SELECT\n metric,\n median_time_to_resolve AS value\n FROM\n _metric_mttr_2021_report\n WHERE\n ('$dora_report') = '2021'\n),\n_final_results as (\n SELECT\n distinct db.id,\n db.metric,\n db.low,\n db.medium,\n db.high,\n db.elite,\n m1.metric as _metric,\n m1.value\n FROM\n dora_benchmarks db\n left join _metric_deployment_frequency m1 on db.metric = m1.metric\n WHERE\n m1.metric is not null\n and db.dora_report = ('$dora_report')\n union\n SELECT\n distinct db.id,\n db.metric,\n db.low,\n db.medium,\n db.high,\n db.elite,\n m2.metric as _metric,\n m2.value\n FROM\n dora_benchmarks db\n left join _metric_change_lead_time m2 on db.metric = m2.metric\n WHERE\n m2.metric is not null\n and db.dora_report = ('$dora_report')\n union\n SELECT\n distinct db.id,\n db.metric,\n db.low,\n db.medium,\n db.high,\n db.elite,\n m3.metric as _metric,\n m3.value\n FROM\n dora_benchmarks db\n left join _metric_cfr m3 on db.metric = m3.metric\n WHERE\n m3.metric is not null\n and db.dora_report = ('$dora_report')\n union\n SELECT\n distinct db.id,\n db.metric,\n db.low,\n db.medium,\n db.high,\n db.elite,\n m4.metric as _metric,\n m4.value\n FROM\n dora_benchmarks db\n left join _metric_mrt_or_mm m4 on db.metric = m4.metric\n WHERE\n m4.metric is not null\n and db.dora_report = ('$dora_report')\n)\nSELECT\n metric,\n replace(metric, ' ', '-') as metric_hidden,\n case\n when low = value then low\n else null\n end as low,\n case\n when medium = value then medium\n else null\n end as medium,\n case\n when high = value then high\n else null\n end as high,\n case\n when elite = value then elite\n else null\n end as elite\nFROM\n _final_results\nORDER BY\n id", + "rawSql": "-- Metric 1: Deployment Frequency\nwith last_few_calendar_months as(\n -- construct the last few calendar months within the selected time period in the top-right corner\n SELECT\n CAST(($__timeTo() - INTERVAL (H + T + U) DAY) AS date) day\n FROM\n (\n SELECT\n 0 H\n UNION\n ALL\n SELECT\n 100\n UNION\n ALL\n SELECT\n 200\n UNION\n ALL\n SELECT\n 300\n ) H\n CROSS JOIN (\n SELECT\n 0 T\n UNION\n ALL\n SELECT\n 10\n UNION\n ALL\n SELECT\n 20\n UNION\n ALL\n SELECT\n 30\n UNION\n ALL\n SELECT\n 40\n UNION\n ALL\n SELECT\n 50\n UNION\n ALL\n SELECT\n 60\n UNION\n ALL\n SELECT\n 70\n UNION\n ALL\n SELECT\n 80\n UNION\n ALL\n SELECT\n 90\n ) T\n CROSS JOIN (\n SELECT\n 0 U\n UNION\n ALL\n SELECT\n 1\n UNION\n ALL\n SELECT\n 2\n UNION\n ALL\n SELECT\n 3\n UNION\n ALL\n SELECT\n 4\n UNION\n ALL\n SELECT\n 5\n UNION\n ALL\n SELECT\n 6\n UNION\n ALL\n SELECT\n 7\n UNION\n ALL\n SELECT\n 8\n UNION\n ALL\n SELECT\n 9\n ) U\n WHERE\n ($__timeTo() - INTERVAL (H + T + U) DAY) > $__timeFrom()\n),\n_production_deployment_days as(\n -- When deploying multiple commits in one pipeline, GitLab and BitBucket may generate more than one deployment. However, DevLake consider these deployments as ONE production deployment and use the last one's finished_date as the finished date.\n SELECT\n cdc.cicd_deployment_id as deployment_id,\n max(DATE(cdc.finished_date)) as day\n FROM\n cicd_deployment_commits cdc\n JOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id\n JOIN project_pr_metrics ppm on cdc.id = ppm.deployment_commit_id\n and pm.`table` = 'cicd_scopes'\n WHERE\n pm.project_name in (${project})\n and cdc.result = 'SUCCESS'\n and cdc.environment = 'PRODUCTION'\n and (ppm.is_authored_by_bot is null or ppm.is_authored_by_bot in (${author_type}))\n GROUP BY\n 1\n),\n_days_weekly_deploy as(\n -- calculate the number of deployment days every week\n SELECT\n date(\n DATE_ADD(\n last_few_calendar_months.day,\n INTERVAL - WEEKDAY(last_few_calendar_months.day) DAY\n )\n ) as week,\n MAX(\n if(\n _production_deployment_days.day is not null,\n 1,\n 0\n )\n ) as weeks_deployed,\n COUNT(distinct _production_deployment_days.day) as days_deployed\n FROM\n last_few_calendar_months\n LEFT JOIN _production_deployment_days ON _production_deployment_days.day = last_few_calendar_months.day\n GROUP BY\n week\n),\n_days_monthly_deploy as(\n -- calculate the number of deployment days every month\n SELECT\n date(\n DATE_ADD(\n last_few_calendar_months.day,\n INTERVAL - DAY(last_few_calendar_months.day) + 1 DAY\n )\n ) as month,\n MAX(\n if(\n _production_deployment_days.day is not null,\n 1,\n null\n )\n ) as months_deployed,\n COUNT(distinct _production_deployment_days.day) as days_deployed\n FROM\n last_few_calendar_months\n LEFT JOIN _production_deployment_days ON _production_deployment_days.day = last_few_calendar_months.day\n GROUP BY\n month\n),\n_days_six_months_deploy AS (\n SELECT\n month,\n SUM(days_deployed) OVER (\n ORDER BY\n month ROWS BETWEEN 5 PRECEDING\n AND CURRENT ROW\n ) AS days_deployed_per_six_months,\n COUNT(months_deployed) OVER (\n ORDER BY\n month ROWS BETWEEN 5 PRECEDING\n AND CURRENT ROW\n ) AS months_deployed_count,\n ROW_NUMBER() OVER (\n PARTITION BY DATE_FORMAT(month, '%Y-%m') DIV 6\n ORDER BY\n month DESC\n ) AS rn\n FROM\n _days_monthly_deploy\n),\n_median_number_of_deployment_days_per_week_ranks as(\n SELECT\n *,\n percent_rank() over(\n order by\n days_deployed\n ) as ranks\n FROM\n _days_weekly_deploy\n),\n_median_number_of_deployment_days_per_week as(\n SELECT\n max(days_deployed) as median_number_of_deployment_days_per_week\n FROM\n _median_number_of_deployment_days_per_week_ranks\n WHERE\n ranks <= 0.5\n),\n_median_number_of_deployment_days_per_month_ranks as(\n SELECT\n *,\n percent_rank() over(\n order by\n days_deployed\n ) as ranks\n FROM\n _days_monthly_deploy\n),\n_median_number_of_deployment_days_per_month as(\n SELECT\n max(days_deployed) as median_number_of_deployment_days_per_month\n FROM\n _median_number_of_deployment_days_per_month_ranks\n WHERE\n ranks <= 0.5\n),\n_days_per_six_months_deploy_by_filter AS (\n SELECT\n month,\n days_deployed_per_six_months,\n months_deployed_count\n FROM\n _days_six_months_deploy\n WHERE\n rn % 6 = 1\n),\n_median_number_of_deployment_days_per_six_months_ranks as(\n SELECT\n *,\n percent_rank() over(\n order by\n days_deployed_per_six_months\n ) as ranks\n FROM\n _days_per_six_months_deploy_by_filter\n),\n_median_number_of_deployment_days_per_six_months as(\n SELECT\n min(days_deployed_per_six_months) as median_number_of_deployment_days_per_six_months,\n min(months_deployed_count) as is_collected\n FROM\n _median_number_of_deployment_days_per_six_months_ranks\n WHERE\n ranks >= 0.5\n),\n_metric_deployment_frequency as (\n SELECT\n 'Deployment frequency' as metric,\n CASE\n WHEN ('$dora_report') = '2023' THEN CASE\n WHEN median_number_of_deployment_days_per_week >= 5 THEN 'On-demand(elite)'\n WHEN median_number_of_deployment_days_per_week >= 1 THEN 'Between once per day and once per week(high)'\n WHEN median_number_of_deployment_days_per_month >= 1 THEN 'Between once per week and once per month(medium)'\n WHEN median_number_of_deployment_days_per_month < 1\n and is_collected is not null THEN 'Fewer than once per month(low)'\n ELSE \"N/A. Please check if you have collected deployments.\"\n END\n WHEN ('$dora_report') = '2021' THEN CASE\n WHEN median_number_of_deployment_days_per_week >= 5 THEN 'On-demand(elite)'\n WHEN median_number_of_deployment_days_per_month >= 1 THEN 'Between once per day and once per month(high)'\n WHEN median_number_of_deployment_days_per_six_months >= 1 THEN 'Between once per month and once every 6 months(medium)'\n WHEN median_number_of_deployment_days_per_six_months < 1\n and is_collected is not null THEN 'Fewer than once per six months(low)'\n ELSE \"N/A. Please check if you have collected deployments.\"\n END\n ELSE 'Invalid dora report'\n END AS value\n FROM\n _median_number_of_deployment_days_per_week,\n _median_number_of_deployment_days_per_month,\n _median_number_of_deployment_days_per_six_months\n),\n-- Metric 2: median lead time for changes\n_pr_stats as (\n -- get the cycle time of PRs deployed by the deployments finished in the selected period\n SELECT\n distinct pr.id,\n ppm.pr_cycle_time\n FROM\n pull_requests pr\n join project_pr_metrics ppm on ppm.id = pr.id\n join project_mapping pm on pr.base_repo_id = pm.row_id\n and pm.`table` = 'repos'\n join cicd_deployment_commits cdc on ppm.deployment_commit_id = cdc.id\n WHERE\n pm.project_name in (${project})\n and pr.merged_date is not null\n and ppm.pr_cycle_time is not null\n and (ppm.is_authored_by_bot is null or ppm.is_authored_by_bot in (${author_type}))\n and $__timeFilter(cdc.finished_date)\n),\n_median_change_lead_time_ranks as(\n SELECT\n *,\n percent_rank() over(\n order by\n pr_cycle_time\n ) as ranks\n FROM\n _pr_stats\n),\n_median_change_lead_time as(\n -- use median PR cycle time as the median change lead time\n SELECT\n max(pr_cycle_time) as median_change_lead_time\n FROM\n _median_change_lead_time_ranks\n WHERE\n ranks <= 0.5\n),\n_metric_change_lead_time as (\n SELECT\n 'Lead time for changes' as metric,\n CASE\n WHEN ('$dora_report') = '2023' THEN CASE\n WHEN median_change_lead_time < 24 * 60 THEN \"Less than one day(elite)\"\n WHEN median_change_lead_time < 7 * 24 * 60 THEN \"Between one day and one week(high)\"\n WHEN median_change_lead_time < 30 * 24 * 60 THEN \"Between one week and one month(medium)\"\n WHEN median_change_lead_time >= 30 * 24 * 60 THEN \"More than one month(low)\"\n ELSE \"N/A. Please check if you have collected deployments/pull_requests.\"\n END\n WHEN ('$dora_report') = '2021' THEN CASE\n WHEN median_change_lead_time < 60 THEN \"Less than one hour(elite)\"\n WHEN median_change_lead_time < 7 * 24 * 60 THEN \"Less than one week(high)\"\n WHEN median_change_lead_time < 180 * 24 * 60 THEN \"Between one week and six months(medium)\"\n WHEN median_change_lead_time >= 180 * 24 * 60 THEN \"More than six months(low)\"\n ELSE \"N/A. Please check if you have collected deployments/pull_requests.\"\n END\n ELSE 'Invalid dora report'\n END AS value\n FROM\n _median_change_lead_time\n),\n-- Metric 3: change failure rate\n_deployments as (\n -- When deploying multiple commits in one pipeline, GitLab and BitBucket may generate more than one deployment. However, DevLake consider these deployments as ONE production deployment and use the last one's finished_date as the finished date.\n SELECT\n cdc.cicd_deployment_id as deployment_id,\n max(cdc.finished_date) as deployment_finished_date\n FROM\n cicd_deployment_commits cdc\n JOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id\n JOIN project_pr_metrics ppm on cdc.id = ppm.deployment_commit_id\n and pm.`table` = 'cicd_scopes'\n WHERE\n pm.project_name in (${project})\n and cdc.result = 'SUCCESS'\n and cdc.environment = 'PRODUCTION'\n and (ppm.is_authored_by_bot is null or ppm.is_authored_by_bot in (${author_type}))\n GROUP BY\n 1\n HAVING\n $__timeFilter(max(cdc.finished_date))\n),\n_failure_caused_by_deployments as (\n -- calculate the number of incidents caused by each deployment\n SELECT\n d.deployment_id,\n d.deployment_finished_date,\n count(\n distinct case\n when i.id is not null then d.deployment_id\n else null\n end\n ) as has_incident\n FROM\n _deployments d\n left join project_incident_deployment_relationships pim on d.deployment_id = pim.deployment_id\n left join incidents i on pim.id = i.id\n GROUP BY\n 1,\n 2\n),\n_change_failure_rate as (\n SELECT\n case\n when count(deployment_id) is null then null\n else sum(has_incident) / count(deployment_id)\n end as change_failure_rate\n FROM\n _failure_caused_by_deployments\n),\n_is_collected_data as(\n SELECT\n CASE\n WHEN COUNT(i.id) = 0\n AND COUNT(cdc.id) = 0 THEN 'No All'\n WHEN COUNT(i.id) = 0 THEN 'No Incidents'\n WHEN COUNT(cdc.id) = 0 THEN 'No Deployments'\n END AS is_collected\n FROM\n (\n SELECT\n 1\n ) AS dummy\n LEFT JOIN incidents i ON 1 = 1\n LEFT JOIN cicd_deployment_commits cdc ON 1 = 1\n),\n_metric_cfr as (\n SELECT\n 'Change failure rate' as metric,\n CASE\n WHEN ('$dora_report') = '2023' THEN CASE\n WHEN is_collected = \"No All\" THEN \"N/A. Please check if you have collected deployments/incidents.\"\n WHEN is_collected = \"No Incidents\" THEN \"N/A. Please check if you have collected incidents.\"\n WHEN is_collected = \"No Deployments\" THEN \"N/A. Please check if you have collected deployments.\"\n WHEN change_failure_rate <=.05 THEN \"0-5%(elite)\"\n WHEN change_failure_rate <=.10 THEN \"5%-10%(high)\"\n WHEN change_failure_rate <=.15 THEN \"10%-15%(medium)\"\n WHEN change_failure_rate >.15 THEN \"> 15%(low)\"\n ELSE \"N/A. Please check if you have collected deployments/incidents.\"\n END\n WHEN ('$dora_report') = '2021' THEN CASE\n WHEN is_collected = \"No All\" THEN \"N/A. Please check if you have collected deployments/incidents.\"\n WHEN is_collected = \"No Incidents\" THEN \"N/A. Please check if you have collected incidents.\"\n WHEN is_collected = \"No Deployments\" THEN \"N/A. Please check if you have collected deployments.\"\n WHEN change_failure_rate <=.15 THEN \"0-15%(elite)\"\n WHEN change_failure_rate <=.20 THEN \"16%-20%(high)\"\n WHEN change_failure_rate <=.30 THEN \"21%-30%(medium)\"\n WHEN change_failure_rate >.30 THEN \"> 30%(low)\"\n ELSE \"N/A. Please check if you have collected deployments/incidents.\"\n END\n ELSE 'Invalid dora report'\n END AS value\n FROM\n _change_failure_rate,\n _is_collected_data\n),\n-- ***** 2023 report ***** --\n-- Metric 4: Failed deployment recovery time\n_incidents_for_deployments as (\n SELECT\n i.id as incident_id,\n i.created_date as incident_create_date,\n i.resolution_date as incident_resolution_date,\n fd.deployment_id as caused_by_deployment,\n fd.deployment_finished_date,\n date_format(fd.deployment_finished_date, '%y/%m') as deployment_finished_month\n FROM\n incidents i\n left join project_incident_deployment_relationships pim on i.id = pim.id\n join _deployments fd on pim.deployment_id = fd.deployment_id\n WHERE\n $__timeFilter(i.resolution_date)\n),\n_recovery_time_ranks as (\n SELECT\n *,\n percent_rank() over(\n order by\n TIMESTAMPDIFF(\n MINUTE,\n deployment_finished_date,\n incident_resolution_date\n )\n ) as ranks\n FROM\n _incidents_for_deployments\n),\n_median_recovery_time as (\n SELECT\n max(\n TIMESTAMPDIFF(\n MINUTE,\n deployment_finished_date,\n incident_resolution_date\n )\n ) as median_recovery_time\n FROM\n _recovery_time_ranks\n WHERE\n ranks <= 0.5\n),\n_metric_recovery_time_2023_report as(\n SELECT\n \"Failed deployment recovery time\" as metric,\n CASE\n WHEN ('$dora_report') = '2023' THEN CASE\n WHEN median_recovery_time < 60 THEN \"Less than one hour(elite)\"\n WHEN median_recovery_time < 24 * 60 THEN \"Less than one day(high)\"\n WHEN median_recovery_time < 7 * 24 * 60 THEN \"Between one day and one week(medium)\"\n WHEN median_recovery_time >= 7 * 24 * 60 THEN \"More than one week(low)\"\n ELSE \"N/A. Please check if you have collected deployments or incidents.\"\n END\n END AS median_recovery_time\n FROM\n _median_recovery_time\n),\n-- ***** 2021 report ***** --\n-- Metric 4: Median time to restore service \n_incidents as (\n -- get the incidents created within the selected time period in the top-right corner\n SELECT\n distinct i.id,\n cast(lead_time_minutes as signed) as lead_time_minutes\n FROM\n incidents i\n join project_mapping pm on i.scope_id = pm.row_id\n and pm.`table` = i.`table`\n WHERE\n pm.project_name in (${project})\n and $__timeFilter(i.resolution_date)\n),\n_median_mttr_ranks as(\n SELECT\n *,\n percent_rank() over(\n order by\n lead_time_minutes\n ) as ranks\n FROM\n _incidents\n),\n_median_mttr as(\n SELECT\n max(lead_time_minutes) as median_time_to_resolve\n FROM\n _median_mttr_ranks\n WHERE\n ranks <= 0.5\n),\n_metric_mttr_2021_report as(\n SELECT\n \"Time to restore service\" as metric,\n CASE\n WHEN ('$dora_report') = '2021' THEN CASE\n WHEN median_time_to_resolve < 60 THEN \"Less than one hour(elite)\"\n WHEN median_time_to_resolve < 24 * 60 THEN \"Less than one day(high)\"\n WHEN median_time_to_resolve < 7 * 24 * 60 THEN \"Between one day and one week(medium)\"\n WHEN median_time_to_resolve >= 7 * 24 * 60 THEN \"More than one week(low)\"\n ELSE \"N/A. Please check if you have collected incidents.\"\n END\n END AS median_time_to_resolve\n FROM\n _median_mttr\n),\n_metric_mrt_or_mm as(\n SELECT\n metric,\n median_recovery_time AS value\n FROM\n _metric_recovery_time_2023_report\n WHERE\n ('$dora_report') = '2023'\n UNION\n SELECT\n metric,\n median_time_to_resolve AS value\n FROM\n _metric_mttr_2021_report\n WHERE\n ('$dora_report') = '2021'\n),\n_final_results as (\n SELECT\n distinct db.id,\n db.metric,\n db.low,\n db.medium,\n db.high,\n db.elite,\n m1.metric as _metric,\n m1.value\n FROM\n dora_benchmarks db\n left join _metric_deployment_frequency m1 on db.metric = m1.metric\n WHERE\n m1.metric is not null\n and db.dora_report = ('$dora_report')\n union\n SELECT\n distinct db.id,\n db.metric,\n db.low,\n db.medium,\n db.high,\n db.elite,\n m2.metric as _metric,\n m2.value\n FROM\n dora_benchmarks db\n left join _metric_change_lead_time m2 on db.metric = m2.metric\n WHERE\n m2.metric is not null\n and db.dora_report = ('$dora_report')\n union\n SELECT\n distinct db.id,\n db.metric,\n db.low,\n db.medium,\n db.high,\n db.elite,\n m3.metric as _metric,\n m3.value\n FROM\n dora_benchmarks db\n left join _metric_cfr m3 on db.metric = m3.metric\n WHERE\n m3.metric is not null\n and db.dora_report = ('$dora_report')\n union\n SELECT\n distinct db.id,\n db.metric,\n db.low,\n db.medium,\n db.high,\n db.elite,\n m4.metric as _metric,\n m4.value\n FROM\n dora_benchmarks db\n left join _metric_mrt_or_mm m4 on db.metric = m4.metric\n WHERE\n m4.metric is not null\n and db.dora_report = ('$dora_report')\n)\nSELECT\n metric,\n replace(metric, ' ', '-') as metric_hidden,\n case\n when low = value then low\n else null\n end as low,\n case\n when medium = value then medium\n else null\n end as medium,\n case\n when high = value then high\n else null\n end as high,\n case\n when elite = value then elite\n else null\n end as elite\nFROM\n _final_results\nORDER BY\n id", "refId": "A", "select": [ [ @@ -350,7 +350,7 @@ { "targetBlank": false, "title": "link", - "url": "/d/Deployment-frequency/dora-drill-down-deployment-frequency?orgId=1&${project:queryparam}&from=${__from}&to=${__to}" + "url": "/d/Deployment-frequency/dora-drill-down-deployment-frequency?orgId=1&${project:queryparam}&${author_type:queryparam}&from=${__from}&to=${__to}" } ], "options": { @@ -380,7 +380,7 @@ "metricColumn": "none", "queryType": "randomWalk", "rawQuery": true, - "rawSql": "-- Metric 1: Deployment Frequency\nwith last_few_calendar_months as(\n-- construct the last few calendar months within the selected time period in the top-right corner\n\tSELECT CAST(($__timeTo()-INTERVAL (H+T+U) DAY) AS date) day\n\tFROM ( SELECT 0 H\n\t\t\tUNION ALL SELECT 100 UNION ALL SELECT 200 UNION ALL SELECT 300\n\t\t) H CROSS JOIN ( SELECT 0 T\n\t\t\tUNION ALL SELECT 10 UNION ALL SELECT 20 UNION ALL SELECT 30\n\t\t\tUNION ALL SELECT 40 UNION ALL SELECT 50 UNION ALL SELECT 60\n\t\t\tUNION ALL SELECT 70 UNION ALL SELECT 80 UNION ALL SELECT 90\n\t\t) T CROSS JOIN ( SELECT 0 U\n\t\t\tUNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3\n\t\t\tUNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6\n\t\t\tUNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9\n\t\t) U\n\tWHERE\n\t\t($__timeTo()-INTERVAL (H+T+U) DAY) > $__timeFrom()\n),\n\n_production_deployment_days as(\n-- When deploying multiple commits in one pipeline, GitLab and BitBucket may generate more than one deployment. However, DevLake consider these deployments as ONE production deployment and use the last one's finished_date as the finished date.\n\tSELECT\n\t\tcdc.cicd_deployment_id as deployment_id,\n\t\tmax(DATE(cdc.finished_date)) as day\n\tFROM cicd_deployment_commits cdc\n\tJOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id and pm.`table` = 'cicd_scopes'\n\tWHERE\n\t\tpm.project_name in (${project})\n\t\tand cdc.result = 'SUCCESS'\n\t\tand cdc.environment = 'PRODUCTION'\n\tGROUP BY 1\n),\n\n_days_weekly_deploy as(\n-- calculate the number of deployment days every week\n\tSELECT\n\t\t\tdate(DATE_ADD(last_few_calendar_months.day, INTERVAL -WEEKDAY(last_few_calendar_months.day) DAY)) as week,\n\t\t\tMAX(if(_production_deployment_days.day is not null, 1, null)) as weeks_deployed,\n\t\t\tCOUNT(distinct _production_deployment_days.day) as days_deployed\n\tFROM \n\t\tlast_few_calendar_months\n\t\tLEFT JOIN _production_deployment_days ON _production_deployment_days.day = last_few_calendar_months.day\n\tGROUP BY week\n\t),\n\n_days_monthly_deploy as(\n-- calculate the number of deployment days every month\n\tSELECT\n\t\t\tdate(DATE_ADD(last_few_calendar_months.day, INTERVAL -DAY(last_few_calendar_months.day)+1 DAY)) as month,\n\t\t\tMAX(if(_production_deployment_days.day is not null, 1, null)) as months_deployed,\n\t\t COUNT(distinct _production_deployment_days.day) as days_deployed\n\tFROM \n\t\tlast_few_calendar_months\n\t\tLEFT JOIN _production_deployment_days ON _production_deployment_days.day = last_few_calendar_months.day\n\tGROUP BY month\n\t),\n\n_days_six_months_deploy AS (\n SELECT\n month,\n SUM(days_deployed) OVER (\n ORDER BY month\n ROWS BETWEEN 5 PRECEDING AND CURRENT ROW\n ) AS days_deployed_per_six_months,\n COUNT(months_deployed) OVER (\n ORDER BY month\n ROWS BETWEEN 5 PRECEDING AND CURRENT ROW\n ) AS months_deployed_count,\n ROW_NUMBER() OVER (\n PARTITION BY DATE_FORMAT(month, '%Y-%m') DIV 6\n ORDER BY month DESC\n ) AS rn\n FROM _days_monthly_deploy\n),\n\n_median_number_of_deployment_days_per_week_ranks as(\n\tSELECT *, percent_rank() over(order by days_deployed) as ranks\n\tFROM _days_weekly_deploy\n),\n\n_median_number_of_deployment_days_per_week as(\n\tSELECT max(days_deployed) as median_number_of_deployment_days_per_week\n\tFROM _median_number_of_deployment_days_per_week_ranks\n\tWHERE ranks <= 0.5\n),\n\n_median_number_of_deployment_days_per_month_ranks as(\n\tSELECT *, percent_rank() over(order by days_deployed) as ranks\n\tFROM _days_monthly_deploy\n),\n\n_median_number_of_deployment_days_per_month as(\n\tSELECT max(days_deployed) as median_number_of_deployment_days_per_month\n\tFROM _median_number_of_deployment_days_per_month_ranks\n\tWHERE ranks <= 0.5\n),\n\n_days_per_six_months_deploy_by_filter AS (\nSELECT\n month,\n days_deployed_per_six_months,\n months_deployed_count\nFROM _days_six_months_deploy\nWHERE rn%6 = 1\n),\n\n\n_median_number_of_deployment_days_per_six_months_ranks as(\n\tSELECT *, percent_rank() over(order by days_deployed_per_six_months) as ranks\n\tFROM _days_per_six_months_deploy_by_filter\n),\n\n_median_number_of_deployment_days_per_six_months as(\n\tSELECT min(days_deployed_per_six_months) as median_number_of_deployment_days_per_six_months, min(months_deployed_count) as is_collected\n\tFROM _median_number_of_deployment_days_per_six_months_ranks\n\tWHERE ranks >= 0.5\n)\n\nSELECT \n CASE\n WHEN ('$dora_report') = '2023' THEN\n\t\t\tCASE \n\t\t\t\tWHEN median_number_of_deployment_days_per_week >= 5 THEN CONCAT(median_number_of_deployment_days_per_week, ' deployment days per week(elite)')\n\t\t\t\tWHEN median_number_of_deployment_days_per_week >= 1 THEN CONCAT(median_number_of_deployment_days_per_week, ' deployment days per week(high)')\n\t\t\t\tWHEN median_number_of_deployment_days_per_month >= 1 THEN CONCAT(median_number_of_deployment_days_per_month, ' deployment days per month(medium)')\n\t\t\t\tWHEN median_number_of_deployment_days_per_month < 1 and is_collected is not null THEN CONCAT(median_number_of_deployment_days_per_month, ' deployment days per month(low)')\n\t\t\t\tELSE \"N/A. Please check if you have collected deployments.\" END\n\t \tWHEN ('$dora_report') = '2021' THEN\n\t\t\tCASE \n\t\t\t\tWHEN median_number_of_deployment_days_per_week >= 5 THEN CONCAT(median_number_of_deployment_days_per_week, ' deployment days per week(elite)')\n\t\t\t\tWHEN median_number_of_deployment_days_per_month >= 1 THEN CONCAT(median_number_of_deployment_days_per_month, ' deployment days per month(high)')\n\t\t\t\tWHEN median_number_of_deployment_days_per_six_months >= 1 THEN CONCAT(median_number_of_deployment_days_per_six_months, ' deployment days per six months(medium)')\n\t\t\t\tWHEN median_number_of_deployment_days_per_six_months < 1 and is_collected is not null THEN CONCAT(median_number_of_deployment_days_per_six_months, ' deployment days per six months(low)')\n\t\t\t\tELSE \"N/A. Please check if you have collected deployments.\" END\n\t\tELSE 'Invalid dora report'\n\tEND AS 'Deployment Frequency'\nFROM _median_number_of_deployment_days_per_week, _median_number_of_deployment_days_per_month, _median_number_of_deployment_days_per_six_months\n", + "rawSql": "-- Metric 1: Deployment Frequency\nwith last_few_calendar_months as(\n-- construct the last few calendar months within the selected time period in the top-right corner\n\tSELECT CAST(($__timeTo()-INTERVAL (H+T+U) DAY) AS date) day\n\tFROM ( SELECT 0 H\n\t\t\tUNION ALL SELECT 100 UNION ALL SELECT 200 UNION ALL SELECT 300\n\t\t) H CROSS JOIN ( SELECT 0 T\n\t\t\tUNION ALL SELECT 10 UNION ALL SELECT 20 UNION ALL SELECT 30\n\t\t\tUNION ALL SELECT 40 UNION ALL SELECT 50 UNION ALL SELECT 60\n\t\t\tUNION ALL SELECT 70 UNION ALL SELECT 80 UNION ALL SELECT 90\n\t\t) T CROSS JOIN ( SELECT 0 U\n\t\t\tUNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3\n\t\t\tUNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6\n\t\t\tUNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9\n\t\t) U\n\tWHERE\n\t\t($__timeTo()-INTERVAL (H+T+U) DAY) > $__timeFrom()\n),\n\n_production_deployment_days as(\n-- When deploying multiple commits in one pipeline, GitLab and BitBucket may generate more than one deployment. However, DevLake consider these deployments as ONE production deployment and use the last one's finished_date as the finished date.\n\tSELECT\n\t\tcdc.cicd_deployment_id as deployment_id,\n\t\tmax(DATE(cdc.finished_date)) as day\n\tFROM cicd_deployment_commits cdc\n\tJOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id and pm.`table` = 'cicd_scopes'\n\tJOIN project_pr_metrics ppm on cdc.id = ppm.deployment_commit_id\n\tWHERE\n\t\tpm.project_name in (${project})\n\t\tand cdc.result = 'SUCCESS'\n\t\tand cdc.environment = 'PRODUCTION'\n\t\tand (ppm.is_authored_by_bot is null or ppm.is_authored_by_bot in (${author_type}))\n\tGROUP BY 1\n),\n\n_days_weekly_deploy as(\n-- calculate the number of deployment days every week\n\tSELECT\n\t\t\tdate(DATE_ADD(last_few_calendar_months.day, INTERVAL -WEEKDAY(last_few_calendar_months.day) DAY)) as week,\n\t\t\tMAX(if(_production_deployment_days.day is not null, 1, null)) as weeks_deployed,\n\t\t\tCOUNT(distinct _production_deployment_days.day) as days_deployed\n\tFROM \n\t\tlast_few_calendar_months\n\t\tLEFT JOIN _production_deployment_days ON _production_deployment_days.day = last_few_calendar_months.day\n\tGROUP BY week\n\t),\n\n_days_monthly_deploy as(\n-- calculate the number of deployment days every month\n\tSELECT\n\t\t\tdate(DATE_ADD(last_few_calendar_months.day, INTERVAL -DAY(last_few_calendar_months.day)+1 DAY)) as month,\n\t\t\tMAX(if(_production_deployment_days.day is not null, 1, null)) as months_deployed,\n\t\t COUNT(distinct _production_deployment_days.day) as days_deployed\n\tFROM \n\t\tlast_few_calendar_months\n\t\tLEFT JOIN _production_deployment_days ON _production_deployment_days.day = last_few_calendar_months.day\n\tGROUP BY month\n\t),\n\n_days_six_months_deploy AS (\n SELECT\n month,\n SUM(days_deployed) OVER (\n ORDER BY month\n ROWS BETWEEN 5 PRECEDING AND CURRENT ROW\n ) AS days_deployed_per_six_months,\n COUNT(months_deployed) OVER (\n ORDER BY month\n ROWS BETWEEN 5 PRECEDING AND CURRENT ROW\n ) AS months_deployed_count,\n ROW_NUMBER() OVER (\n PARTITION BY DATE_FORMAT(month, '%Y-%m') DIV 6\n ORDER BY month DESC\n ) AS rn\n FROM _days_monthly_deploy\n),\n\n_median_number_of_deployment_days_per_week_ranks as(\n\tSELECT *, percent_rank() over(order by days_deployed) as ranks\n\tFROM _days_weekly_deploy\n),\n\n_median_number_of_deployment_days_per_week as(\n\tSELECT max(days_deployed) as median_number_of_deployment_days_per_week\n\tFROM _median_number_of_deployment_days_per_week_ranks\n\tWHERE ranks <= 0.5\n),\n\n_median_number_of_deployment_days_per_month_ranks as(\n\tSELECT *, percent_rank() over(order by days_deployed) as ranks\n\tFROM _days_monthly_deploy\n),\n\n_median_number_of_deployment_days_per_month as(\n\tSELECT max(days_deployed) as median_number_of_deployment_days_per_month\n\tFROM _median_number_of_deployment_days_per_month_ranks\n\tWHERE ranks <= 0.5\n),\n\n_days_per_six_months_deploy_by_filter AS (\nSELECT\n month,\n days_deployed_per_six_months,\n months_deployed_count\nFROM _days_six_months_deploy\nWHERE rn%6 = 1\n),\n\n\n_median_number_of_deployment_days_per_six_months_ranks as(\n\tSELECT *, percent_rank() over(order by days_deployed_per_six_months) as ranks\n\tFROM _days_per_six_months_deploy_by_filter\n),\n\n_median_number_of_deployment_days_per_six_months as(\n\tSELECT min(days_deployed_per_six_months) as median_number_of_deployment_days_per_six_months, min(months_deployed_count) as is_collected\n\tFROM _median_number_of_deployment_days_per_six_months_ranks\n\tWHERE ranks >= 0.5\n)\n\nSELECT \n CASE\n WHEN ('$dora_report') = '2023' THEN\n\t\t\tCASE \n\t\t\t\tWHEN median_number_of_deployment_days_per_week >= 5 THEN CONCAT(median_number_of_deployment_days_per_week, ' deployment days per week(elite)')\n\t\t\t\tWHEN median_number_of_deployment_days_per_week >= 1 THEN CONCAT(median_number_of_deployment_days_per_week, ' deployment days per week(high)')\n\t\t\t\tWHEN median_number_of_deployment_days_per_month >= 1 THEN CONCAT(median_number_of_deployment_days_per_month, ' deployment days per month(medium)')\n\t\t\t\tWHEN median_number_of_deployment_days_per_month < 1 and is_collected is not null THEN CONCAT(median_number_of_deployment_days_per_month, ' deployment days per month(low)')\n\t\t\t\tELSE \"N/A. Please check if you have collected deployments.\" END\n\t \tWHEN ('$dora_report') = '2021' THEN\n\t\t\tCASE \n\t\t\t\tWHEN median_number_of_deployment_days_per_week >= 5 THEN CONCAT(median_number_of_deployment_days_per_week, ' deployment days per week(elite)')\n\t\t\t\tWHEN median_number_of_deployment_days_per_month >= 1 THEN CONCAT(median_number_of_deployment_days_per_month, ' deployment days per month(high)')\n\t\t\t\tWHEN median_number_of_deployment_days_per_six_months >= 1 THEN CONCAT(median_number_of_deployment_days_per_six_months, ' deployment days per six months(medium)')\n\t\t\t\tWHEN median_number_of_deployment_days_per_six_months < 1 and is_collected is not null THEN CONCAT(median_number_of_deployment_days_per_six_months, ' deployment days per six months(low)')\n\t\t\t\tELSE \"N/A. Please check if you have collected deployments.\" END\n\t\tELSE 'Invalid dora report'\n\tEND AS 'Deployment Frequency'\nFROM _median_number_of_deployment_days_per_week, _median_number_of_deployment_days_per_month, _median_number_of_deployment_days_per_six_months\n", "refId": "A", "select": [ [ @@ -496,7 +496,7 @@ "links": [ { "title": "link", - "url": "/d/Lead-time-for-changes/dora-drill-down-lead-time-for-changes?orgId=1&${project:queryparam}&from=${__from}&to=${__to}" + "url": "/d/Lead-time-for-changes/dora-drill-down-lead-time-for-changes?orgId=1&${project:queryparam}&${author_type:queryparam}&from=${__from}&to=${__to}" } ], "options": { @@ -526,7 +526,7 @@ "metricColumn": "none", "queryType": "randomWalk", "rawQuery": true, - "rawSql": "-- Metric 2: median lead time for changes\nwith _pr_stats as (\n-- get the cycle time of PRs deployed by the deployments finished in the selected period\n\tSELECT\n\t\tdistinct pr.id,\n\t\tppm.pr_cycle_time\n\tFROM\n\t\tpull_requests pr \n\t\tjoin project_pr_metrics ppm on ppm.id = pr.id\n\t\tjoin project_mapping pm on pr.base_repo_id = pm.row_id and pm.`table` = 'repos'\n\t\tjoin cicd_deployment_commits cdc on ppm.deployment_commit_id = cdc.id\n\tWHERE\n\t pm.project_name in (${project}) \n\t\tand pr.merged_date is not null\n\t\tand ppm.pr_cycle_time is not null\n\t\tand $__timeFilter(cdc.finished_date)\n),\n\n_median_change_lead_time_ranks as(\n\tSELECT *, percent_rank() over(order by pr_cycle_time) as ranks\n\tFROM _pr_stats\n),\n\n_median_change_lead_time as(\n-- use median PR cycle time as the median change lead time\n\tSELECT max(pr_cycle_time) as median_change_lead_time\n\tFROM _median_change_lead_time_ranks\n\tWHERE ranks <= 0.5\n)\n\nSELECT \n CASE\n WHEN ('$dora_report') = '2023' THEN\n\t\t\tCASE\n\t\t\t\tWHEN median_change_lead_time < 24 * 60 THEN CONCAT(round(median_change_lead_time/60,1), \"(elite)\")\n\t\t\t\tWHEN median_change_lead_time < 7 * 24 * 60 THEN CONCAT(round(median_change_lead_time/60,1), \"(high)\")\n\t\t\t\tWHEN median_change_lead_time < 30 * 24 * 60 THEN CONCAT(round(median_change_lead_time/60,1), \"(medium)\")\n\t\t\t\tWHEN median_change_lead_time >= 30 * 24 * 60 THEN CONCAT(round(median_change_lead_time/60,1), \"(low)\")\n\t\t\t\tELSE \"N/A. Please check if you have collected deployments/pull_requests.\"\n\t\t\t\tEND\n WHEN ('$dora_report') = '2021' THEN\n\t\t CASE\n\t\t\t\tWHEN median_change_lead_time < 60 THEN CONCAT(round(median_change_lead_time/60,1), \"(elite)\")\n\t\t\t\tWHEN median_change_lead_time < 7 * 24 * 60 THEN CONCAT(round(median_change_lead_time/60,1), \"(high)\")\n\t\t\t\tWHEN median_change_lead_time < 180 * 24 * 60 THEN CONCAT(round(median_change_lead_time/60,1), \"(medium)\")\n\t\t\t\tWHEN median_change_lead_time >= 180 * 24 * 60 THEN CONCAT(round(median_change_lead_time/60,1), \"(low)\")\n\t\t\t\tELSE \"N/A. Please check if you have collected deployments/pull_requests.\"\n\t\t\t\tEND\n\t\tELSE 'Invalid dora report'\n\tEND AS median_change_lead_time\nFROM _median_change_lead_time", + "rawSql": "-- Metric 2: median lead time for changes\nwith _pr_stats as (\n-- get the cycle time of PRs deployed by the deployments finished in the selected period\n\tSELECT\n\t\tdistinct pr.id,\n\t\tppm.pr_cycle_time\n\tFROM\n\t\tpull_requests pr \n\t\tjoin project_pr_metrics ppm on ppm.id = pr.id\n\t\tjoin project_mapping pm on pr.base_repo_id = pm.row_id and pm.`table` = 'repos'\n\t\tjoin cicd_deployment_commits cdc on ppm.deployment_commit_id = cdc.id\n\tWHERE\n\t pm.project_name in (${project}) \n\t\tand pr.merged_date is not null\n\t\tand ppm.pr_cycle_time is not null\n\t\tand (ppm.is_authored_by_bot is null or ppm.is_authored_by_bot in (${author_type}))\n\t\tand $__timeFilter(cdc.finished_date)\n),\n\n_median_change_lead_time_ranks as(\n\tSELECT *, percent_rank() over(order by pr_cycle_time) as ranks\n\tFROM _pr_stats\n),\n\n_median_change_lead_time as(\n-- use median PR cycle time as the median change lead time\n\tSELECT max(pr_cycle_time) as median_change_lead_time\n\tFROM _median_change_lead_time_ranks\n\tWHERE ranks <= 0.5\n)\n\nSELECT \n CASE\n WHEN ('$dora_report') = '2023' THEN\n\t\t\tCASE\n\t\t\t\tWHEN median_change_lead_time < 24 * 60 THEN CONCAT(round(median_change_lead_time/60,1), \"(elite)\")\n\t\t\t\tWHEN median_change_lead_time < 7 * 24 * 60 THEN CONCAT(round(median_change_lead_time/60,1), \"(high)\")\n\t\t\t\tWHEN median_change_lead_time < 30 * 24 * 60 THEN CONCAT(round(median_change_lead_time/60,1), \"(medium)\")\n\t\t\t\tWHEN median_change_lead_time >= 30 * 24 * 60 THEN CONCAT(round(median_change_lead_time/60,1), \"(low)\")\n\t\t\t\tELSE \"N/A. Please check if you have collected deployments/pull_requests.\"\n\t\t\t\tEND\n WHEN ('$dora_report') = '2021' THEN\n\t\t CASE\n\t\t\t\tWHEN median_change_lead_time < 60 THEN CONCAT(round(median_change_lead_time/60,1), \"(elite)\")\n\t\t\t\tWHEN median_change_lead_time < 7 * 24 * 60 THEN CONCAT(round(median_change_lead_time/60,1), \"(high)\")\n\t\t\t\tWHEN median_change_lead_time < 180 * 24 * 60 THEN CONCAT(round(median_change_lead_time/60,1), \"(medium)\")\n\t\t\t\tWHEN median_change_lead_time >= 180 * 24 * 60 THEN CONCAT(round(median_change_lead_time/60,1), \"(low)\")\n\t\t\t\tELSE \"N/A. Please check if you have collected deployments/pull_requests.\"\n\t\t\t\tEND\n\t\tELSE 'Invalid dora report'\n\tEND AS median_change_lead_time\nFROM _median_change_lead_time", "refId": "A", "select": [ [ @@ -643,7 +643,7 @@ "links": [ { "title": "link", - "url": "/d/Change-failure-rate/dora-drill-down-change-failure-rate?orgId=1&${project:queryparam}&from=${__from}&to=${__to}" + "url": "/d/Change-failure-rate/dora-drill-down-change-failure-rate?orgId=1&${project:queryparam}&${author_type:queryparam}&from=${__from}&to=${__to}" } ], "options": { @@ -673,7 +673,7 @@ "metricColumn": "none", "queryType": "randomWalk", "rawQuery": true, - "rawSql": "-- Metric 3: change failure rate\nwith _deployments as (\n -- When deploying multiple commits in one pipeline, GitLab and BitBucket may generate more than one deployment. However, DevLake consider these deployments as ONE production deployment and use the last one's finished_date as the finished date.\n SELECT\n cdc.cicd_deployment_id as deployment_id,\n max(cdc.finished_date) as deployment_finished_date\n FROM\n cicd_deployment_commits cdc\n JOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id\n and pm.`table` = 'cicd_scopes'\n WHERE\n pm.project_name in (${project})\n and cdc.result = 'SUCCESS'\n and cdc.environment = 'PRODUCTION'\n GROUP BY\n 1\n HAVING\n $__timeFilter(max(cdc.finished_date))\n),\n_failure_caused_by_deployments as (\n -- calculate the number of incidents caused by each deployment\n SELECT\n d.deployment_id,\n d.deployment_finished_date,\n count(\n distinct case\n when i.id is not null then d.deployment_id\n else null\n end\n ) as has_incident\n FROM\n _deployments d\n left join project_incident_deployment_relationships pim on d.deployment_id = pim.deployment_id\n left join incidents i on pim.id = i.id\n GROUP BY\n 1,\n 2\n),\n_change_failure_rate as (\n SELECT\n case\n when count(deployment_id) is null then null\n else sum(has_incident) / count(deployment_id)\n end as change_failure_rate\n FROM\n _failure_caused_by_deployments\n),\n_is_collected_data as(\n SELECT\n CASE\n WHEN COUNT(i.id) = 0\n AND COUNT(cdc.id) = 0 THEN 'No All'\n WHEN COUNT(i.id) = 0 THEN 'No Incidents'\n WHEN COUNT(cdc.id) = 0 THEN 'No Deployments'\n END AS is_collected\n FROM\n (\n SELECT\n 1\n ) AS dummy\n LEFT JOIN incidents i ON 1 = 1\n LEFT JOIN cicd_deployment_commits cdc ON 1 = 1\n)\nSELECT\n CASE\n WHEN ('$dora_report') = '2023' THEN CASE\n WHEN is_collected = \"No All\" THEN \"N/A. Please check if you have collected deployments/incidents.\"\n WHEN is_collected = \"No Incidents\" THEN \"N/A. Please check if you have collected incidents.\"\n WHEN is_collected = \"No Deployments\" THEN \"N/A. Please check if you have collected deployments.\"\n WHEN change_failure_rate <=.05 THEN CONCAT(round(change_failure_rate * 100, 1), \"%(elite)\")\n WHEN change_failure_rate <=.10 THEN CONCAT(round(change_failure_rate * 100, 1), \"%(high)\")\n WHEN change_failure_rate <=.15 THEN CONCAT(round(change_failure_rate * 100, 1), \"%(medium)\")\n WHEN change_failure_rate >.15 THEN CONCAT(round(change_failure_rate * 100, 1), \"%(low)\")\n ELSE \"N/A. Please check if you have collected deployments/incidents.\"\n END\n WHEN ('$dora_report') = '2021' THEN CASE\n WHEN is_collected = \"No All\" THEN \"N/A. Please check if you have collected deployments/incidents.\"\n WHEN is_collected = \"No Incidents\" THEN \"N/A. Please check if you have collected incidents.\"\n WHEN is_collected = \"No Deployments\" THEN \"N/A. Please check if you have collected deployments.\"\n WHEN change_failure_rate <=.15 THEN CONCAT(round(change_failure_rate * 100, 1), \"%(elite)\")\n WHEN change_failure_rate <=.20 THEN CONCAT(round(change_failure_rate * 100, 1), \"%(high)\")\n WHEN change_failure_rate <=.30 THEN CONCAT(round(change_failure_rate * 100, 1), \"%(medium)\")\n WHEN change_failure_rate >.30 THEN CONCAT(round(change_failure_rate * 100, 1), \"%(low)\")\n ELSE \"N/A. Please check if you have collected deployments/incidents.\"\n END\n ELSE 'No data'\n END AS change_failure_rate\nFROM\n _change_failure_rate,\n _is_collected_data", + "rawSql": "-- Metric 3: change failure rate\nwith _deployments as (\n -- When deploying multiple commits in one pipeline, GitLab and BitBucket may generate more than one deployment. However, DevLake consider these deployments as ONE production deployment and use the last one's finished_date as the finished date.\n SELECT\n cdc.cicd_deployment_id as deployment_id,\n max(cdc.finished_date) as deployment_finished_date\n FROM\n cicd_deployment_commits cdc\n JOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id\n JOIN project_pr_metrics ppm on cdc.id = ppm.deployment_commit_id\n and pm.`table` = 'cicd_scopes'\n and (ppm.is_authored_by_bot is null or ppm.is_authored_by_bot in (${author_type}))\n WHERE\n pm.project_name in (${project})\n and cdc.result = 'SUCCESS'\n and cdc.environment = 'PRODUCTION'\n GROUP BY\n 1\n HAVING\n $__timeFilter(max(cdc.finished_date))\n),\n_failure_caused_by_deployments as (\n -- calculate the number of incidents caused by each deployment\n SELECT\n d.deployment_id,\n d.deployment_finished_date,\n count(\n distinct case\n when i.id is not null then d.deployment_id\n else null\n end\n ) as has_incident\n FROM\n _deployments d\n left join project_incident_deployment_relationships pim on d.deployment_id = pim.deployment_id\n left join incidents i on pim.id = i.id\n GROUP BY\n 1,\n 2\n),\n_change_failure_rate as (\n SELECT\n case\n when count(deployment_id) is null then null\n else sum(has_incident) / count(deployment_id)\n end as change_failure_rate\n FROM\n _failure_caused_by_deployments\n),\n_is_collected_data as(\n SELECT\n CASE\n WHEN COUNT(i.id) = 0\n AND COUNT(cdc.id) = 0 THEN 'No All'\n WHEN COUNT(i.id) = 0 THEN 'No Incidents'\n WHEN COUNT(cdc.id) = 0 THEN 'No Deployments'\n END AS is_collected\n FROM\n (\n SELECT\n 1\n ) AS dummy\n LEFT JOIN incidents i ON 1 = 1\n LEFT JOIN cicd_deployment_commits cdc ON 1 = 1\n)\nSELECT\n CASE\n WHEN ('$dora_report') = '2023' THEN CASE\n WHEN is_collected = \"No All\" THEN \"N/A. Please check if you have collected deployments/incidents.\"\n WHEN is_collected = \"No Incidents\" THEN \"N/A. Please check if you have collected incidents.\"\n WHEN is_collected = \"No Deployments\" THEN \"N/A. Please check if you have collected deployments.\"\n WHEN change_failure_rate <=.05 THEN CONCAT(round(change_failure_rate * 100, 1), \"%(elite)\")\n WHEN change_failure_rate <=.10 THEN CONCAT(round(change_failure_rate * 100, 1), \"%(high)\")\n WHEN change_failure_rate <=.15 THEN CONCAT(round(change_failure_rate * 100, 1), \"%(medium)\")\n WHEN change_failure_rate >.15 THEN CONCAT(round(change_failure_rate * 100, 1), \"%(low)\")\n ELSE \"N/A. Please check if you have collected deployments/incidents.\"\n END\n WHEN ('$dora_report') = '2021' THEN CASE\n WHEN is_collected = \"No All\" THEN \"N/A. Please check if you have collected deployments/incidents.\"\n WHEN is_collected = \"No Incidents\" THEN \"N/A. Please check if you have collected incidents.\"\n WHEN is_collected = \"No Deployments\" THEN \"N/A. Please check if you have collected deployments.\"\n WHEN change_failure_rate <=.15 THEN CONCAT(round(change_failure_rate * 100, 1), \"%(elite)\")\n WHEN change_failure_rate <=.20 THEN CONCAT(round(change_failure_rate * 100, 1), \"%(high)\")\n WHEN change_failure_rate <=.30 THEN CONCAT(round(change_failure_rate * 100, 1), \"%(medium)\")\n WHEN change_failure_rate >.30 THEN CONCAT(round(change_failure_rate * 100, 1), \"%(low)\")\n ELSE \"N/A. Please check if you have collected deployments/incidents.\"\n END\n ELSE 'No data'\n END AS change_failure_rate\nFROM\n _change_failure_rate,\n _is_collected_data", "refId": "A", "select": [ [ @@ -793,11 +793,11 @@ "links": [ { "title": "Failed Deployment Recovery Time", - "url": "/d/Failed-deployment-recovery-time/dora-details-failed-deployment-recovery-time?orgId=1&${project:queryparam}&from=${__from}&to=${__to}" + "url": "/d/Failed-deployment-recovery-time/dora-details-failed-deployment-recovery-time?orgId=1&${project:queryparam}&${author_type:queryparam}&from=${__from}&to=${__to}" }, { "title": "Median Time to Restore Service", - "url": "/d/Time-to-restore-service/dora-details-median-time-to-restore-service?orgId=1&${project:queryparam}&from=${__from}&to=${__to}" + "url": "/d/Time-to-restore-service/dora-details-median-time-to-restore-service?orgId=1&${project:queryparam}&${author_type:queryparam}&from=${__from}&to=${__to}" } ], "options": { @@ -827,7 +827,7 @@ "metricColumn": "none", "queryType": "randomWalk", "rawQuery": true, - "rawSql": "-- ***** 2023 report ***** --\n-- Metric 4: Failed deployment recovery time\nwith _deployments as (\n SELECT\n cdc.cicd_deployment_id as deployment_id,\n max(cdc.finished_date) as deployment_finished_date\n FROM\n cicd_deployment_commits cdc\n JOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id\n and pm.`table` = 'cicd_scopes'\n WHERE\n pm.project_name in ($project)\n and cdc.result = 'SUCCESS'\n and cdc.environment = 'PRODUCTION'\n GROUP BY\n 1\n HAVING\n $__timeFilter(max(cdc.finished_date))\n),\n_incidents_for_deployments as (\n SELECT\n i.id as incident_id,\n i.created_date as incident_create_date,\n i.resolution_date as incident_resolution_date,\n fd.deployment_id as caused_by_deployment,\n fd.deployment_finished_date,\n date_format(fd.deployment_finished_date, '%y/%m') as deployment_finished_month\n FROM\n incidents i\n left join project_incident_deployment_relationships pim on i.id = pim.id\n join _deployments fd on pim.deployment_id = fd.deployment_id\n WHERE\n $__timeFilter(i.resolution_date)\n),\n_recovery_time_ranks as (\n SELECT\n *,\n percent_rank() over(\n order by\n TIMESTAMPDIFF(\n MINUTE,\n deployment_finished_date,\n incident_resolution_date\n )\n ) as ranks\n FROM\n _incidents_for_deployments\n),\n_median_recovery_time as (\n SELECT\n max(\n TIMESTAMPDIFF(\n MINUTE,\n deployment_finished_date,\n incident_resolution_date\n )\n ) as median_recovery_time\n FROM\n _recovery_time_ranks\n WHERE\n ranks <= 0.5\n),\n\n_is_collected_data as(\n SELECT\n CASE\n WHEN EXISTS(select COUNT(d.deployment_id) from _deployments) = 0 AND EXISTS(select COUNT(i.incident_id) FROM incidents) = 0 THEN 'No deployments and incidents'\n WHEN EXISTS(select COUNT(d.deployment_id) from _deployments) = 0 THEN 'No Deployments'\n WHEN EXISTS(select COUNT(i.incident_id) FROM incidents) = 0 THEN 'No Incidents'\n Else 'No incidents are mapped to deployments'\n END AS is_collected\n FROM\n _deployments d, _incidents_for_deployments i\n),\n\n_metric_recovery_time_2023_report as(\n SELECT\n CASE\n WHEN ('$dora_report') = '2023' THEN CASE\n WHEN is_collected = \"No deployments and incidents\" THEN \"N/A. Please check if you have collected deployments and incidents.\"\n WHEN is_collected = \"No Deployments\" THEN \"N/A. Please check if you have collected deployments.\"\n WHEN is_collected = \"No Incidents\" THEN \"N/A. Please check if you have collected incidents.\"\n WHEN median_recovery_time < 60 THEN CONCAT(round(median_recovery_time / 60, 1), \"(elite)\")\n WHEN median_recovery_time < 24 * 60 THEN CONCAT(round(median_recovery_time / 60, 1), \"(high)\")\n WHEN median_recovery_time < 7 * 24 * 60 THEN CONCAT(round(median_recovery_time / 60, 1), \"(medium)\")\n WHEN median_recovery_time >= 7 * 24 * 60 THEN CONCAT(round(median_recovery_time / 60, 1), \"(low)\")\n ELSE \"No data\"\n END\n END AS median_recovery_time\n FROM\n _median_recovery_time,\n _is_collected_data\n),\n-- ***** 2021 report ***** --\n-- Metric 4: Median time to restore service \n_incidents as (\n -- get the incidents created within the selected time period in the top-right corner\n SELECT\n distinct i.id,\n cast(lead_time_minutes as signed) as lead_time_minutes\n FROM\n incidents i\n join project_mapping pm on i.scope_id = pm.row_id\n and pm.`table` = i.`table`\n WHERE\n pm.project_name in (${project})\n and $__timeFilter(i.resolution_date)\n),\n_median_mttr_ranks as(\n SELECT\n *,\n percent_rank() over(\n order by\n lead_time_minutes\n ) as ranks\n FROM\n _incidents\n),\n_median_mttr as(\n SELECT\n max(lead_time_minutes) as median_time_to_resolve\n FROM\n _median_mttr_ranks\n WHERE\n ranks <= 0.5\n),\n_metric_mttr_2021_report as(\n SELECT\n CASE\n WHEN ('$dora_report') = '2021' THEN CASE\n WHEN median_time_to_resolve < 60 THEN CONCAT(round(median_time_to_resolve / 60, 1), \"(elite)\")\n WHEN median_time_to_resolve < 24 * 60 THEN CONCAT(round(median_time_to_resolve / 60, 1), \"(high)\")\n WHEN median_time_to_resolve < 7 * 24 * 60 THEN CONCAT(\n round(median_time_to_resolve / 60, 1),\n \"(medium)\"\n )\n WHEN median_time_to_resolve >= 7 * 24 * 60 THEN CONCAT(round(median_time_to_resolve / 60, 1), \"(low)\")\n ELSE \"N/A. Please check if you have collected incidents.\"\n END\n END AS median_time_to_resolve\n FROM\n _median_mttr\n)\nSELECT\n median_recovery_time AS median_time_in_hour\nFROM\n _metric_recovery_time_2023_report\nWHERE\n ('$dora_report') = '2023'\nUNION\nSELECT\n median_time_to_resolve AS median_time_to_resolve\nFROM\n _metric_mttr_2021_report\nWHERE\n ('$dora_report') = '2021'", + "rawSql": "-- ***** 2023 report ***** --\n-- Metric 4: Failed deployment recovery time\nwith _deployments as (\n SELECT\n cdc.cicd_deployment_id as deployment_id,\n max(cdc.finished_date) as deployment_finished_date\n FROM\n cicd_deployment_commits cdc\n JOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id\n JOIN project_pr_metrics ppm on cdc.id = ppm.deployment_commit_id\n and pm.`table` = 'cicd_scopes'\n and (ppm.is_authored_by_bot is null or ppm.is_authored_by_bot in (${author_type}))\n WHERE\n pm.project_name in ($project)\n and cdc.result = 'SUCCESS'\n and cdc.environment = 'PRODUCTION'\n GROUP BY\n 1\n HAVING\n $__timeFilter(max(cdc.finished_date))\n),\n_incidents_for_deployments as (\n SELECT\n i.id as incident_id,\n i.created_date as incident_create_date,\n i.resolution_date as incident_resolution_date,\n fd.deployment_id as caused_by_deployment,\n fd.deployment_finished_date,\n date_format(fd.deployment_finished_date, '%y/%m') as deployment_finished_month\n FROM\n incidents i\n left join project_incident_deployment_relationships pim on i.id = pim.id\n join _deployments fd on pim.deployment_id = fd.deployment_id\n WHERE\n $__timeFilter(i.resolution_date)\n),\n_recovery_time_ranks as (\n SELECT\n *,\n percent_rank() over(\n order by\n TIMESTAMPDIFF(\n MINUTE,\n deployment_finished_date,\n incident_resolution_date\n )\n ) as ranks\n FROM\n _incidents_for_deployments\n),\n_median_recovery_time as (\n SELECT\n max(\n TIMESTAMPDIFF(\n MINUTE,\n deployment_finished_date,\n incident_resolution_date\n )\n ) as median_recovery_time\n FROM\n _recovery_time_ranks\n WHERE\n ranks <= 0.5\n),\n\n_is_collected_data as(\n SELECT\n CASE\n WHEN EXISTS(select COUNT(d.deployment_id) from _deployments) = 0 AND EXISTS(select COUNT(i.incident_id) FROM incidents) = 0 THEN 'No deployments and incidents'\n WHEN EXISTS(select COUNT(d.deployment_id) from _deployments) = 0 THEN 'No Deployments'\n WHEN EXISTS(select COUNT(i.incident_id) FROM incidents) = 0 THEN 'No Incidents'\n Else 'No incidents are mapped to deployments'\n END AS is_collected\n FROM\n _deployments d, _incidents_for_deployments i\n),\n\n_metric_recovery_time_2023_report as(\n SELECT\n CASE\n WHEN ('$dora_report') = '2023' THEN CASE\n WHEN is_collected = \"No deployments and incidents\" THEN \"N/A. Please check if you have collected deployments and incidents.\"\n WHEN is_collected = \"No Deployments\" THEN \"N/A. Please check if you have collected deployments.\"\n WHEN is_collected = \"No Incidents\" THEN \"N/A. Please check if you have collected incidents.\"\n WHEN median_recovery_time < 60 THEN CONCAT(round(median_recovery_time / 60, 1), \"(elite)\")\n WHEN median_recovery_time < 24 * 60 THEN CONCAT(round(median_recovery_time / 60, 1), \"(high)\")\n WHEN median_recovery_time < 7 * 24 * 60 THEN CONCAT(round(median_recovery_time / 60, 1), \"(medium)\")\n WHEN median_recovery_time >= 7 * 24 * 60 THEN CONCAT(round(median_recovery_time / 60, 1), \"(low)\")\n ELSE \"No data\"\n END\n END AS median_recovery_time\n FROM\n _median_recovery_time,\n _is_collected_data\n),\n-- ***** 2021 report ***** --\n-- Metric 4: Median time to restore service \n_incidents as (\n -- get the incidents created within the selected time period in the top-right corner\n SELECT\n distinct i.id,\n cast(lead_time_minutes as signed) as lead_time_minutes\n FROM\n incidents i\n join project_mapping pm on i.scope_id = pm.row_id\n and pm.`table` = i.`table`\n WHERE\n pm.project_name in (${project})\n and $__timeFilter(i.resolution_date)\n),\n_median_mttr_ranks as(\n SELECT\n *,\n percent_rank() over(\n order by\n lead_time_minutes\n ) as ranks\n FROM\n _incidents\n),\n_median_mttr as(\n SELECT\n max(lead_time_minutes) as median_time_to_resolve\n FROM\n _median_mttr_ranks\n WHERE\n ranks <= 0.5\n),\n_metric_mttr_2021_report as(\n SELECT\n CASE\n WHEN ('$dora_report') = '2021' THEN CASE\n WHEN median_time_to_resolve < 60 THEN CONCAT(round(median_time_to_resolve / 60, 1), \"(elite)\")\n WHEN median_time_to_resolve < 24 * 60 THEN CONCAT(round(median_time_to_resolve / 60, 1), \"(high)\")\n WHEN median_time_to_resolve < 7 * 24 * 60 THEN CONCAT(\n round(median_time_to_resolve / 60, 1),\n \"(medium)\"\n )\n WHEN median_time_to_resolve >= 7 * 24 * 60 THEN CONCAT(round(median_time_to_resolve / 60, 1), \"(low)\")\n ELSE \"N/A. Please check if you have collected incidents.\"\n END\n END AS median_time_to_resolve\n FROM\n _median_mttr\n)\nSELECT\n median_recovery_time AS median_time_in_hour\nFROM\n _metric_recovery_time_2023_report\nWHERE\n ('$dora_report') = '2023'\nUNION\nSELECT\n median_time_to_resolve AS median_time_to_resolve\nFROM\n _metric_mttr_2021_report\nWHERE\n ('$dora_report') = '2021'", "refId": "A", "select": [ [ @@ -927,7 +927,7 @@ "links": [ { "title": "link", - "url": "/d/Deployment-frequency/dora-drill-down-deployment-frequency?orgId=1&${project:queryparam}&from=${__from}&to=${__to}" + "url": "/d/Deployment-frequency/dora-drill-down-deployment-frequency?orgId=1&${project:queryparam}&${author_type:queryparam}&from=${__from}&to=${__to}" } ], "options": { @@ -962,7 +962,7 @@ "metricColumn": "none", "queryType": "randomWalk", "rawQuery": true, - "rawSql": "-- Metric 1: Number of deployments per month\nwith _deployments as(\n-- When deploying multiple commits in one pipeline, GitLab and BitBucket may generate more than one deployment. However, DevLake consider these deployments as ONE production deployment and use the last one's finished_date as the finished date.\n\tSELECT \n\t\tdate_format(deployment_finished_date,'%y/%m') as month,\n\t\tcount(cicd_deployment_id) as deployment_count\n\tFROM (\n\t\tSELECT\n\t\t\tcdc.cicd_deployment_id,\n\t\t\tmax(cdc.finished_date) as deployment_finished_date\n\t\tFROM cicd_deployment_commits cdc\n\t\tJOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id and pm.`table` = 'cicd_scopes'\n\t\tWHERE\n\t\t\tpm.project_name in (${project})\n\t\t\tand cdc.result = 'SUCCESS'\n\t\t\tand cdc.environment = 'PRODUCTION'\n\t\tGROUP BY 1\n\t\tHAVING $__timeFilter(max(cdc.finished_date))\n\t) _production_deployments\n\tGROUP BY 1\n)\n\nSELECT \n\tcm.month, \n\tcase when d.deployment_count is null then 0 else d.deployment_count end as 'Deployment Count'\nFROM \n\tcalendar_months cm\n\tLEFT JOIN _deployments d on cm.month = d.month\n\tWHERE month_timestamp between DATE(DATE_FORMAT($__timeFrom(), '%Y-%m-01')) AND DATE(DATE_FORMAT($__timeTo(), '%Y-%m-01'))", + "rawSql": "-- Metric 1: Number of deployments per month\nwith _deployments as(\n-- When deploying multiple commits in one pipeline, GitLab and BitBucket may generate more than one deployment. However, DevLake consider these deployments as ONE production deployment and use the last one's finished_date as the finished date.\n\tSELECT \n\t\tdate_format(deployment_finished_date,'%y/%m') as month,\n\t\tcount(cicd_deployment_id) as deployment_count\n\tFROM (\n\t\tSELECT\n\t\t\tcdc.cicd_deployment_id,\n\t\t\tmax(cdc.finished_date) as deployment_finished_date\n\t\tFROM cicd_deployment_commits cdc\n\t\tJOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id and pm.`table` = 'cicd_scopes'\n\t\tJOIN project_pr_metrics ppm on cdc.id = ppm.deployment_commit_id\n\t\tWHERE\n\t\t\tpm.project_name in (${project})\n\t\t\tand cdc.result = 'SUCCESS'\n\t\t\tand cdc.environment = 'PRODUCTION'\n\t\t\tand (ppm.is_authored_by_bot is null or ppm.is_authored_by_bot in (${author_type}))\n\t\tGROUP BY 1\n\t\tHAVING $__timeFilter(max(cdc.finished_date))\n\t) _production_deployments\n\tGROUP BY 1\n)\n\nSELECT \n\tcm.month, \n\tcase when d.deployment_count is null then 0 else d.deployment_count end as 'Deployment Count'\nFROM \n\tcalendar_months cm\n\tLEFT JOIN _deployments d on cm.month = d.month\n\tWHERE month_timestamp between DATE(DATE_FORMAT($__timeFrom(), '%Y-%m-01')) AND DATE(DATE_FORMAT($__timeTo(), '%Y-%m-01'))", "refId": "A", "select": [ [ @@ -1059,7 +1059,7 @@ "links": [ { "title": "link", - "url": "/d/Lead-time-for-changes/dora-drill-down-lead-time-for-changes?orgId=1&${project:queryparam}&from=${__from}&to=${__to}" + "url": "/d/Lead-time-for-changes/dora-drill-down-lead-time-for-changes?orgId=1&${project:queryparam}&${author_type:queryparam}&from=${__from}&to=${__to}" } ], "options": { @@ -1095,7 +1095,7 @@ "hide": false, "metricColumn": "none", "rawQuery": true, - "rawSql": "-- Metric 2: median change lead time per month\nwith _pr_stats as (\n-- get the cycle time of PRs deployed by the deployments finished each month\n\tSELECT\n\t\tdistinct pr.id,\n\t\tdate_format(cdc.finished_date,'%y/%m') as month,\n\t\tppm.pr_cycle_time\n\tFROM\n\t\tpull_requests pr\n\t\tjoin project_pr_metrics ppm on ppm.id = pr.id\n\t\tjoin project_mapping pm on pr.base_repo_id = pm.row_id and pm.`table` = 'repos'\n\t\tjoin cicd_deployment_commits cdc on ppm.deployment_commit_id = cdc.id\n\tWHERE\n\t\tpm.project_name in (${project}) \n\t\tand pr.merged_date is not null\n\t\tand ppm.pr_cycle_time is not null\n\t\tand $__timeFilter(cdc.finished_date)\n),\n\n_find_median_clt_each_month_ranks as(\n\tSELECT *, percent_rank() over(PARTITION BY month order by pr_cycle_time) as ranks\n\tFROM _pr_stats\n),\n\n_clt as(\n\tSELECT month, max(pr_cycle_time) as median_change_lead_time\n\tFROM _find_median_clt_each_month_ranks\n\tWHERE ranks <= 0.5\n\tgroup by month\n)\n\nSELECT \n\tcm.month,\n\tcase \n\t\twhen _clt.median_change_lead_time is null then 0 \n\t\telse _clt.median_change_lead_time/60 end as 'Median Change Lead Time In Hours'\nFROM \n\tcalendar_months cm\n\tLEFT JOIN _clt on cm.month = _clt.month\n WHERE month_timestamp between DATE(DATE_FORMAT($__timeFrom(), '%Y-%m-01')) AND DATE(DATE_FORMAT($__timeTo(), '%Y-%m-01'))", + "rawSql": "-- Metric 2: median change lead time per month\nwith _pr_stats as (\n-- get the cycle time of PRs deployed by the deployments finished each month\n\tSELECT\n\t\tdistinct pr.id,\n\t\tdate_format(cdc.finished_date,'%y/%m') as month,\n\t\tppm.pr_cycle_time\n\tFROM\n\t\tpull_requests pr\n\t\tjoin project_pr_metrics ppm on ppm.id = pr.id\n\t\tjoin project_mapping pm on pr.base_repo_id = pm.row_id and pm.`table` = 'repos'\n\t\tjoin cicd_deployment_commits cdc on ppm.deployment_commit_id = cdc.id\n\tWHERE\n\t\tpm.project_name in (${project}) \n\t\tand pr.merged_date is not null\n\t\tand ppm.pr_cycle_time is not null\n\t\tand (ppm.is_authored_by_bot is null or ppm.is_authored_by_bot in (${author_type}))\n\t\tand $__timeFilter(cdc.finished_date)\n),\n\n_find_median_clt_each_month_ranks as(\n\tSELECT *, percent_rank() over(PARTITION BY month order by pr_cycle_time) as ranks\n\tFROM _pr_stats\n),\n\n_clt as(\n\tSELECT month, max(pr_cycle_time) as median_change_lead_time\n\tFROM _find_median_clt_each_month_ranks\n\tWHERE ranks <= 0.5\n\tgroup by month\n)\n\nSELECT \n\tcm.month,\n\tcase \n\t\twhen _clt.median_change_lead_time is null then 0 \n\t\telse _clt.median_change_lead_time/60 end as 'Median Change Lead Time In Hours'\nFROM \n\tcalendar_months cm\n\tLEFT JOIN _clt on cm.month = _clt.month\n WHERE month_timestamp between DATE(DATE_FORMAT($__timeFrom(), '%Y-%m-01')) AND DATE(DATE_FORMAT($__timeTo(), '%Y-%m-01'))", "refId": "A", "select": [ [ @@ -1211,7 +1211,7 @@ "links": [ { "title": "link", - "url": "/d/Change-failure-rate/dora-drill-down-change-failure-rate?orgId=1&${project:queryparam}&from=${__from}&to=${__to}" + "url": "/d/Change-failure-rate/dora-drill-down-change-failure-rate?orgId=1&${project:queryparam}&${author_type:queryparam}&from=${__from}&to=${__to}" } ], "options": { @@ -1249,7 +1249,7 @@ "hide": false, "metricColumn": "none", "rawQuery": true, - "rawSql": "-- Metric 3: change failure rate per month\nwith _deployments as (\n -- When deploying multiple commits in one pipeline, GitLab and BitBucket may generate more than one deployment. However, DevLake consider these deployments as ONE production deployment and use the last one's finished_date as the finished date.\n SELECT\n cdc.cicd_deployment_id as deployment_id,\n max(cdc.finished_date) as deployment_finished_date\n FROM\n cicd_deployment_commits cdc\n JOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id\n and pm.`table` = 'cicd_scopes'\n WHERE\n pm.project_name in (${project})\n and cdc.result = 'SUCCESS'\n and cdc.environment = 'PRODUCTION'\n GROUP BY\n 1\n HAVING\n $__timeFilter(max(cdc.finished_date))\n),\n_failure_caused_by_deployments as (\n -- calculate the number of incidents caused by each deployment\n SELECT\n d.deployment_id,\n d.deployment_finished_date,\n count(\n distinct case\n when i.id is not null then d.deployment_id\n else null\n end\n ) as has_incident\n FROM\n _deployments d\n left join project_incident_deployment_relationships pim on d.deployment_id = pim.deployment_id\n left join incidents i on pim.id = i.id\n GROUP BY\n 1,\n 2\n),\n_change_failure_rate_for_each_month as (\n SELECT\n date_format(deployment_finished_date, '%y/%m') as month,\n case\n when count(deployment_id) is null then null\n else sum(has_incident) / count(deployment_id)\n end as change_failure_rate\n FROM\n _failure_caused_by_deployments\n GROUP BY\n 1\n)\nSELECT\n cm.month,\n cfr.change_failure_rate as 'Change Failure Rate'\nFROM\n calendar_months cm\n LEFT JOIN _change_failure_rate_for_each_month cfr on cm.month = cfr.month\nWHERE\n month_timestamp between DATE(DATE_FORMAT($__timeFrom(), '%Y-%m-01')) AND DATE(DATE_FORMAT($__timeTo(), '%Y-%m-01'))", + "rawSql": "-- Metric 3: change failure rate per month\nwith _deployments as (\n -- When deploying multiple commits in one pipeline, GitLab and BitBucket may generate more than one deployment. However, DevLake consider these deployments as ONE production deployment and use the last one's finished_date as the finished date.\n SELECT\n cdc.cicd_deployment_id as deployment_id,\n max(cdc.finished_date) as deployment_finished_date\n FROM\n cicd_deployment_commits cdc\n JOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id\n JOIN project_pr_metrics ppm on cdc.id = ppm.deployment_commit_id\n and pm.`table` = 'cicd_scopes'\n WHERE\n pm.project_name in (${project})\n and cdc.result = 'SUCCESS'\n and cdc.environment = 'PRODUCTION'\n and (ppm.is_authored_by_bot is null or ppm.is_authored_by_bot in (${author_type}))\n GROUP BY\n 1\n HAVING\n $__timeFilter(max(cdc.finished_date))\n),\n_failure_caused_by_deployments as (\n -- calculate the number of incidents caused by each deployment\n SELECT\n d.deployment_id,\n d.deployment_finished_date,\n count(\n distinct case\n when i.id is not null then d.deployment_id\n else null\n end\n ) as has_incident\n FROM\n _deployments d\n left join project_incident_deployment_relationships pim on d.deployment_id = pim.deployment_id\n left join incidents i on pim.id = i.id\n GROUP BY\n 1,\n 2\n),\n_change_failure_rate_for_each_month as (\n SELECT\n date_format(deployment_finished_date, '%y/%m') as month,\n case\n when count(deployment_id) is null then null\n else sum(has_incident) / count(deployment_id)\n end as change_failure_rate\n FROM\n _failure_caused_by_deployments\n GROUP BY\n 1\n)\nSELECT\n cm.month,\n cfr.change_failure_rate as 'Change Failure Rate'\nFROM\n calendar_months cm\n LEFT JOIN _change_failure_rate_for_each_month cfr on cm.month = cfr.month\nWHERE\n month_timestamp between DATE(DATE_FORMAT($__timeFrom(), '%Y-%m-01')) AND DATE(DATE_FORMAT($__timeTo(), '%Y-%m-01'))", "refId": "A", "select": [ [ @@ -1367,11 +1367,11 @@ "links": [ { "title": "Failed Deployment Recovery Time", - "url": "/d/Failed-deployment-recovery-time/dora-details-failed-deployment-recovery-time?orgId=1&${project:queryparam}&from=${__from}&to=${__to}" + "url": "/d/Failed-deployment-recovery-time/dora-details-failed-deployment-recovery-time?orgId=1&${project:queryparam}&${author_type:queryparam}&from=${__from}&to=${__to}" }, { "title": "Median Time To Restore Service", - "url": "/d/Time-to-restore-service/dora-details-median-time-to-restore-service?orgId=1&${project:queryparam}&from=${__from}&to=${__to}" + "url": "/d/Time-to-restore-service/dora-details-median-time-to-restore-service?orgId=1&${project:queryparam}&${author_type:queryparam}&from=${__from}&to=${__to}" } ], "options": { @@ -1407,7 +1407,7 @@ "hide": false, "metricColumn": "none", "rawQuery": true, - "rawSql": "-- ***** 2023 report ***** --\n-- Metric 4: Failed deployment recovery time\nwith _deployments as (\n SELECT\n cdc.cicd_deployment_id as deployment_id,\n max(cdc.finished_date) as deployment_finished_date\n FROM\n cicd_deployment_commits cdc\n JOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id\n and pm.`table` = 'cicd_scopes'\n WHERE\n pm.project_name in ($project)\n and cdc.result = 'SUCCESS'\n and cdc.environment = 'PRODUCTION'\n GROUP BY\n 1\n HAVING\n $__timeFilter(max(cdc.finished_date))\n),\n_incidents_for_deployments as (\n SELECT\n i.id as incident_id,\n i.created_date as incident_create_date,\n i.resolution_date as incident_resolution_date,\n fd.deployment_id as caused_by_deployment,\n fd.deployment_finished_date,\n date_format(fd.deployment_finished_date, '%y/%m') as deployment_finished_month\n FROM\n incidents i\n left join project_incident_deployment_relationships pim on i.id = pim.id\n join _deployments fd on pim.deployment_id = fd.deployment_id\n WHERE\n $__timeFilter(i.resolution_date)\n),\n_recovery_time_ranks as (\n SELECT\n *,\n percent_rank() over(\n PARTITION BY deployment_finished_month\n order by\n TIMESTAMPDIFF(\n MINUTE,\n deployment_finished_date,\n incident_resolution_date\n )\n ) as ranks\n FROM\n _incidents_for_deployments\n),\n_median_recovery_time as (\n SELECT\n deployment_finished_month,\n max(\n TIMESTAMPDIFF(\n MINUTE,\n deployment_finished_date,\n incident_resolution_date\n )\n ) as median_recovery_time\n FROM\n _recovery_time_ranks\n WHERE\n ranks <= 0.5\n GROUP BY\n deployment_finished_month\n),\n_metric_recovery_time_2023_report as (\n SELECT\n cm.month,\n case\n when m.median_recovery_time is null then 0\n else m.median_recovery_time / 60\n end as median_recovery_time_in_hour\n FROM\n calendar_months cm\n LEFT JOIN _median_recovery_time m on cm.month = m.deployment_finished_month\n WHERE\n month_timestamp between DATE(DATE_FORMAT($__timeFrom(), '%Y-%m-01')) AND DATE(DATE_FORMAT($__timeTo(), '%Y-%m-01'))\n),\n-- ***** 2021 report ***** --\n-- Metric 4: median time to restore service - MTTR\n_incidents as (\n -- get the number of incidents created each month\n SELECT\n distinct i.id,\n date_format(i.resolution_date, '%y/%m') as month,\n cast(lead_time_minutes as signed) as lead_time_minutes\n FROM\n incidents i\n join project_mapping pm on i.scope_id = pm.row_id\n and pm.`table` = i.`table`\n WHERE\n pm.project_name in (${project})\n and i.lead_time_minutes is not null\n),\n_find_median_mttr_each_month_ranks as(\n SELECT\n *,\n percent_rank() over(\n PARTITION BY month\n order by\n lead_time_minutes\n ) as ranks\n FROM\n _incidents\n),\n_mttr as(\n SELECT\n month,\n max(lead_time_minutes) as median_time_to_resolve\n FROM\n _find_median_mttr_each_month_ranks\n WHERE\n ranks <= 0.5\n GROUP BY\n month\n),\n_metric_mttr_2021_report as (\n SELECT\n cm.month,\n case\n when m.median_time_to_resolve is null then 0\n else m.median_time_to_resolve / 60\n end as median_time_to_resolve_in_hour\n FROM\n calendar_months cm\n LEFT JOIN _mttr m on cm.month = m.month\n WHERE\n month_timestamp between DATE(DATE_FORMAT($__timeFrom(), '%Y-%m-01')) AND DATE(DATE_FORMAT($__timeTo(), '%Y-%m-01'))\n)\nSELECT\n cm.month,\n CASE\n WHEN '${dora_report}' = '2023' THEN mrt.median_recovery_time_in_hour\n WHEN '${dora_report}' = '2021' THEN mm.median_time_to_resolve_in_hour\n END AS '${title_value} In Hours'\nFROM\n calendar_months cm\n LEFT JOIN _metric_recovery_time_2023_report mrt ON cm.month = mrt.month\n LEFT JOIN _metric_mttr_2021_report mm ON cm.month = mm.month\nWHERE\n month_timestamp between DATE(DATE_FORMAT($__timeFrom(), '%Y-%m-01')) AND DATE(DATE_FORMAT($__timeTo(), '%Y-%m-01'))", + "rawSql": "-- ***** 2023 report ***** --\n-- Metric 4: Failed deployment recovery time\nwith _deployments as (\n SELECT\n cdc.cicd_deployment_id as deployment_id,\n max(cdc.finished_date) as deployment_finished_date\n FROM\n cicd_deployment_commits cdc\n JOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id\n JOIN project_pr_metrics ppm on cdc.id = ppm.deployment_commit_id\n and pm.`table` = 'cicd_scopes'\n WHERE\n pm.project_name in ($project)\n and cdc.result = 'SUCCESS'\n and cdc.environment = 'PRODUCTION'\n and (ppm.is_authored_by_bot is null or ppm.is_authored_by_bot in (${author_type}))\n GROUP BY\n 1\n HAVING\n $__timeFilter(max(cdc.finished_date))\n),\n_incidents_for_deployments as (\n SELECT\n i.id as incident_id,\n i.created_date as incident_create_date,\n i.resolution_date as incident_resolution_date,\n fd.deployment_id as caused_by_deployment,\n fd.deployment_finished_date,\n date_format(fd.deployment_finished_date, '%y/%m') as deployment_finished_month\n FROM\n incidents i\n left join project_incident_deployment_relationships pim on i.id = pim.id\n join _deployments fd on pim.deployment_id = fd.deployment_id\n WHERE\n $__timeFilter(i.resolution_date)\n),\n_recovery_time_ranks as (\n SELECT\n *,\n percent_rank() over(\n PARTITION BY deployment_finished_month\n order by\n TIMESTAMPDIFF(\n MINUTE,\n deployment_finished_date,\n incident_resolution_date\n )\n ) as ranks\n FROM\n _incidents_for_deployments\n),\n_median_recovery_time as (\n SELECT\n deployment_finished_month,\n max(\n TIMESTAMPDIFF(\n MINUTE,\n deployment_finished_date,\n incident_resolution_date\n )\n ) as median_recovery_time\n FROM\n _recovery_time_ranks\n WHERE\n ranks <= 0.5\n GROUP BY\n deployment_finished_month\n),\n_metric_recovery_time_2023_report as (\n SELECT\n cm.month,\n case\n when m.median_recovery_time is null then 0\n else m.median_recovery_time / 60\n end as median_recovery_time_in_hour\n FROM\n calendar_months cm\n LEFT JOIN _median_recovery_time m on cm.month = m.deployment_finished_month\n WHERE\n month_timestamp between DATE(DATE_FORMAT($__timeFrom(), '%Y-%m-01')) AND DATE(DATE_FORMAT($__timeTo(), '%Y-%m-01'))\n),\n-- ***** 2021 report ***** --\n-- Metric 4: median time to restore service - MTTR\n_incidents as (\n -- get the number of incidents created each month\n SELECT\n distinct i.id,\n date_format(i.resolution_date, '%y/%m') as month,\n cast(lead_time_minutes as signed) as lead_time_minutes\n FROM\n incidents i\n join project_mapping pm on i.scope_id = pm.row_id\n and pm.`table` = i.`table`\n WHERE\n pm.project_name in (${project})\n and i.lead_time_minutes is not null\n),\n_find_median_mttr_each_month_ranks as(\n SELECT\n *,\n percent_rank() over(\n PARTITION BY month\n order by\n lead_time_minutes\n ) as ranks\n FROM\n _incidents\n),\n_mttr as(\n SELECT\n month,\n max(lead_time_minutes) as median_time_to_resolve\n FROM\n _find_median_mttr_each_month_ranks\n WHERE\n ranks <= 0.5\n GROUP BY\n month\n),\n_metric_mttr_2021_report as (\n SELECT\n cm.month,\n case\n when m.median_time_to_resolve is null then 0\n else m.median_time_to_resolve / 60\n end as median_time_to_resolve_in_hour\n FROM\n calendar_months cm\n LEFT JOIN _mttr m on cm.month = m.month\n WHERE\n month_timestamp between DATE(DATE_FORMAT($__timeFrom(), '%Y-%m-01')) AND DATE(DATE_FORMAT($__timeTo(), '%Y-%m-01'))\n)\nSELECT\n cm.month,\n CASE\n WHEN '${dora_report}' = '2023' THEN mrt.median_recovery_time_in_hour\n WHEN '${dora_report}' = '2021' THEN mm.median_time_to_resolve_in_hour\n END AS '${title_value} In Hours'\nFROM\n calendar_months cm\n LEFT JOIN _metric_recovery_time_2023_report mrt ON cm.month = mrt.month\n LEFT JOIN _metric_mttr_2021_report mm ON cm.month = mm.month\nWHERE\n month_timestamp between DATE(DATE_FORMAT($__timeFrom(), '%Y-%m-01')) AND DATE(DATE_FORMAT($__timeTo(), '%Y-%m-01'))", "refId": "A", "select": [ [ @@ -1527,6 +1527,31 @@ "skipUrlSync": false, "sort": 0, "type": "query" + }, + { + "allValue": "", + "current": { + "text": "$__all", + "value": "$__all" + }, + "description": "Filter Metrics by author type: Human or Bot.", + "includeAll": true, + "label": "Author Type", + "name": "author_type", + "options": [ + { + "selected": false, + "text": "Human", + "value": "0" + }, + { + "selected": false, + "text": "Bot", + "value": "1" + } + ], + "query": "Human : 0, Bot : 1", + "type": "custom" } ] }, diff --git a/grafana/dashboards/DORADetails-ChangeFailureRate.json b/grafana/dashboards/DORADetails-ChangeFailureRate.json index 8048b282b1f..438eb5867f6 100644 --- a/grafana/dashboards/DORADetails-ChangeFailureRate.json +++ b/grafana/dashboards/DORADetails-ChangeFailureRate.json @@ -164,7 +164,7 @@ "metricColumn": "none", "queryType": "randomWalk", "rawQuery": true, - "rawSql": "-- Metric 3: change failure rate\nwith _deployments as (\n -- When deploying multiple commits in one pipeline, GitLab and BitBucket may generate more than one deployment. However, DevLake consider these deployments as ONE production deployment and use the last one's finished_date as the finished date.\n SELECT\n cdc.cicd_deployment_id as deployment_id,\n max(cdc.finished_date) as deployment_finished_date\n FROM\n cicd_deployment_commits cdc\n JOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id\n and pm.`table` = 'cicd_scopes'\n WHERE\n pm.project_name in (${project})\n and cdc.result = 'SUCCESS'\n and cdc.environment = 'PRODUCTION'\n GROUP BY\n 1\n HAVING\n $__timeFilter(max(cdc.finished_date))\n),\n_failure_caused_by_deployments as (\n -- calculate the number of incidents caused by each deployment\n SELECT\n d.deployment_id,\n d.deployment_finished_date,\n count(distinct i.id) as has_incident\n FROM\n _deployments d\n left join project_incident_deployment_relationships pim on d.deployment_id = pim.deployment_id\n left join incidents i on pim.id = i.id\n GROUP BY\n 1,\n 2\n)\nSELECT\n sum(has_incident) / count(deployment_id) as \"change_failure_rate\"\nFROM\n _failure_caused_by_deployments", + "rawSql": "-- Metric 3: change failure rate\nwith _deployments as (\n -- When deploying multiple commits in one pipeline, GitLab and BitBucket may generate more than one deployment. However, DevLake consider these deployments as ONE production deployment and use the last one's finished_date as the finished date.\n SELECT\n cdc.cicd_deployment_id as deployment_id,\n max(cdc.finished_date) as deployment_finished_date\n FROM\n cicd_deployment_commits cdc\n JOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id\n JOIN project_pr_metrics ppm on cdc.id = ppm.deployment_commit_id\n and pm.`table` = 'cicd_scopes'\n and (ppm.is_authored_by_bot is null or ppm.is_authored_by_bot in (${author_type}))\n WHERE\n pm.project_name in (${project})\n and cdc.result = 'SUCCESS'\n and cdc.environment = 'PRODUCTION'\n GROUP BY\n 1\n HAVING\n $__timeFilter(max(cdc.finished_date))\n),\n_failure_caused_by_deployments as (\n -- calculate the number of incidents caused by each deployment\n SELECT\n d.deployment_id,\n d.deployment_finished_date,\n count(distinct i.id) as has_incident\n FROM\n _deployments d\n left join project_incident_deployment_relationships pim on d.deployment_id = pim.deployment_id\n left join incidents i on pim.id = i.id\n GROUP BY\n 1,\n 2\n)\nSELECT\n sum(has_incident) / count(deployment_id) as \"change_failure_rate\"\nFROM\n _failure_caused_by_deployments", "refId": "A", "select": [ [ @@ -365,7 +365,7 @@ "metricColumn": "none", "queryType": "randomWalk", "rawQuery": true, - "rawSql": "-- Metric 3: change failure rate\nwith _deployments as (\n-- When deploying multiple commits in one pipeline, GitLab and BitBucket may generate more than one deployment. However, DevLake consider these deployments as ONE production deployment and use the last one's finished_date as the finished date.\n\tSELECT\n\t\tcdc.cicd_deployment_id as deployment_id,\n\t\tmax(cdc.finished_date) as deployment_finished_date\n\tFROM \n\t\tcicd_deployment_commits cdc\n\t\tJOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id and pm.`table` = 'cicd_scopes'\n\tWHERE\n\t\tpm.project_name in (${project})\n\t\tand cdc.result = 'SUCCESS'\n\t\tand cdc.environment = 'PRODUCTION'\n\tGROUP BY 1\n\tHAVING $__timeFilter(max(cdc.finished_date))\n),\n\n_failure_caused_by_deployments as (\n-- calculate the number of incidents caused by each deployment\n\tSELECT\n\t\td.deployment_id as \"deployment_id\",\n\t\td.deployment_finished_date,\n\t\tpim.id as incident_id,\n\t\ti.title,\n\t\ti.url,\n\t\ti.url as \"metric_hidden\",\n\t\ti.created_date\n\t\t-- i.resolution_date,\n\tFROM\n\t\t_deployments d\n\t\tleft join project_incident_deployment_relationships pim on d.deployment_id = pim.deployment_id\n\t\tleft join issues i on pim.id = i.id\n\tWHERE pim.id is not null\n\tORDER BY 2\n)\n\nselect * \nFROM _failure_caused_by_deployments\n", + "rawSql": "-- Metric 3: change failure rate\nwith _deployments as (\n-- When deploying multiple commits in one pipeline, GitLab and BitBucket may generate more than one deployment. However, DevLake consider these deployments as ONE production deployment and use the last one's finished_date as the finished date.\n\tSELECT\n\t\tcdc.cicd_deployment_id as deployment_id,\n\t\tmax(cdc.finished_date) as deployment_finished_date\n\tFROM \n\t\tcicd_deployment_commits cdc\n\t\tJOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id and pm.`table` = 'cicd_scopes'\n\t\tJOIN project_pr_metrics ppm on cdc.id = ppm.deployment_commit_id\n\n\tWHERE\n\t\tpm.project_name in (${project})\n\t\tand cdc.result = 'SUCCESS'\n\t\tand cdc.environment = 'PRODUCTION'\n\t\tand (ppm.is_authored_by_bot is null or ppm.is_authored_by_bot in (${author_type}))\n\tGROUP BY 1\n\tHAVING $__timeFilter(max(cdc.finished_date))\n),\n\n_failure_caused_by_deployments as (\n-- calculate the number of incidents caused by each deployment\n\tSELECT\n\t\td.deployment_id as \"deployment_id\",\n\t\td.deployment_finished_date,\n\t\tpim.id as incident_id,\n\t\ti.title,\n\t\ti.url,\n\t\ti.url as \"metric_hidden\",\n\t\ti.created_date\n\t\t-- i.resolution_date,\n\tFROM\n\t\t_deployments d\n\t\tleft join project_incident_deployment_relationships pim on d.deployment_id = pim.deployment_id\n\t\tleft join issues i on pim.id = i.id\n\tWHERE pim.id is not null\n\tORDER BY 2\n)\n\nselect * \nFROM _failure_caused_by_deployments\n", "refId": "A", "select": [ [ @@ -502,7 +502,7 @@ "metricColumn": "none", "queryType": "randomWalk", "rawQuery": true, - "rawSql": "-- Metric 3: change failure rate\nwith _deployments as (\n -- When deploying multiple commits in one pipeline, GitLab and BitBucket may generate more than one deployment. However, DevLake consider these deployments as ONE production deployment and use the last one's finished_date as the finished date.\n SELECT\n cdc.cicd_deployment_id as deployment_id,\n max(cdc.finished_date) as deployment_finished_date\n FROM\n cicd_deployment_commits cdc\n JOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id\n and pm.`table` = 'cicd_scopes'\n WHERE\n pm.project_name in (${project})\n and cdc.result = 'SUCCESS'\n and cdc.environment = 'PRODUCTION'\n GROUP BY\n 1\n HAVING\n $__timeFilter(max(cdc.finished_date))\n),\n_failure_caused_by_deployments as (\n -- calculate the number of incidents caused by each deployment\n SELECT\n d.deployment_id,\n d.deployment_finished_date,\n count(distinct i.id) as has_incident\n FROM\n _deployments d\n left join project_incident_deployment_relationships pim on d.deployment_id = pim.deployment_id\n left join incidents i on pim.id = i.id\n GROUP BY\n 1,\n 2\n)\nSELECT\n sum(has_incident) as \"incident count\",\n count(deployment_id) as \"deployment count\"\nFROM\n _failure_caused_by_deployments", + "rawSql": "-- Metric 3: change failure rate\nwith _deployments as (\n -- When deploying multiple commits in one pipeline, GitLab and BitBucket may generate more than one deployment. However, DevLake consider these deployments as ONE production deployment and use the last one's finished_date as the finished date.\n SELECT\n cdc.cicd_deployment_id as deployment_id,\n max(cdc.finished_date) as deployment_finished_date\n FROM\n cicd_deployment_commits cdc\n JOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id\n JOIN project_pr_metrics ppm on cdc.id = ppm.deployment_commit_id\n and pm.`table` = 'cicd_scopes'\n WHERE\n pm.project_name in (${project})\n and cdc.result = 'SUCCESS'\n and cdc.environment = 'PRODUCTION'\n and (ppm.is_authored_by_bot is null or ppm.is_authored_by_bot in (${author_type}))\n GROUP BY\n 1\n HAVING\n $__timeFilter(max(cdc.finished_date))\n),\n_failure_caused_by_deployments as (\n -- calculate the number of incidents caused by each deployment\n SELECT\n d.deployment_id,\n d.deployment_finished_date,\n count(distinct i.id) as has_incident\n FROM\n _deployments d\n left join project_incident_deployment_relationships pim on d.deployment_id = pim.deployment_id\n left join incidents i on pim.id = i.id\n GROUP BY\n 1,\n 2\n)\nSELECT\n sum(has_incident) as \"incident count\",\n count(deployment_id) as \"deployment count\"\nFROM\n _failure_caused_by_deployments", "refId": "A", "select": [ [ @@ -627,7 +627,7 @@ "metricColumn": "none", "queryType": "randomWalk", "rawQuery": true, - "rawSql": "with _deployments as(\n select\n distinct d.cicd_deployment_id as deployment_id,\n d.result,\n d.environment,\n d.finished_date,\n d.cicd_scope_id,\n pm.project_name\n from\n cicd_deployment_commits d\n join project_mapping pm on d.cicd_scope_id = pm.row_id\n and pm.`table` = 'cicd_scopes'\n where\n -- only result needs to specified, not envioronment\n d.result = 'SUCCESS' -- choose your project_name\n and pm.project_name in ($project)\n and $__timeFilter(d.finished_date)\n),\n_incidents as(\n select\n distinct i.id as issue_id,\n i.created_date,\n pm.project_name\n from\n incidents i\n join project_mapping pm on i.scope_id = pm.row_id\n and i.`table` = pm.`table`\n where\n -- choose your project_name\n pm.project_name in ($project)\n and $__timeFilter(i.created_date)\n)\nselect\n finished_date as 'Time (Ascending)',\n deployment_id as 'Entity ID',\n 'DEPLOYMENT' as 'Entity Type (Deployment/Incident)'\nfrom\n _deployments\nunion\nselect\n created_date as 'Time (Ascending)',\n issue_id as 'Entity ID',\n 'INCIDENT' as 'Entity Type (Deployment/Incident)'\nfrom\n _incidents\norder by\n 1", + "rawSql": "with _deployments as(\n select\n distinct d.cicd_deployment_id as deployment_id,\n d.result,\n d.environment,\n d.finished_date,\n d.cicd_scope_id,\n pm.project_name\n from\n cicd_deployment_commits d\n join project_mapping pm on d.cicd_scope_id = pm.row_id\n join project_pr_metrics ppm on d.id = ppm.deployment_commit_id\n and pm.`table` = 'cicd_scopes'\n where\n -- only result needs to specified, not envioronment\n d.result = 'SUCCESS' -- choose your project_name\n and pm.project_name in ($project)\n and (ppm.is_authored_by_bot is null or ppm.is_authored_by_bot in (${author_type}))\n and $__timeFilter(d.finished_date)\n),\n_incidents as(\n select\n distinct i.id as issue_id,\n i.created_date,\n pm.project_name\n from\n incidents i\n join project_mapping pm on i.scope_id = pm.row_id\n and i.`table` = pm.`table`\n where\n -- choose your project_name\n pm.project_name in ($project)\n and $__timeFilter(i.created_date)\n)\nselect\n finished_date as 'Time (Ascending)',\n deployment_id as 'Entity ID',\n 'DEPLOYMENT' as 'Entity Type (Deployment/Incident)'\nfrom\n _deployments\nunion\nselect\n created_date as 'Time (Ascending)',\n issue_id as 'Entity ID',\n 'INCIDENT' as 'Entity Type (Deployment/Incident)'\nfrom\n _incidents\norder by\n 1", "refId": "A", "select": [ [ @@ -742,6 +742,30 @@ "skipUrlSync": false, "sort": 0, "type": "query" + }, + { + "current": { + "text": "$__all", + "value": "$__all" + }, + "description": "Filter Metrics by author type: Human or Bot.", + "includeAll": true, + "label": "Author Type", + "name": "author_type", + "options": [ + { + "selected": false, + "text": "Human", + "value": "0" + }, + { + "selected": false, + "text": "Bot", + "value": "1" + } + ], + "query": "Human : 0, Bot : 1", + "type": "custom" } ] }, diff --git a/grafana/dashboards/DORADetails-DeploymentFrequency.json b/grafana/dashboards/DORADetails-DeploymentFrequency.json index 44c49c5ad23..104bc8ca6be 100644 --- a/grafana/dashboards/DORADetails-DeploymentFrequency.json +++ b/grafana/dashboards/DORADetails-DeploymentFrequency.json @@ -257,7 +257,7 @@ "metricColumn": "none", "queryType": "randomWalk", "rawQuery": true, - "rawSql": "with _deployment_commit_rank as(\n SELECT\n \tpm.project_name,\n \tIF(cdc._raw_data_table != '', cdc._raw_data_table, cdc.cicd_scope_id) as _raw_data_table,\n \tcdc.id,\n cdc.display_title,\n cdc.url,\n \tcdc.cicd_deployment_id,\n \tcdc.cicd_scope_id,\n \tresult,\n \tenvironment,\n finished_date,\n row_number() over(partition by cdc.cicd_deployment_id order by finished_date desc) as _deployment_commit_rank\n FROM cicd_deployment_commits cdc\n left join project_mapping pm on cdc.cicd_scope_id = pm.row_id and pm.`table` = 'cicd_scopes'\n WHERE\n pm.project_name in ($project)\n \tand result = 'SUCCESS'\n \tand environment = 'PRODUCTION'\n)\n\nSELECT \n project_name, \n cicd_deployment_id as deployment_id,\n case when display_title = '' then 'N/A' else display_title end as display_title,\n url,\n url as metric_hidden,\n -- a deployment may have multiple deployment_commits\n -- id as deployment_commit_id, \n result,\n environment,\n finished_date\nFROM _deployment_commit_rank\nWHERE \n _deployment_commit_rank = 1\n and $__timeFilter(finished_date)\nORDER BY finished_date DESC", + "rawSql": "with _deployment_commit_rank as(\n SELECT\n \tpm.project_name,\n \tIF(cdc._raw_data_table != '', cdc._raw_data_table, cdc.cicd_scope_id) as _raw_data_table,\n \tcdc.id,\n cdc.display_title,\n cdc.url,\n \tcdc.cicd_deployment_id,\n \tcdc.cicd_scope_id,\n \tresult,\n \tenvironment,\n finished_date,\n row_number() over(partition by cdc.cicd_deployment_id order by finished_date desc) as _deployment_commit_rank\n FROM cicd_deployment_commits cdc\n left join project_mapping pm on cdc.cicd_scope_id = pm.row_id and pm.`table` = 'cicd_scopes'\n left join project_pr_metrics ppm on cdc.id = ppm.deployment_commit_id\n WHERE\n pm.project_name in ($project)\n \tand result = 'SUCCESS'\n \tand environment = 'PRODUCTION'\n and (ppm.is_authored_by_bot is null or ppm.is_authored_by_bot in (${author_type}))\n)\n\nSELECT \n project_name, \n cicd_deployment_id as deployment_id,\n case when display_title = '' then 'N/A' else display_title end as display_title,\n url,\n url as metric_hidden,\n -- a deployment may have multiple deployment_commits\n -- id as deployment_commit_id, \n result,\n environment,\n finished_date\nFROM _deployment_commit_rank\nWHERE \n _deployment_commit_rank = 1\n and $__timeFilter(finished_date)\nORDER BY finished_date DESC", "refId": "A", "select": [ [ @@ -375,7 +375,7 @@ "metricColumn": "none", "queryType": "randomWalk", "rawQuery": true, - "rawSql": "-- Metric 1: Deployment Frequency\nWITH last_few_calendar_days AS (\n -- Construct the last few calendar days within the selected time period in the top-right corner\n SELECT CAST(($__timeTo() - INTERVAL (H + T + U) DAY) AS date) AS day\n FROM (\n SELECT 0 H\n UNION ALL SELECT 100 UNION ALL SELECT 200 UNION ALL SELECT 300\n ) H\n CROSS JOIN (\n SELECT 0 T\n UNION ALL SELECT 10 UNION ALL SELECT 20 UNION ALL SELECT 30\n UNION ALL SELECT 40 UNION ALL SELECT 50 UNION ALL SELECT 60\n UNION ALL SELECT 70 UNION ALL SELECT 80 UNION ALL SELECT 90\n ) T\n CROSS JOIN (\n SELECT 0 U\n UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3\n UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6\n UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9\n ) U\n WHERE ($__timeTo() - INTERVAL (H + T + U) DAY) > $__timeFrom()\n),\n\n_deployment_commit_rank as(\n SELECT\n \tpm.project_name,\n \tIF(cdc._raw_data_table != '', cdc._raw_data_table, cdc.cicd_scope_id) as _raw_data_table,\n \tcdc.id,\n \tcdc.cicd_deployment_id,\n \tcdc.cicd_scope_id,\n \tresult,\n \tenvironment,\n finished_date,\n row_number() over(partition by cdc.cicd_deployment_id order by finished_date desc) as _deployment_commit_rank\n FROM cicd_deployment_commits cdc\n left join project_mapping pm on cdc.cicd_scope_id = pm.row_id and pm.`table` = 'cicd_scopes'\n WHERE\n pm.project_name in ($project)\n \tand result = 'SUCCESS'\n \tand environment = 'PRODUCTION'\n),\n\n_deployments as (\n SELECT \n project_name, \n cicd_deployment_id as deployment_id,\n -- a deployment may have multiple deployment_commits\n id as deployment_commit_id, \n result,\n environment,\n finished_date\n FROM _deployment_commit_rank\n WHERE \n _deployment_commit_rank = 1\n and $__timeFilter(finished_date)\n)\n\nSELECT\n\tdate_format(last_few_calendar_days.day, '%Y-%m-%d') AS day,\n\tCOALESCE(COUNT(d.finished_date), 0) AS successful_deployments_to_prod\nFROM last_few_calendar_days\nLEFT JOIN _deployments d ON last_few_calendar_days.day = DATE(d.finished_date)\nGROUP BY 1\nORDER BY 1 DESC", + "rawSql": "-- Metric 1: Deployment Frequency\nWITH last_few_calendar_days AS (\n -- Construct the last few calendar days within the selected time period in the top-right corner\n SELECT CAST(($__timeTo() - INTERVAL (H + T + U) DAY) AS date) AS day\n FROM (\n SELECT 0 H\n UNION ALL SELECT 100 UNION ALL SELECT 200 UNION ALL SELECT 300\n ) H\n CROSS JOIN (\n SELECT 0 T\n UNION ALL SELECT 10 UNION ALL SELECT 20 UNION ALL SELECT 30\n UNION ALL SELECT 40 UNION ALL SELECT 50 UNION ALL SELECT 60\n UNION ALL SELECT 70 UNION ALL SELECT 80 UNION ALL SELECT 90\n ) T\n CROSS JOIN (\n SELECT 0 U\n UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3\n UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6\n UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9\n ) U\n WHERE ($__timeTo() - INTERVAL (H + T + U) DAY) > $__timeFrom()\n),\n\n_deployment_commit_rank as(\n SELECT\n \tpm.project_name,\n \tIF(cdc._raw_data_table != '', cdc._raw_data_table, cdc.cicd_scope_id) as _raw_data_table,\n \tcdc.id,\n \tcdc.cicd_deployment_id,\n \tcdc.cicd_scope_id,\n \tresult,\n \tenvironment,\n finished_date,\n row_number() over(partition by cdc.cicd_deployment_id order by finished_date desc) as _deployment_commit_rank\n FROM cicd_deployment_commits cdc\n left join project_mapping pm on cdc.cicd_scope_id = pm.row_id and pm.`table` = 'cicd_scopes'\n left join project_pr_metrics ppm on cdc.id = ppm.deployment_commit_id\n WHERE\n pm.project_name in ($project)\n \tand result = 'SUCCESS'\n \tand environment = 'PRODUCTION'\n and (ppm.is_authored_by_bot is null or ppm.is_authored_by_bot in (${author_type}))\n),\n\n_deployments as (\n SELECT \n project_name, \n cicd_deployment_id as deployment_id,\n -- a deployment may have multiple deployment_commits\n id as deployment_commit_id, \n result,\n environment,\n finished_date\n FROM _deployment_commit_rank\n WHERE \n _deployment_commit_rank = 1\n and $__timeFilter(finished_date)\n)\n\nSELECT\n\tdate_format(last_few_calendar_days.day, '%Y-%m-%d') AS day,\n\tCOALESCE(COUNT(d.finished_date), 0) AS successful_deployments_to_prod\nFROM last_few_calendar_days\nLEFT JOIN _deployments d ON last_few_calendar_days.day = DATE(d.finished_date)\nGROUP BY 1\nORDER BY 1 DESC", "refId": "A", "select": [ [ @@ -503,7 +503,7 @@ "metricColumn": "none", "queryType": "randomWalk", "rawQuery": true, - "rawSql": "-- Metric 1: Deployment Frequency\nwith last_few_calendar_months as(\n-- construct the last few calendar months within the selected time period in the top-right corner\n\tSELECT CAST(($__timeTo()-INTERVAL (H+T+U) DAY) AS date) day\n\tFROM ( SELECT 0 H\n\t\t\tUNION ALL SELECT 100 UNION ALL SELECT 200 UNION ALL SELECT 300\n\t\t) H CROSS JOIN ( SELECT 0 T\n\t\t\tUNION ALL SELECT 10 UNION ALL SELECT 20 UNION ALL SELECT 30\n\t\t\tUNION ALL SELECT 40 UNION ALL SELECT 50 UNION ALL SELECT 60\n\t\t\tUNION ALL SELECT 70 UNION ALL SELECT 80 UNION ALL SELECT 90\n\t\t) T CROSS JOIN ( SELECT 0 U\n\t\t\tUNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3\n\t\t\tUNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6\n\t\t\tUNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9\n\t\t) U\n\tWHERE\n\t\t($__timeTo()-INTERVAL (H+T+U) DAY) > $__timeFrom()\n),\n\n_production_deployment_days as(\n-- When deploying multiple commits in one pipeline, GitLab and BitBucket may generate more than one deployment. However, DevLake consider these deployments as ONE production deployment and use the last one's finished_date as the finished date.\n\tSELECT\n\t\tcdc.cicd_deployment_id as deployment_id,\n\t\tmax(DATE(cdc.finished_date)) as day\n\tFROM cicd_deployment_commits cdc\n\tJOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id and pm.`table` = 'cicd_scopes'\n\tWHERE\n\t\tpm.project_name in ($project)\n\t\tand cdc.result = 'SUCCESS'\n\t\tand cdc.environment = 'PRODUCTION'\n\tGROUP BY 1\n),\n\n_days_weekly_deploy as(\n-- calculate the number of deployment days every week\n\tSELECT\n\t\t\tdate(DATE_ADD(last_few_calendar_months.day, INTERVAL -WEEKDAY(last_few_calendar_months.day) DAY)) as week,\n\t\t\tMAX(if(_production_deployment_days.day is not null, 1, null)) as weeks_deployed,\n\t\t\tCOUNT(distinct _production_deployment_days.day) as days_deployed\n\tFROM \n\t\tlast_few_calendar_months\n\t\tLEFT JOIN _production_deployment_days ON _production_deployment_days.day = last_few_calendar_months.day\n\tGROUP BY week\n\t),\n\n_days_monthly_deploy as(\n-- calculate the number of deployment days every month\n\tSELECT\n\t\t\tdate(DATE_ADD(last_few_calendar_months.day, INTERVAL -DAY(last_few_calendar_months.day)+1 DAY)) as month,\n\t\t\tMAX(if(_production_deployment_days.day is not null, 1, null)) as months_deployed,\n\t\t COUNT(distinct _production_deployment_days.day) as days_deployed\n\tFROM \n\t\tlast_few_calendar_months\n\t\tLEFT JOIN _production_deployment_days ON _production_deployment_days.day = last_few_calendar_months.day\n\tGROUP BY month\n\t),\n\n_days_six_months_deploy AS (\n SELECT\n month,\n SUM(days_deployed) OVER (\n ORDER BY month\n ROWS BETWEEN 5 PRECEDING AND CURRENT ROW\n ) AS days_deployed_per_six_months,\n COUNT(months_deployed) OVER (\n ORDER BY month\n ROWS BETWEEN 5 PRECEDING AND CURRENT ROW\n ) AS months_deployed_count,\n ROW_NUMBER() OVER (\n PARTITION BY DATE_FORMAT(month, '%Y-%m') DIV 6\n ORDER BY month DESC\n ) AS rn\n FROM _days_monthly_deploy\n),\n\ncalendar_weeks as(\n select \n \tdistinct date(DATE_ADD(date(day), INTERVAL -WEEKDAY(date(day)) DAY)) as start_of_week\n FROM last_few_calendar_months\n ORDER BY 1 asc\n)\n\n\nSELECT \n concat(date_format(cw.start_of_week,'%m/%d'), ' - ', date_format(DATE_ADD(cw.start_of_week, INTERVAL +6 DAY),'%m/%d')) as week,\n days_deployed\nfrom calendar_weeks cw left join _days_weekly_deploy b on cw.start_of_week = b.week", + "rawSql": "-- Metric 1: Deployment Frequency\nwith last_few_calendar_months as(\n-- construct the last few calendar months within the selected time period in the top-right corner\n\tSELECT CAST(($__timeTo()-INTERVAL (H+T+U) DAY) AS date) day\n\tFROM ( SELECT 0 H\n\t\t\tUNION ALL SELECT 100 UNION ALL SELECT 200 UNION ALL SELECT 300\n\t\t) H CROSS JOIN ( SELECT 0 T\n\t\t\tUNION ALL SELECT 10 UNION ALL SELECT 20 UNION ALL SELECT 30\n\t\t\tUNION ALL SELECT 40 UNION ALL SELECT 50 UNION ALL SELECT 60\n\t\t\tUNION ALL SELECT 70 UNION ALL SELECT 80 UNION ALL SELECT 90\n\t\t) T CROSS JOIN ( SELECT 0 U\n\t\t\tUNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3\n\t\t\tUNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6\n\t\t\tUNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9\n\t\t) U\n\tWHERE\n\t\t($__timeTo()-INTERVAL (H+T+U) DAY) > $__timeFrom()\n),\n\n_production_deployment_days as(\n-- When deploying multiple commits in one pipeline, GitLab and BitBucket may generate more than one deployment. However, DevLake consider these deployments as ONE production deployment and use the last one's finished_date as the finished date.\n\tSELECT\n\t\tcdc.cicd_deployment_id as deployment_id,\n\t\tmax(DATE(cdc.finished_date)) as day\n\tFROM cicd_deployment_commits cdc\n\tJOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id and pm.`table` = 'cicd_scopes'\n\tJOIN project_pr_metrics ppm on cdc.id = ppm.deployment_commit_id\n\tWHERE\n\t\tpm.project_name in ($project)\n\t\tand cdc.result = 'SUCCESS'\n\t\tand cdc.environment = 'PRODUCTION'\n\t\tand (ppm.is_authored_by_bot is null or ppm.is_authored_by_bot in (${author_type}))\n\tGROUP BY 1\n),\n\n_days_weekly_deploy as(\n-- calculate the number of deployment days every week\n\tSELECT\n\t\t\tdate(DATE_ADD(last_few_calendar_months.day, INTERVAL -WEEKDAY(last_few_calendar_months.day) DAY)) as week,\n\t\t\tMAX(if(_production_deployment_days.day is not null, 1, null)) as weeks_deployed,\n\t\t\tCOUNT(distinct _production_deployment_days.day) as days_deployed\n\tFROM \n\t\tlast_few_calendar_months\n\t\tLEFT JOIN _production_deployment_days ON _production_deployment_days.day = last_few_calendar_months.day\n\tGROUP BY week\n\t),\n\n_days_monthly_deploy as(\n-- calculate the number of deployment days every month\n\tSELECT\n\t\t\tdate(DATE_ADD(last_few_calendar_months.day, INTERVAL -DAY(last_few_calendar_months.day)+1 DAY)) as month,\n\t\t\tMAX(if(_production_deployment_days.day is not null, 1, null)) as months_deployed,\n\t\t COUNT(distinct _production_deployment_days.day) as days_deployed\n\tFROM \n\t\tlast_few_calendar_months\n\t\tLEFT JOIN _production_deployment_days ON _production_deployment_days.day = last_few_calendar_months.day\n\tGROUP BY month\n\t),\n\n_days_six_months_deploy AS (\n SELECT\n month,\n SUM(days_deployed) OVER (\n ORDER BY month\n ROWS BETWEEN 5 PRECEDING AND CURRENT ROW\n ) AS days_deployed_per_six_months,\n COUNT(months_deployed) OVER (\n ORDER BY month\n ROWS BETWEEN 5 PRECEDING AND CURRENT ROW\n ) AS months_deployed_count,\n ROW_NUMBER() OVER (\n PARTITION BY DATE_FORMAT(month, '%Y-%m') DIV 6\n ORDER BY month DESC\n ) AS rn\n FROM _days_monthly_deploy\n),\n\ncalendar_weeks as(\n select \n \tdistinct date(DATE_ADD(date(day), INTERVAL -WEEKDAY(date(day)) DAY)) as start_of_week\n FROM last_few_calendar_months\n ORDER BY 1 asc\n)\n\n\nSELECT \n concat(date_format(cw.start_of_week,'%m/%d'), ' - ', date_format(DATE_ADD(cw.start_of_week, INTERVAL +6 DAY),'%m/%d')) as week,\n days_deployed\nfrom calendar_weeks cw left join _days_weekly_deploy b on cw.start_of_week = b.week", "refId": "A", "select": [ [ @@ -633,7 +633,7 @@ "metricColumn": "none", "queryType": "randomWalk", "rawQuery": true, - "rawSql": "-- Metric 1: Deployment Frequency\nwith last_few_calendar_months as(\n-- construct the last few calendar months within the selected time period in the top-right corner\n\tSELECT CAST(($__timeTo()-INTERVAL (H+T+U) DAY) AS date) day\n\tFROM ( SELECT 0 H\n\t\t\tUNION ALL SELECT 100 UNION ALL SELECT 200 UNION ALL SELECT 300\n\t\t) H CROSS JOIN ( SELECT 0 T\n\t\t\tUNION ALL SELECT 10 UNION ALL SELECT 20 UNION ALL SELECT 30\n\t\t\tUNION ALL SELECT 40 UNION ALL SELECT 50 UNION ALL SELECT 60\n\t\t\tUNION ALL SELECT 70 UNION ALL SELECT 80 UNION ALL SELECT 90\n\t\t) T CROSS JOIN ( SELECT 0 U\n\t\t\tUNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3\n\t\t\tUNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6\n\t\t\tUNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9\n\t\t) U\n\tWHERE\n\t\t($__timeTo()-INTERVAL (H+T+U) DAY) > $__timeFrom()\n),\n\n_production_deployment_days as(\n-- When deploying multiple commits in one pipeline, GitLab and BitBucket may generate more than one deployment. However, DevLake consider these deployments as ONE production deployment and use the last one's finished_date as the finished date.\n\tSELECT\n\t\tcdc.cicd_deployment_id as deployment_id,\n\t\tmax(DATE(cdc.finished_date)) as day\n\tFROM cicd_deployment_commits cdc\n\tJOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id and pm.`table` = 'cicd_scopes'\n\tWHERE\n\t\tpm.project_name in ($project)\n\t\tand cdc.result = 'SUCCESS'\n\t\tand cdc.environment = 'PRODUCTION'\n\tGROUP BY 1\n),\n\n_days_weekly_deploy as(\n-- calculate the number of deployment days every week\n\tSELECT\n\t\t\tdate(DATE_ADD(last_few_calendar_months.day, INTERVAL -WEEKDAY(last_few_calendar_months.day) DAY)) as week,\n\t\t\tMAX(if(_production_deployment_days.day is not null, 1, null)) as weeks_deployed,\n\t\t\tCOUNT(distinct _production_deployment_days.day) as days_deployed\n\tFROM \n\t\tlast_few_calendar_months\n\t\tLEFT JOIN _production_deployment_days ON _production_deployment_days.day = last_few_calendar_months.day\n\tGROUP BY week\n\t),\n\n_days_monthly_deploy as(\n-- calculate the number of deployment days every month\n\tSELECT\n\t\t\tdate(DATE_ADD(last_few_calendar_months.day, INTERVAL -DAY(last_few_calendar_months.day)+1 DAY)) as month,\n\t\t\tMAX(if(_production_deployment_days.day is not null, 1, null)) as months_deployed,\n\t\t COUNT(distinct _production_deployment_days.day) as days_deployed\n\tFROM \n\t\tlast_few_calendar_months\n\t\tLEFT JOIN _production_deployment_days ON _production_deployment_days.day = last_few_calendar_months.day\n\tGROUP BY month\n\t),\n\n_days_six_months_deploy AS (\n SELECT\n month,\n SUM(days_deployed) OVER (\n ORDER BY month\n ROWS BETWEEN 5 PRECEDING AND CURRENT ROW\n ) AS days_deployed_per_six_months,\n COUNT(months_deployed) OVER (\n ORDER BY month\n ROWS BETWEEN 5 PRECEDING AND CURRENT ROW\n ) AS months_deployed_count,\n ROW_NUMBER() OVER (\n PARTITION BY DATE_FORMAT(month, '%Y-%m') DIV 6\n ORDER BY month DESC\n ) AS rn\n FROM _days_monthly_deploy\n)\n\n\n\nSELECT \n DATE_FORMAT(month, '%y/%m') as month, days_deployed\nFROM _days_monthly_deploy", + "rawSql": "-- Metric 1: Deployment Frequency\nwith last_few_calendar_months as(\n-- construct the last few calendar months within the selected time period in the top-right corner\n\tSELECT CAST(($__timeTo()-INTERVAL (H+T+U) DAY) AS date) day\n\tFROM ( SELECT 0 H\n\t\t\tUNION ALL SELECT 100 UNION ALL SELECT 200 UNION ALL SELECT 300\n\t\t) H CROSS JOIN ( SELECT 0 T\n\t\t\tUNION ALL SELECT 10 UNION ALL SELECT 20 UNION ALL SELECT 30\n\t\t\tUNION ALL SELECT 40 UNION ALL SELECT 50 UNION ALL SELECT 60\n\t\t\tUNION ALL SELECT 70 UNION ALL SELECT 80 UNION ALL SELECT 90\n\t\t) T CROSS JOIN ( SELECT 0 U\n\t\t\tUNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3\n\t\t\tUNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6\n\t\t\tUNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9\n\t\t) U\n\tWHERE\n\t\t($__timeTo()-INTERVAL (H+T+U) DAY) > $__timeFrom()\n),\n\n_production_deployment_days as(\n-- When deploying multiple commits in one pipeline, GitLab and BitBucket may generate more than one deployment. However, DevLake consider these deployments as ONE production deployment and use the last one's finished_date as the finished date.\n\tSELECT\n\t\tcdc.cicd_deployment_id as deployment_id,\n\t\tmax(DATE(cdc.finished_date)) as day\n\tFROM cicd_deployment_commits cdc\n\tJOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id and pm.`table` = 'cicd_scopes'\n\tJOIN project_pr_metrics ppm on cdc.id = ppm.deployment_commit_id\n\tWHERE\n\t\tpm.project_name in ($project)\n\t\tand cdc.result = 'SUCCESS'\n\t\tand cdc.environment = 'PRODUCTION'\n\t\tand (ppm.is_authored_by_bot is null or ppm.is_authored_by_bot in (${author_type}))\n\tGROUP BY 1\n),\n\n_days_weekly_deploy as(\n-- calculate the number of deployment days every week\n\tSELECT\n\t\t\tdate(DATE_ADD(last_few_calendar_months.day, INTERVAL -WEEKDAY(last_few_calendar_months.day) DAY)) as week,\n\t\t\tMAX(if(_production_deployment_days.day is not null, 1, null)) as weeks_deployed,\n\t\t\tCOUNT(distinct _production_deployment_days.day) as days_deployed\n\tFROM \n\t\tlast_few_calendar_months\n\t\tLEFT JOIN _production_deployment_days ON _production_deployment_days.day = last_few_calendar_months.day\n\tGROUP BY week\n\t),\n\n_days_monthly_deploy as(\n-- calculate the number of deployment days every month\n\tSELECT\n\t\t\tdate(DATE_ADD(last_few_calendar_months.day, INTERVAL -DAY(last_few_calendar_months.day)+1 DAY)) as month,\n\t\t\tMAX(if(_production_deployment_days.day is not null, 1, null)) as months_deployed,\n\t\t COUNT(distinct _production_deployment_days.day) as days_deployed\n\tFROM \n\t\tlast_few_calendar_months\n\t\tLEFT JOIN _production_deployment_days ON _production_deployment_days.day = last_few_calendar_months.day\n\tGROUP BY month\n\t),\n\n_days_six_months_deploy AS (\n SELECT\n month,\n SUM(days_deployed) OVER (\n ORDER BY month\n ROWS BETWEEN 5 PRECEDING AND CURRENT ROW\n ) AS days_deployed_per_six_months,\n COUNT(months_deployed) OVER (\n ORDER BY month\n ROWS BETWEEN 5 PRECEDING AND CURRENT ROW\n ) AS months_deployed_count,\n ROW_NUMBER() OVER (\n PARTITION BY DATE_FORMAT(month, '%Y-%m') DIV 6\n ORDER BY month DESC\n ) AS rn\n FROM _days_monthly_deploy\n)\n\n\n\nSELECT \n DATE_FORMAT(month, '%y/%m') as month, days_deployed\nFROM _days_monthly_deploy", "refId": "A", "select": [ [ @@ -762,7 +762,7 @@ "metricColumn": "none", "queryType": "randomWalk", "rawQuery": true, - "rawSql": "-- Metric 1: Deployment Frequency\nwith last_few_calendar_months as(\n-- construct the last few calendar months within the selected time period in the top-right corner\n\tSELECT CAST(($__timeTo()-INTERVAL (H+T+U) DAY) AS date) day\n\tFROM ( SELECT 0 H\n\t\t\tUNION ALL SELECT 100 UNION ALL SELECT 200 UNION ALL SELECT 300\n\t\t) H CROSS JOIN ( SELECT 0 T\n\t\t\tUNION ALL SELECT 10 UNION ALL SELECT 20 UNION ALL SELECT 30\n\t\t\tUNION ALL SELECT 40 UNION ALL SELECT 50 UNION ALL SELECT 60\n\t\t\tUNION ALL SELECT 70 UNION ALL SELECT 80 UNION ALL SELECT 90\n\t\t) T CROSS JOIN ( SELECT 0 U\n\t\t\tUNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3\n\t\t\tUNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6\n\t\t\tUNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9\n\t\t) U\n\tWHERE\n\t\t($__timeTo()-INTERVAL (H+T+U) DAY) > $__timeFrom()\n),\n\n_production_deployment_days as(\n-- When deploying multiple commits in one pipeline, GitLab and BitBucket may generate more than one deployment. However, DevLake consider these deployments as ONE production deployment and use the last one's finished_date as the finished date.\n\tSELECT\n\t\tcdc.cicd_deployment_id as deployment_id,\n\t\tmax(DATE(cdc.finished_date)) as day\n\tFROM cicd_deployment_commits cdc\n\tJOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id and pm.`table` = 'cicd_scopes'\n\tWHERE\n\t\tpm.project_name in ($project)\n\t\tand cdc.result = 'SUCCESS'\n\t\tand cdc.environment = 'PRODUCTION'\n\tGROUP BY 1\n),\n\n_days_weekly_deploy as(\n-- calculate the number of deployment days every week\n\tSELECT\n\t\t\tdate(DATE_ADD(last_few_calendar_months.day, INTERVAL -WEEKDAY(last_few_calendar_months.day) DAY)) as week,\n\t\t\tMAX(if(_production_deployment_days.day is not null, 1, null)) as weeks_deployed,\n\t\t\tCOUNT(distinct _production_deployment_days.day) as days_deployed\n\tFROM \n\t\tlast_few_calendar_months\n\t\tLEFT JOIN _production_deployment_days ON _production_deployment_days.day = last_few_calendar_months.day\n\tGROUP BY week\n\t),\n\n_days_monthly_deploy as(\n-- calculate the number of deployment days every month\n\tSELECT\n\t\t\tdate(DATE_ADD(last_few_calendar_months.day, INTERVAL -DAY(last_few_calendar_months.day)+1 DAY)) as month,\n\t\t\tMAX(if(_production_deployment_days.day is not null, 1, null)) as months_deployed,\n\t\t COUNT(distinct _production_deployment_days.day) as days_deployed\n\tFROM \n\t\tlast_few_calendar_months\n\t\tLEFT JOIN _production_deployment_days ON _production_deployment_days.day = last_few_calendar_months.day\n\tGROUP BY month\n\t),\n\n_days_six_months_deploy AS (\n SELECT\n month,\n SUM(days_deployed) OVER (\n ORDER BY month\n ROWS BETWEEN 5 PRECEDING AND CURRENT ROW\n ) AS days_deployed_per_six_months,\n COUNT(months_deployed) OVER (\n ORDER BY month\n ROWS BETWEEN 5 PRECEDING AND CURRENT ROW\n ) AS months_deployed_count,\n ROW_NUMBER() OVER (\n PARTITION BY DATE_FORMAT(month, '%Y-%m') DIV 6\n ORDER BY month DESC\n ) AS rn\n FROM _days_monthly_deploy\n)\n\n\n\nSELECT \n CONCAT(DATE_FORMAT(DATE_SUB(month, INTERVAL 5 MONTH), '%y/%m'), ' ~ ', DATE_FORMAT(month, '%y/%m')) AS month_range, days_deployed_per_six_months as days_deployed\nFROM _days_six_months_deploy\nORDER BY month", + "rawSql": "-- Metric 1: Deployment Frequency\nwith last_few_calendar_months as(\n-- construct the last few calendar months within the selected time period in the top-right corner\n\tSELECT CAST(($__timeTo()-INTERVAL (H+T+U) DAY) AS date) day\n\tFROM ( SELECT 0 H\n\t\t\tUNION ALL SELECT 100 UNION ALL SELECT 200 UNION ALL SELECT 300\n\t\t) H CROSS JOIN ( SELECT 0 T\n\t\t\tUNION ALL SELECT 10 UNION ALL SELECT 20 UNION ALL SELECT 30\n\t\t\tUNION ALL SELECT 40 UNION ALL SELECT 50 UNION ALL SELECT 60\n\t\t\tUNION ALL SELECT 70 UNION ALL SELECT 80 UNION ALL SELECT 90\n\t\t) T CROSS JOIN ( SELECT 0 U\n\t\t\tUNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3\n\t\t\tUNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6\n\t\t\tUNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9\n\t\t) U\n\tWHERE\n\t\t($__timeTo()-INTERVAL (H+T+U) DAY) > $__timeFrom()\n),\n\n_production_deployment_days as(\n-- When deploying multiple commits in one pipeline, GitLab and BitBucket may generate more than one deployment. However, DevLake consider these deployments as ONE production deployment and use the last one's finished_date as the finished date.\n\tSELECT\n\t\tcdc.cicd_deployment_id as deployment_id,\n\t\tmax(DATE(cdc.finished_date)) as day\n\tFROM cicd_deployment_commits cdc\n\tJOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id and pm.`table` = 'cicd_scopes'\n\tJOIN project_pr_metrics ppm on cdc.id = ppm.deployment_commit_id\n\tWHERE\n\t\tpm.project_name in ($project)\n\t\tand cdc.result = 'SUCCESS'\n\t\tand cdc.environment = 'PRODUCTION'\n\t\tand (ppm.is_authored_by_bot is null or ppm.is_authored_by_bot in (${author_type}))\n\tGROUP BY 1\n),\n\n_days_weekly_deploy as(\n-- calculate the number of deployment days every week\n\tSELECT\n\t\t\tdate(DATE_ADD(last_few_calendar_months.day, INTERVAL -WEEKDAY(last_few_calendar_months.day) DAY)) as week,\n\t\t\tMAX(if(_production_deployment_days.day is not null, 1, null)) as weeks_deployed,\n\t\t\tCOUNT(distinct _production_deployment_days.day) as days_deployed\n\tFROM \n\t\tlast_few_calendar_months\n\t\tLEFT JOIN _production_deployment_days ON _production_deployment_days.day = last_few_calendar_months.day\n\tGROUP BY week\n\t),\n\n_days_monthly_deploy as(\n-- calculate the number of deployment days every month\n\tSELECT\n\t\t\tdate(DATE_ADD(last_few_calendar_months.day, INTERVAL -DAY(last_few_calendar_months.day)+1 DAY)) as month,\n\t\t\tMAX(if(_production_deployment_days.day is not null, 1, null)) as months_deployed,\n\t\t COUNT(distinct _production_deployment_days.day) as days_deployed\n\tFROM \n\t\tlast_few_calendar_months\n\t\tLEFT JOIN _production_deployment_days ON _production_deployment_days.day = last_few_calendar_months.day\n\tGROUP BY month\n\t),\n\n_days_six_months_deploy AS (\n SELECT\n month,\n SUM(days_deployed) OVER (\n ORDER BY month\n ROWS BETWEEN 5 PRECEDING AND CURRENT ROW\n ) AS days_deployed_per_six_months,\n COUNT(months_deployed) OVER (\n ORDER BY month\n ROWS BETWEEN 5 PRECEDING AND CURRENT ROW\n ) AS months_deployed_count,\n ROW_NUMBER() OVER (\n PARTITION BY DATE_FORMAT(month, '%Y-%m') DIV 6\n ORDER BY month DESC\n ) AS rn\n FROM _days_monthly_deploy\n)\n\n\n\nSELECT \n CONCAT(DATE_FORMAT(DATE_SUB(month, INTERVAL 5 MONTH), '%y/%m'), ' ~ ', DATE_FORMAT(month, '%y/%m')) AS month_range, days_deployed_per_six_months as days_deployed\nFROM _days_six_months_deploy\nORDER BY month", "refId": "A", "select": [ [ @@ -925,7 +925,7 @@ "metricColumn": "none", "queryType": "randomWalk", "rawQuery": true, - "rawSql": "-- Metric 1: Deployment Frequency\nwith last_few_calendar_months as(\n-- construct the last few calendar months within the selected time period in the top-right corner\n\tSELECT CAST(($__timeTo()-INTERVAL (H+T+U) DAY) AS date) day\n\tFROM ( SELECT 0 H\n\t\t\tUNION ALL SELECT 100 UNION ALL SELECT 200 UNION ALL SELECT 300\n\t\t) H CROSS JOIN ( SELECT 0 T\n\t\t\tUNION ALL SELECT 10 UNION ALL SELECT 20 UNION ALL SELECT 30\n\t\t\tUNION ALL SELECT 40 UNION ALL SELECT 50 UNION ALL SELECT 60\n\t\t\tUNION ALL SELECT 70 UNION ALL SELECT 80 UNION ALL SELECT 90\n\t\t) T CROSS JOIN ( SELECT 0 U\n\t\t\tUNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3\n\t\t\tUNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6\n\t\t\tUNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9\n\t\t) U\n\tWHERE\n\t\t($__timeTo()-INTERVAL (H+T+U) DAY) > $__timeFrom()\n),\n\n_production_deployment_days as(\n-- When deploying multiple commits in one pipeline, GitLab and BitBucket may generate more than one deployment. However, DevLake consider these deployments as ONE production deployment and use the last one's finished_date as the finished date.\n\tSELECT\n\t\tcdc.cicd_deployment_id as deployment_id,\n\t\tmax(DATE(cdc.finished_date)) as day\n\tFROM cicd_deployment_commits cdc\n\tJOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id and pm.`table` = 'cicd_scopes'\n\tWHERE\n\t\tpm.project_name in (${project})\n\t\tand cdc.result = 'SUCCESS'\n\t\tand cdc.environment = 'PRODUCTION'\n\tGROUP BY 1\n),\n\n_days_weekly_deploy as(\n-- calculate the number of deployment days every week\n\tSELECT\n\t\t\tdate(DATE_ADD(last_few_calendar_months.day, INTERVAL -WEEKDAY(last_few_calendar_months.day) DAY)) as week,\n\t\t\tMAX(if(_production_deployment_days.day is not null, 1, null)) as weeks_deployed,\n\t\t\tCOUNT(distinct _production_deployment_days.day) as days_deployed\n\tFROM \n\t\tlast_few_calendar_months\n\t\tLEFT JOIN _production_deployment_days ON _production_deployment_days.day = last_few_calendar_months.day\n\tGROUP BY week\n\t),\n\n_days_monthly_deploy as(\n-- calculate the number of deployment days every month\n\tSELECT\n\t\t\tdate(DATE_ADD(last_few_calendar_months.day, INTERVAL -DAY(last_few_calendar_months.day)+1 DAY)) as month,\n\t\t\tMAX(if(_production_deployment_days.day is not null, 1, null)) as months_deployed,\n\t\t COUNT(distinct _production_deployment_days.day) as days_deployed\n\tFROM \n\t\tlast_few_calendar_months\n\t\tLEFT JOIN _production_deployment_days ON _production_deployment_days.day = last_few_calendar_months.day\n\tGROUP BY month\n\t),\n\n_days_six_months_deploy AS (\n SELECT\n month,\n SUM(days_deployed) OVER (\n ORDER BY month\n ROWS BETWEEN 5 PRECEDING AND CURRENT ROW\n ) AS days_deployed_per_six_months,\n COUNT(months_deployed) OVER (\n ORDER BY month\n ROWS BETWEEN 5 PRECEDING AND CURRENT ROW\n ) AS months_deployed_count,\n ROW_NUMBER() OVER (\n PARTITION BY DATE_FORMAT(month, '%Y-%m') DIV 6\n ORDER BY month DESC\n ) AS rn\n FROM _days_monthly_deploy\n),\n\n_median_number_of_deployment_days_per_week_ranks as(\n\tSELECT *, percent_rank() over(order by days_deployed) as ranks\n\tFROM _days_weekly_deploy\n),\n\n_median_number_of_deployment_days_per_week as(\n\tSELECT max(days_deployed) as median_number_of_deployment_days_per_week\n\tFROM _median_number_of_deployment_days_per_week_ranks\n\tWHERE ranks <= 0.5\n),\n\n_median_number_of_deployment_days_per_month_ranks as(\n\tSELECT *, percent_rank() over(order by days_deployed) as ranks\n\tFROM _days_monthly_deploy\n),\n\n_median_number_of_deployment_days_per_month as(\n\tSELECT max(days_deployed) as median_number_of_deployment_days_per_month\n\tFROM _median_number_of_deployment_days_per_month_ranks\n\tWHERE ranks <= 0.5\n),\n\n_days_per_six_months_deploy_by_filter AS (\nSELECT\n month,\n days_deployed_per_six_months,\n months_deployed_count\nFROM _days_six_months_deploy\nWHERE rn%6 = 1\n),\n\n\n_median_number_of_deployment_days_per_six_months_ranks as(\n\tSELECT *, percent_rank() over(order by days_deployed_per_six_months) as ranks\n\tFROM _days_per_six_months_deploy_by_filter\n),\n\n_median_number_of_deployment_days_per_six_months as(\n\tSELECT min(days_deployed_per_six_months) as median_number_of_deployment_days_per_six_months, min(months_deployed_count) as is_collected\n\tFROM _median_number_of_deployment_days_per_six_months_ranks\n\tWHERE ranks >= 0.5\n),\n\n_tolal_production_deployment_days as(\n\tselect \n\tcount(*) as tpdd,\n\tcount(distinct day) as dtpdd\n\tfrom _production_deployment_days\n)\n\nSELECT \n -- tpdd as \"Production Deploy Counts\",\n\t-- dtpdd as \"Production Deployment Days\",\n median_number_of_deployment_days_per_week as \"Median weekly deployment days\"\n\t-- median_number_of_deployment_days_per_month as \"Median monthly deployment days\",\n\t-- median_number_of_deployment_days_per_six_months as \"Median semi-annual deployment days\"\nFROM _median_number_of_deployment_days_per_week, _median_number_of_deployment_days_per_month, _median_number_of_deployment_days_per_six_months, _tolal_production_deployment_days", + "rawSql": "-- Metric 1: Deployment Frequency\nwith last_few_calendar_months as(\n-- construct the last few calendar months within the selected time period in the top-right corner\n\tSELECT CAST(($__timeTo()-INTERVAL (H+T+U) DAY) AS date) day\n\tFROM ( SELECT 0 H\n\t\t\tUNION ALL SELECT 100 UNION ALL SELECT 200 UNION ALL SELECT 300\n\t\t) H CROSS JOIN ( SELECT 0 T\n\t\t\tUNION ALL SELECT 10 UNION ALL SELECT 20 UNION ALL SELECT 30\n\t\t\tUNION ALL SELECT 40 UNION ALL SELECT 50 UNION ALL SELECT 60\n\t\t\tUNION ALL SELECT 70 UNION ALL SELECT 80 UNION ALL SELECT 90\n\t\t) T CROSS JOIN ( SELECT 0 U\n\t\t\tUNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3\n\t\t\tUNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6\n\t\t\tUNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9\n\t\t) U\n\tWHERE\n\t\t($__timeTo()-INTERVAL (H+T+U) DAY) > $__timeFrom()\n),\n\n_production_deployment_days as(\n-- When deploying multiple commits in one pipeline, GitLab and BitBucket may generate more than one deployment. However, DevLake consider these deployments as ONE production deployment and use the last one's finished_date as the finished date.\n\tSELECT\n\t\tcdc.cicd_deployment_id as deployment_id,\n\t\tmax(DATE(cdc.finished_date)) as day\n\tFROM cicd_deployment_commits cdc\n\tJOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id and pm.`table` = 'cicd_scopes'\n\tJOIN project_pr_metrics ppm on cdc.id = ppm.deployment_commit_id\n\tWHERE\n\t\tpm.project_name in (${project})\n\t\tand cdc.result = 'SUCCESS'\n\t\tand cdc.environment = 'PRODUCTION'\n\t\tand (ppm.is_authored_by_bot is null or ppm.is_authored_by_bot in (${author_type}))\n\tGROUP BY 1\n),\n\n_days_weekly_deploy as(\n-- calculate the number of deployment days every week\n\tSELECT\n\t\t\tdate(DATE_ADD(last_few_calendar_months.day, INTERVAL -WEEKDAY(last_few_calendar_months.day) DAY)) as week,\n\t\t\tMAX(if(_production_deployment_days.day is not null, 1, null)) as weeks_deployed,\n\t\t\tCOUNT(distinct _production_deployment_days.day) as days_deployed\n\tFROM \n\t\tlast_few_calendar_months\n\t\tLEFT JOIN _production_deployment_days ON _production_deployment_days.day = last_few_calendar_months.day\n\tGROUP BY week\n\t),\n\n_days_monthly_deploy as(\n-- calculate the number of deployment days every month\n\tSELECT\n\t\t\tdate(DATE_ADD(last_few_calendar_months.day, INTERVAL -DAY(last_few_calendar_months.day)+1 DAY)) as month,\n\t\t\tMAX(if(_production_deployment_days.day is not null, 1, null)) as months_deployed,\n\t\t COUNT(distinct _production_deployment_days.day) as days_deployed\n\tFROM \n\t\tlast_few_calendar_months\n\t\tLEFT JOIN _production_deployment_days ON _production_deployment_days.day = last_few_calendar_months.day\n\tGROUP BY month\n\t),\n\n_days_six_months_deploy AS (\n SELECT\n month,\n SUM(days_deployed) OVER (\n ORDER BY month\n ROWS BETWEEN 5 PRECEDING AND CURRENT ROW\n ) AS days_deployed_per_six_months,\n COUNT(months_deployed) OVER (\n ORDER BY month\n ROWS BETWEEN 5 PRECEDING AND CURRENT ROW\n ) AS months_deployed_count,\n ROW_NUMBER() OVER (\n PARTITION BY DATE_FORMAT(month, '%Y-%m') DIV 6\n ORDER BY month DESC\n ) AS rn\n FROM _days_monthly_deploy\n),\n\n_median_number_of_deployment_days_per_week_ranks as(\n\tSELECT *, percent_rank() over(order by days_deployed) as ranks\n\tFROM _days_weekly_deploy\n),\n\n_median_number_of_deployment_days_per_week as(\n\tSELECT max(days_deployed) as median_number_of_deployment_days_per_week\n\tFROM _median_number_of_deployment_days_per_week_ranks\n\tWHERE ranks <= 0.5\n),\n\n_median_number_of_deployment_days_per_month_ranks as(\n\tSELECT *, percent_rank() over(order by days_deployed) as ranks\n\tFROM _days_monthly_deploy\n),\n\n_median_number_of_deployment_days_per_month as(\n\tSELECT max(days_deployed) as median_number_of_deployment_days_per_month\n\tFROM _median_number_of_deployment_days_per_month_ranks\n\tWHERE ranks <= 0.5\n),\n\n_days_per_six_months_deploy_by_filter AS (\nSELECT\n month,\n days_deployed_per_six_months,\n months_deployed_count\nFROM _days_six_months_deploy\nWHERE rn%6 = 1\n),\n\n\n_median_number_of_deployment_days_per_six_months_ranks as(\n\tSELECT *, percent_rank() over(order by days_deployed_per_six_months) as ranks\n\tFROM _days_per_six_months_deploy_by_filter\n),\n\n_median_number_of_deployment_days_per_six_months as(\n\tSELECT min(days_deployed_per_six_months) as median_number_of_deployment_days_per_six_months, min(months_deployed_count) as is_collected\n\tFROM _median_number_of_deployment_days_per_six_months_ranks\n\tWHERE ranks >= 0.5\n),\n\n_tolal_production_deployment_days as(\n\tselect \n\tcount(*) as tpdd,\n\tcount(distinct day) as dtpdd\n\tfrom _production_deployment_days\n)\n\nSELECT \n -- tpdd as \"Production Deploy Counts\",\n\t-- dtpdd as \"Production Deployment Days\",\n median_number_of_deployment_days_per_week as \"Median weekly deployment days\"\n\t-- median_number_of_deployment_days_per_month as \"Median monthly deployment days\",\n\t-- median_number_of_deployment_days_per_six_months as \"Median semi-annual deployment days\"\nFROM _median_number_of_deployment_days_per_week, _median_number_of_deployment_days_per_month, _median_number_of_deployment_days_per_six_months, _tolal_production_deployment_days", "refId": "A", "select": [ [ @@ -1063,7 +1063,7 @@ "metricColumn": "none", "queryType": "randomWalk", "rawQuery": true, - "rawSql": "-- Metric 1: Deployment Frequency\nwith last_few_calendar_months as(\n-- construct the last few calendar months within the selected time period in the top-right corner\n\tSELECT CAST(($__timeTo()-INTERVAL (H+T+U) DAY) AS date) day\n\tFROM ( SELECT 0 H\n\t\t\tUNION ALL SELECT 100 UNION ALL SELECT 200 UNION ALL SELECT 300\n\t\t) H CROSS JOIN ( SELECT 0 T\n\t\t\tUNION ALL SELECT 10 UNION ALL SELECT 20 UNION ALL SELECT 30\n\t\t\tUNION ALL SELECT 40 UNION ALL SELECT 50 UNION ALL SELECT 60\n\t\t\tUNION ALL SELECT 70 UNION ALL SELECT 80 UNION ALL SELECT 90\n\t\t) T CROSS JOIN ( SELECT 0 U\n\t\t\tUNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3\n\t\t\tUNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6\n\t\t\tUNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9\n\t\t) U\n\tWHERE\n\t\t($__timeTo()-INTERVAL (H+T+U) DAY) > $__timeFrom()\n),\n\n_production_deployment_days as(\n-- When deploying multiple commits in one pipeline, GitLab and BitBucket may generate more than one deployment. However, DevLake consider these deployments as ONE production deployment and use the last one's finished_date as the finished date.\n\tSELECT\n\t\tcdc.cicd_deployment_id as deployment_id,\n\t\tmax(DATE(cdc.finished_date)) as day\n\tFROM cicd_deployment_commits cdc\n\tJOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id and pm.`table` = 'cicd_scopes'\n\tWHERE\n\t\tpm.project_name in (${project})\n\t\tand cdc.result = 'SUCCESS'\n\t\tand cdc.environment = 'PRODUCTION'\n\tGROUP BY 1\n),\n\n_days_weekly_deploy as(\n-- calculate the number of deployment days every week\n\tSELECT\n\t\t\tdate(DATE_ADD(last_few_calendar_months.day, INTERVAL -WEEKDAY(last_few_calendar_months.day) DAY)) as week,\n\t\t\tMAX(if(_production_deployment_days.day is not null, 1, null)) as weeks_deployed,\n\t\t\tCOUNT(distinct _production_deployment_days.day) as days_deployed\n\tFROM \n\t\tlast_few_calendar_months\n\t\tLEFT JOIN _production_deployment_days ON _production_deployment_days.day = last_few_calendar_months.day\n\tGROUP BY week\n\t),\n\n_days_monthly_deploy as(\n-- calculate the number of deployment days every month\n\tSELECT\n\t\t\tdate(DATE_ADD(last_few_calendar_months.day, INTERVAL -DAY(last_few_calendar_months.day)+1 DAY)) as month,\n\t\t\tMAX(if(_production_deployment_days.day is not null, 1, null)) as months_deployed,\n\t\t COUNT(distinct _production_deployment_days.day) as days_deployed\n\tFROM \n\t\tlast_few_calendar_months\n\t\tLEFT JOIN _production_deployment_days ON _production_deployment_days.day = last_few_calendar_months.day\n\tGROUP BY month\n\t),\n\n_days_six_months_deploy AS (\n SELECT\n month,\n SUM(days_deployed) OVER (\n ORDER BY month\n ROWS BETWEEN 5 PRECEDING AND CURRENT ROW\n ) AS days_deployed_per_six_months,\n COUNT(months_deployed) OVER (\n ORDER BY month\n ROWS BETWEEN 5 PRECEDING AND CURRENT ROW\n ) AS months_deployed_count,\n ROW_NUMBER() OVER (\n PARTITION BY DATE_FORMAT(month, '%Y-%m') DIV 6\n ORDER BY month DESC\n ) AS rn\n FROM _days_monthly_deploy\n),\n\n_median_number_of_deployment_days_per_week_ranks as(\n\tSELECT *, percent_rank() over(order by days_deployed) as ranks\n\tFROM _days_weekly_deploy\n),\n\n_median_number_of_deployment_days_per_week as(\n\tSELECT max(days_deployed) as median_number_of_deployment_days_per_week\n\tFROM _median_number_of_deployment_days_per_week_ranks\n\tWHERE ranks <= 0.5\n),\n\n_median_number_of_deployment_days_per_month_ranks as(\n\tSELECT *, percent_rank() over(order by days_deployed) as ranks\n\tFROM _days_monthly_deploy\n),\n\n_median_number_of_deployment_days_per_month as(\n\tSELECT max(days_deployed) as median_number_of_deployment_days_per_month\n\tFROM _median_number_of_deployment_days_per_month_ranks\n\tWHERE ranks <= 0.5\n),\n\n_days_per_six_months_deploy_by_filter AS (\nSELECT\n month,\n days_deployed_per_six_months,\n months_deployed_count\nFROM _days_six_months_deploy\nWHERE rn%6 = 1\n),\n\n\n_median_number_of_deployment_days_per_six_months_ranks as(\n\tSELECT *, percent_rank() over(order by days_deployed_per_six_months) as ranks\n\tFROM _days_per_six_months_deploy_by_filter\n),\n\n_median_number_of_deployment_days_per_six_months as(\n\tSELECT min(days_deployed_per_six_months) as median_number_of_deployment_days_per_six_months, min(months_deployed_count) as is_collected\n\tFROM _median_number_of_deployment_days_per_six_months_ranks\n\tWHERE ranks >= 0.5\n),\n\n_tolal_production_deployment_days as(\n\tselect \n\tcount(*) as tpdd,\n\tcount(distinct day) as dtpdd\n\tfrom _production_deployment_days\n)\n\nSELECT \n -- tpdd as \"Production Deploy Counts\",\n\t-- dtpdd as \"Production Deployment Days\",\n -- median_number_of_deployment_days_per_week as \"Median weekly deployment days\"\n\tmedian_number_of_deployment_days_per_month as \"Median monthly deployment days\"\n\t-- median_number_of_deployment_days_per_six_months as \"Median semi-annual deployment days\"\nFROM _median_number_of_deployment_days_per_week, _median_number_of_deployment_days_per_month, _median_number_of_deployment_days_per_six_months, _tolal_production_deployment_days", + "rawSql": "-- Metric 1: Deployment Frequency\nwith last_few_calendar_months as(\n-- construct the last few calendar months within the selected time period in the top-right corner\n\tSELECT CAST(($__timeTo()-INTERVAL (H+T+U) DAY) AS date) day\n\tFROM ( SELECT 0 H\n\t\t\tUNION ALL SELECT 100 UNION ALL SELECT 200 UNION ALL SELECT 300\n\t\t) H CROSS JOIN ( SELECT 0 T\n\t\t\tUNION ALL SELECT 10 UNION ALL SELECT 20 UNION ALL SELECT 30\n\t\t\tUNION ALL SELECT 40 UNION ALL SELECT 50 UNION ALL SELECT 60\n\t\t\tUNION ALL SELECT 70 UNION ALL SELECT 80 UNION ALL SELECT 90\n\t\t) T CROSS JOIN ( SELECT 0 U\n\t\t\tUNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3\n\t\t\tUNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6\n\t\t\tUNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9\n\t\t) U\n\tWHERE\n\t\t($__timeTo()-INTERVAL (H+T+U) DAY) > $__timeFrom()\n),\n\n_production_deployment_days as(\n-- When deploying multiple commits in one pipeline, GitLab and BitBucket may generate more than one deployment. However, DevLake consider these deployments as ONE production deployment and use the last one's finished_date as the finished date.\n\tSELECT\n\t\tcdc.cicd_deployment_id as deployment_id,\n\t\tmax(DATE(cdc.finished_date)) as day\n\tFROM cicd_deployment_commits cdc\n\tJOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id and pm.`table` = 'cicd_scopes'\n\tJOIN project_pr_metrics ppm on cdc.id = ppm.deployment_commit_id\n\tWHERE\n\t\tpm.project_name in (${project})\n\t\tand cdc.result = 'SUCCESS'\n\t\tand cdc.environment = 'PRODUCTION'\n\t\tand (ppm.is_authored_by_bot is null or ppm.is_authored_by_bot in (${author_type}))\n\tGROUP BY 1\n),\n\n_days_weekly_deploy as(\n-- calculate the number of deployment days every week\n\tSELECT\n\t\t\tdate(DATE_ADD(last_few_calendar_months.day, INTERVAL -WEEKDAY(last_few_calendar_months.day) DAY)) as week,\n\t\t\tMAX(if(_production_deployment_days.day is not null, 1, null)) as weeks_deployed,\n\t\t\tCOUNT(distinct _production_deployment_days.day) as days_deployed\n\tFROM \n\t\tlast_few_calendar_months\n\t\tLEFT JOIN _production_deployment_days ON _production_deployment_days.day = last_few_calendar_months.day\n\tGROUP BY week\n\t),\n\n_days_monthly_deploy as(\n-- calculate the number of deployment days every month\n\tSELECT\n\t\t\tdate(DATE_ADD(last_few_calendar_months.day, INTERVAL -DAY(last_few_calendar_months.day)+1 DAY)) as month,\n\t\t\tMAX(if(_production_deployment_days.day is not null, 1, null)) as months_deployed,\n\t\t COUNT(distinct _production_deployment_days.day) as days_deployed\n\tFROM \n\t\tlast_few_calendar_months\n\t\tLEFT JOIN _production_deployment_days ON _production_deployment_days.day = last_few_calendar_months.day\n\tGROUP BY month\n\t),\n\n_days_six_months_deploy AS (\n SELECT\n month,\n SUM(days_deployed) OVER (\n ORDER BY month\n ROWS BETWEEN 5 PRECEDING AND CURRENT ROW\n ) AS days_deployed_per_six_months,\n COUNT(months_deployed) OVER (\n ORDER BY month\n ROWS BETWEEN 5 PRECEDING AND CURRENT ROW\n ) AS months_deployed_count,\n ROW_NUMBER() OVER (\n PARTITION BY DATE_FORMAT(month, '%Y-%m') DIV 6\n ORDER BY month DESC\n ) AS rn\n FROM _days_monthly_deploy\n),\n\n_median_number_of_deployment_days_per_week_ranks as(\n\tSELECT *, percent_rank() over(order by days_deployed) as ranks\n\tFROM _days_weekly_deploy\n),\n\n_median_number_of_deployment_days_per_week as(\n\tSELECT max(days_deployed) as median_number_of_deployment_days_per_week\n\tFROM _median_number_of_deployment_days_per_week_ranks\n\tWHERE ranks <= 0.5\n),\n\n_median_number_of_deployment_days_per_month_ranks as(\n\tSELECT *, percent_rank() over(order by days_deployed) as ranks\n\tFROM _days_monthly_deploy\n),\n\n_median_number_of_deployment_days_per_month as(\n\tSELECT max(days_deployed) as median_number_of_deployment_days_per_month\n\tFROM _median_number_of_deployment_days_per_month_ranks\n\tWHERE ranks <= 0.5\n),\n\n_days_per_six_months_deploy_by_filter AS (\nSELECT\n month,\n days_deployed_per_six_months,\n months_deployed_count\nFROM _days_six_months_deploy\nWHERE rn%6 = 1\n),\n\n\n_median_number_of_deployment_days_per_six_months_ranks as(\n\tSELECT *, percent_rank() over(order by days_deployed_per_six_months) as ranks\n\tFROM _days_per_six_months_deploy_by_filter\n),\n\n_median_number_of_deployment_days_per_six_months as(\n\tSELECT min(days_deployed_per_six_months) as median_number_of_deployment_days_per_six_months, min(months_deployed_count) as is_collected\n\tFROM _median_number_of_deployment_days_per_six_months_ranks\n\tWHERE ranks >= 0.5\n),\n\n_tolal_production_deployment_days as(\n\tselect \n\tcount(*) as tpdd,\n\tcount(distinct day) as dtpdd\n\tfrom _production_deployment_days\n)\n\nSELECT \n -- tpdd as \"Production Deploy Counts\",\n\t-- dtpdd as \"Production Deployment Days\",\n -- median_number_of_deployment_days_per_week as \"Median weekly deployment days\"\n\tmedian_number_of_deployment_days_per_month as \"Median monthly deployment days\"\n\t-- median_number_of_deployment_days_per_six_months as \"Median semi-annual deployment days\"\nFROM _median_number_of_deployment_days_per_week, _median_number_of_deployment_days_per_month, _median_number_of_deployment_days_per_six_months, _tolal_production_deployment_days", "refId": "A", "select": [ [ @@ -1201,7 +1201,7 @@ "metricColumn": "none", "queryType": "randomWalk", "rawQuery": true, - "rawSql": "-- Metric 1: Deployment Frequency\nwith last_few_calendar_months as(\n-- construct the last few calendar months within the selected time period in the top-right corner\n\tSELECT CAST(($__timeTo()-INTERVAL (H+T+U) DAY) AS date) day\n\tFROM ( SELECT 0 H\n\t\t\tUNION ALL SELECT 100 UNION ALL SELECT 200 UNION ALL SELECT 300\n\t\t) H CROSS JOIN ( SELECT 0 T\n\t\t\tUNION ALL SELECT 10 UNION ALL SELECT 20 UNION ALL SELECT 30\n\t\t\tUNION ALL SELECT 40 UNION ALL SELECT 50 UNION ALL SELECT 60\n\t\t\tUNION ALL SELECT 70 UNION ALL SELECT 80 UNION ALL SELECT 90\n\t\t) T CROSS JOIN ( SELECT 0 U\n\t\t\tUNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3\n\t\t\tUNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6\n\t\t\tUNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9\n\t\t) U\n\tWHERE\n\t\t($__timeTo()-INTERVAL (H+T+U) DAY) > $__timeFrom()\n),\n\n_production_deployment_days as(\n-- When deploying multiple commits in one pipeline, GitLab and BitBucket may generate more than one deployment. However, DevLake consider these deployments as ONE production deployment and use the last one's finished_date as the finished date.\n\tSELECT\n\t\tcdc.cicd_deployment_id as deployment_id,\n\t\tmax(DATE(cdc.finished_date)) as day\n\tFROM cicd_deployment_commits cdc\n\tJOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id and pm.`table` = 'cicd_scopes'\n\tWHERE\n\t\tpm.project_name in (${project})\n\t\tand cdc.result = 'SUCCESS'\n\t\tand cdc.environment = 'PRODUCTION'\n\tGROUP BY 1\n),\n\n_days_weekly_deploy as(\n-- calculate the number of deployment days every week\n\tSELECT\n\t\t\tdate(DATE_ADD(last_few_calendar_months.day, INTERVAL -WEEKDAY(last_few_calendar_months.day) DAY)) as week,\n\t\t\tMAX(if(_production_deployment_days.day is not null, 1, null)) as weeks_deployed,\n\t\t\tCOUNT(distinct _production_deployment_days.day) as days_deployed\n\tFROM \n\t\tlast_few_calendar_months\n\t\tLEFT JOIN _production_deployment_days ON _production_deployment_days.day = last_few_calendar_months.day\n\tGROUP BY week\n\t),\n\n_days_monthly_deploy as(\n-- calculate the number of deployment days every month\n\tSELECT\n\t\t\tdate(DATE_ADD(last_few_calendar_months.day, INTERVAL -DAY(last_few_calendar_months.day)+1 DAY)) as month,\n\t\t\tMAX(if(_production_deployment_days.day is not null, 1, null)) as months_deployed,\n\t\t COUNT(distinct _production_deployment_days.day) as days_deployed\n\tFROM \n\t\tlast_few_calendar_months\n\t\tLEFT JOIN _production_deployment_days ON _production_deployment_days.day = last_few_calendar_months.day\n\tGROUP BY month\n\t),\n\n_days_six_months_deploy AS (\n SELECT\n month,\n SUM(days_deployed) OVER (\n ORDER BY month\n ROWS BETWEEN 5 PRECEDING AND CURRENT ROW\n ) AS days_deployed_per_six_months,\n COUNT(months_deployed) OVER (\n ORDER BY month\n ROWS BETWEEN 5 PRECEDING AND CURRENT ROW\n ) AS months_deployed_count,\n ROW_NUMBER() OVER (\n PARTITION BY DATE_FORMAT(month, '%Y-%m') DIV 6\n ORDER BY month DESC\n ) AS rn\n FROM _days_monthly_deploy\n),\n\n_median_number_of_deployment_days_per_week_ranks as(\n\tSELECT *, percent_rank() over(order by days_deployed) as ranks\n\tFROM _days_weekly_deploy\n),\n\n_median_number_of_deployment_days_per_week as(\n\tSELECT max(days_deployed) as median_number_of_deployment_days_per_week\n\tFROM _median_number_of_deployment_days_per_week_ranks\n\tWHERE ranks <= 0.5\n),\n\n_median_number_of_deployment_days_per_month_ranks as(\n\tSELECT *, percent_rank() over(order by days_deployed) as ranks\n\tFROM _days_monthly_deploy\n),\n\n_median_number_of_deployment_days_per_month as(\n\tSELECT max(days_deployed) as median_number_of_deployment_days_per_month\n\tFROM _median_number_of_deployment_days_per_month_ranks\n\tWHERE ranks <= 0.5\n),\n\n_days_per_six_months_deploy_by_filter AS (\nSELECT\n month,\n days_deployed_per_six_months,\n months_deployed_count\nFROM _days_six_months_deploy\nWHERE rn%6 = 1\n),\n\n\n_median_number_of_deployment_days_per_six_months_ranks as(\n\tSELECT *, percent_rank() over(order by days_deployed_per_six_months) as ranks\n\tFROM _days_per_six_months_deploy_by_filter\n),\n\n_median_number_of_deployment_days_per_six_months as(\n\tSELECT min(days_deployed_per_six_months) as median_number_of_deployment_days_per_six_months, min(months_deployed_count) as is_collected\n\tFROM _median_number_of_deployment_days_per_six_months_ranks\n\tWHERE ranks >= 0.5\n),\n\n_tolal_production_deployment_days as(\n\tselect \n\tcount(*) as tpdd,\n\tcount(distinct day) as dtpdd\n\tfrom _production_deployment_days\n)\n\nSELECT \n -- tpdd as \"Production Deploy Counts\",\n\t-- dtpdd as \"Production Deployment Days\",\n -- median_number_of_deployment_days_per_week as \"Median weekly deployment days\"\n\t-- median_number_of_deployment_days_per_month as \"Median monthly deployment days\"\n\tmedian_number_of_deployment_days_per_six_months as \"Median semi-annual deployment days\"\nFROM _median_number_of_deployment_days_per_week, _median_number_of_deployment_days_per_month, _median_number_of_deployment_days_per_six_months, _tolal_production_deployment_days", + "rawSql": "-- Metric 1: Deployment Frequency\nwith last_few_calendar_months as(\n-- construct the last few calendar months within the selected time period in the top-right corner\n\tSELECT CAST(($__timeTo()-INTERVAL (H+T+U) DAY) AS date) day\n\tFROM ( SELECT 0 H\n\t\t\tUNION ALL SELECT 100 UNION ALL SELECT 200 UNION ALL SELECT 300\n\t\t) H CROSS JOIN ( SELECT 0 T\n\t\t\tUNION ALL SELECT 10 UNION ALL SELECT 20 UNION ALL SELECT 30\n\t\t\tUNION ALL SELECT 40 UNION ALL SELECT 50 UNION ALL SELECT 60\n\t\t\tUNION ALL SELECT 70 UNION ALL SELECT 80 UNION ALL SELECT 90\n\t\t) T CROSS JOIN ( SELECT 0 U\n\t\t\tUNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3\n\t\t\tUNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6\n\t\t\tUNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9\n\t\t) U\n\tWHERE\n\t\t($__timeTo()-INTERVAL (H+T+U) DAY) > $__timeFrom()\n),\n\n_production_deployment_days as(\n-- When deploying multiple commits in one pipeline, GitLab and BitBucket may generate more than one deployment. However, DevLake consider these deployments as ONE production deployment and use the last one's finished_date as the finished date.\n\tSELECT\n\t\tcdc.cicd_deployment_id as deployment_id,\n\t\tmax(DATE(cdc.finished_date)) as day\n\tFROM cicd_deployment_commits cdc\n\tJOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id and pm.`table` = 'cicd_scopes'\n\tJOIN project_pr_metrics ppm on cdc.id = ppm.deployment_commit_id\n\tWHERE\n\t\tpm.project_name in (${project})\n\t\tand cdc.result = 'SUCCESS'\n\t\tand cdc.environment = 'PRODUCTION'\n\t\tand (ppm.is_authored_by_bot is null or ppm.is_authored_by_bot in (${author_type}))\n\tGROUP BY 1\n),\n\n_days_weekly_deploy as(\n-- calculate the number of deployment days every week\n\tSELECT\n\t\t\tdate(DATE_ADD(last_few_calendar_months.day, INTERVAL -WEEKDAY(last_few_calendar_months.day) DAY)) as week,\n\t\t\tMAX(if(_production_deployment_days.day is not null, 1, null)) as weeks_deployed,\n\t\t\tCOUNT(distinct _production_deployment_days.day) as days_deployed\n\tFROM \n\t\tlast_few_calendar_months\n\t\tLEFT JOIN _production_deployment_days ON _production_deployment_days.day = last_few_calendar_months.day\n\tGROUP BY week\n\t),\n\n_days_monthly_deploy as(\n-- calculate the number of deployment days every month\n\tSELECT\n\t\t\tdate(DATE_ADD(last_few_calendar_months.day, INTERVAL -DAY(last_few_calendar_months.day)+1 DAY)) as month,\n\t\t\tMAX(if(_production_deployment_days.day is not null, 1, null)) as months_deployed,\n\t\t COUNT(distinct _production_deployment_days.day) as days_deployed\n\tFROM \n\t\tlast_few_calendar_months\n\t\tLEFT JOIN _production_deployment_days ON _production_deployment_days.day = last_few_calendar_months.day\n\tGROUP BY month\n\t),\n\n_days_six_months_deploy AS (\n SELECT\n month,\n SUM(days_deployed) OVER (\n ORDER BY month\n ROWS BETWEEN 5 PRECEDING AND CURRENT ROW\n ) AS days_deployed_per_six_months,\n COUNT(months_deployed) OVER (\n ORDER BY month\n ROWS BETWEEN 5 PRECEDING AND CURRENT ROW\n ) AS months_deployed_count,\n ROW_NUMBER() OVER (\n PARTITION BY DATE_FORMAT(month, '%Y-%m') DIV 6\n ORDER BY month DESC\n ) AS rn\n FROM _days_monthly_deploy\n),\n\n_median_number_of_deployment_days_per_week_ranks as(\n\tSELECT *, percent_rank() over(order by days_deployed) as ranks\n\tFROM _days_weekly_deploy\n),\n\n_median_number_of_deployment_days_per_week as(\n\tSELECT max(days_deployed) as median_number_of_deployment_days_per_week\n\tFROM _median_number_of_deployment_days_per_week_ranks\n\tWHERE ranks <= 0.5\n),\n\n_median_number_of_deployment_days_per_month_ranks as(\n\tSELECT *, percent_rank() over(order by days_deployed) as ranks\n\tFROM _days_monthly_deploy\n),\n\n_median_number_of_deployment_days_per_month as(\n\tSELECT max(days_deployed) as median_number_of_deployment_days_per_month\n\tFROM _median_number_of_deployment_days_per_month_ranks\n\tWHERE ranks <= 0.5\n),\n\n_days_per_six_months_deploy_by_filter AS (\nSELECT\n month,\n days_deployed_per_six_months,\n months_deployed_count\nFROM _days_six_months_deploy\nWHERE rn%6 = 1\n),\n\n\n_median_number_of_deployment_days_per_six_months_ranks as(\n\tSELECT *, percent_rank() over(order by days_deployed_per_six_months) as ranks\n\tFROM _days_per_six_months_deploy_by_filter\n),\n\n_median_number_of_deployment_days_per_six_months as(\n\tSELECT min(days_deployed_per_six_months) as median_number_of_deployment_days_per_six_months, min(months_deployed_count) as is_collected\n\tFROM _median_number_of_deployment_days_per_six_months_ranks\n\tWHERE ranks >= 0.5\n),\n\n_tolal_production_deployment_days as(\n\tselect \n\tcount(*) as tpdd,\n\tcount(distinct day) as dtpdd\n\tfrom _production_deployment_days\n)\n\nSELECT \n -- tpdd as \"Production Deploy Counts\",\n\t-- dtpdd as \"Production Deployment Days\",\n -- median_number_of_deployment_days_per_week as \"Median weekly deployment days\"\n\t-- median_number_of_deployment_days_per_month as \"Median monthly deployment days\"\n\tmedian_number_of_deployment_days_per_six_months as \"Median semi-annual deployment days\"\nFROM _median_number_of_deployment_days_per_week, _median_number_of_deployment_days_per_month, _median_number_of_deployment_days_per_six_months, _tolal_production_deployment_days", "refId": "A", "select": [ [ @@ -1318,6 +1318,30 @@ "skipUrlSync": false, "sort": 0, "type": "query" + }, + { + "current": { + "text": "$__all", + "value": "$__all" + }, + "description": "Filter Metrics by author type: Human or Bot.", + "includeAll": true, + "label": "Author Type", + "name": "author_type", + "options": [ + { + "selected": false, + "text": "Human", + "value": "0" + }, + { + "selected": false, + "text": "Bot", + "value": "1" + } + ], + "query": "Human : 0, Bot : 1", + "type": "custom" } ] }, diff --git a/grafana/dashboards/DORADetails-FailedDeploymentRecoveryTime.json b/grafana/dashboards/DORADetails-FailedDeploymentRecoveryTime.json index 4dfd6fb0638..755aaa815b2 100644 --- a/grafana/dashboards/DORADetails-FailedDeploymentRecoveryTime.json +++ b/grafana/dashboards/DORADetails-FailedDeploymentRecoveryTime.json @@ -121,7 +121,7 @@ "format": "table", "hide": false, "rawQuery": true, - "rawSql": "-- ***** 2023 report ***** --\n-- Metric 4: Failed deployment recovery time\nwith _deployments as (\n SELECT\n cdc.cicd_deployment_id as deployment_id,\n max(cdc.finished_date) as deployment_finished_date\n FROM\n cicd_deployment_commits cdc\n JOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id\n and pm.`table` = 'cicd_scopes'\n WHERE\n pm.project_name in ($project)\n and cdc.result = 'SUCCESS'\n and cdc.environment = 'PRODUCTION'\n GROUP BY\n 1\n HAVING\n $__timeFilter(max(cdc.finished_date))\n),\n_incidents_for_deployments as (\n SELECT\n i.id as incident_id,\n i.created_date as incident_create_date,\n i.resolution_date as incident_resolution_date,\n fd.deployment_id as caused_by_deployment,\n fd.deployment_finished_date,\n date_format(fd.deployment_finished_date, '%y/%m') as deployment_finished_month\n FROM\n incidents i\n left join project_incident_deployment_relationships pim on i.id = pim.id\n join _deployments fd on pim.deployment_id = fd.deployment_id\n WHERE\n $__timeFilter(i.resolution_date)\n),\n_recovery_time_ranks as (\n SELECT\n *,\n percent_rank() over(\n order by\n TIMESTAMPDIFF(\n MINUTE,\n deployment_finished_date,\n incident_resolution_date\n )\n ) as ranks\n FROM\n _incidents_for_deployments\n),\n_median_recovery_time as (\n SELECT\n max(\n TIMESTAMPDIFF(\n MINUTE,\n deployment_finished_date,\n incident_resolution_date\n )\n ) as median_recovery_time\n FROM\n _recovery_time_ranks\n WHERE\n ranks <= 0.5\n),\n\n_is_collected_data as(\n SELECT\n CASE\n WHEN EXISTS(select COUNT(d.deployment_id) from _deployments) = 0 AND EXISTS(select COUNT(i.incident_id) FROM incidents) = 0 THEN 'No deployments and incidents'\n WHEN EXISTS(select COUNT(d.deployment_id) from _deployments) = 0 THEN 'No Deployments'\n WHEN EXISTS(select COUNT(i.incident_id) FROM incidents) = 0 THEN 'No Incidents'\n Else 'No incidents are mapped to deployments'\n END AS is_collected\n FROM\n _deployments d, _incidents_for_deployments i\n)\n\nSELECT\n CASE\n WHEN is_collected = \"No deployments and incidents\" THEN \"N/A. Please check if you have collected deployments and incidents.\"\n WHEN is_collected = \"No Deployments\" THEN \"N/A. Please check if you have collected deployments.\"\n WHEN is_collected = \"No Incidents\" THEN \"N/A. Please check if you have collected incidents.\"\n WHEN median_recovery_time is not null then median_recovery_time/60 \n ELSE \"No data\"\n END AS median_recovery_time_in_hours\nFROM\n _median_recovery_time,\n _is_collected_data", + "rawSql": "-- ***** 2023 report ***** --\n-- Metric 4: Failed deployment recovery time\nwith _deployments as (\n SELECT\n cdc.cicd_deployment_id as deployment_id,\n max(cdc.finished_date) as deployment_finished_date\n FROM\n cicd_deployment_commits cdc\n JOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id\n JOIN project_pr_metrics ppm on cdc.id = ppm.deployment_commit_id\n and pm.`table` = 'cicd_scopes'\n WHERE\n pm.project_name in ($project)\n and cdc.result = 'SUCCESS'\n and cdc.environment = 'PRODUCTION'\n and (ppm.is_authored_by_bot is null or ppm.is_authored_by_bot in (${author_type}))\n GROUP BY\n 1\n HAVING\n $__timeFilter(max(cdc.finished_date))\n),\n_incidents_for_deployments as (\n SELECT\n i.id as incident_id,\n i.created_date as incident_create_date,\n i.resolution_date as incident_resolution_date,\n fd.deployment_id as caused_by_deployment,\n fd.deployment_finished_date,\n date_format(fd.deployment_finished_date, '%y/%m') as deployment_finished_month\n FROM\n incidents i\n left join project_incident_deployment_relationships pim on i.id = pim.id\n join _deployments fd on pim.deployment_id = fd.deployment_id\n WHERE\n $__timeFilter(i.resolution_date)\n),\n_recovery_time_ranks as (\n SELECT\n *,\n percent_rank() over(\n order by\n TIMESTAMPDIFF(\n MINUTE,\n deployment_finished_date,\n incident_resolution_date\n )\n ) as ranks\n FROM\n _incidents_for_deployments\n),\n_median_recovery_time as (\n SELECT\n max(\n TIMESTAMPDIFF(\n MINUTE,\n deployment_finished_date,\n incident_resolution_date\n )\n ) as median_recovery_time\n FROM\n _recovery_time_ranks\n WHERE\n ranks <= 0.5\n),\n\n_is_collected_data as(\n SELECT\n CASE\n WHEN EXISTS(select COUNT(d.deployment_id) from _deployments) = 0 AND EXISTS(select COUNT(i.incident_id) FROM incidents) = 0 THEN 'No deployments and incidents'\n WHEN EXISTS(select COUNT(d.deployment_id) from _deployments) = 0 THEN 'No Deployments'\n WHEN EXISTS(select COUNT(i.incident_id) FROM incidents) = 0 THEN 'No Incidents'\n Else 'No incidents are mapped to deployments'\n END AS is_collected\n FROM\n _deployments d, _incidents_for_deployments i\n)\n\nSELECT\n CASE\n WHEN is_collected = \"No deployments and incidents\" THEN \"N/A. Please check if you have collected deployments and incidents.\"\n WHEN is_collected = \"No Deployments\" THEN \"N/A. Please check if you have collected deployments.\"\n WHEN is_collected = \"No Incidents\" THEN \"N/A. Please check if you have collected incidents.\"\n WHEN median_recovery_time is not null then median_recovery_time/60 \n ELSE \"No data\"\n END AS median_recovery_time_in_hours\nFROM\n _median_recovery_time,\n _is_collected_data", "refId": "D", "sql": { "columns": [ @@ -314,7 +314,7 @@ "metricColumn": "none", "queryType": "randomWalk", "rawQuery": true, - "rawSql": "-- ***** 2023 report ***** --\n-- Metric 4: Failed deployment recovery time\nwith _deployments as (\n SELECT\n cdc.cicd_deployment_id as deployment_id,\n max(cdc.finished_date) as deployment_finished_date\n FROM\n cicd_deployment_commits cdc\n JOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id\n and pm.`table` = 'cicd_scopes'\n WHERE\n pm.project_name in ($project)\n and cdc.result = 'SUCCESS'\n and cdc.environment = 'PRODUCTION'\n GROUP BY\n 1\n HAVING\n $__timeFilter(max(cdc.finished_date))\n),\n_incidents_for_deployments as (\n SELECT\n fd.deployment_id as \"deployment_id\",\n fd.deployment_finished_date,\n -- date_format(fd.deployment_finished_date,'%y/%m') as deployment_finished_month,\n i.id as incident_caused_by_deployment,\n i.title as incident_title,\n i.url as incident_url,\n i.url as \"metric_hidden\",\n -- i.created_date as incident_create_date,\n i.resolution_date as incident_resolution_date,\n TIMESTAMPDIFF(\n HOUR,\n fd.deployment_finished_date,\n i.resolution_date\n ) as \"failed_deployment_recovery_time\"\n FROM\n incidents i\n left join project_incident_deployment_relationships pim on i.id = pim.id\n join _deployments fd on pim.deployment_id = fd.deployment_id\n WHERE\n $__timeFilter(i.resolution_date)\n)\nselect\n *\nFROM\n _incidents_for_deployments\nwhere\n incident_resolution_date IS NOT NULL", + "rawSql": "-- ***** 2023 report ***** --\n-- Metric 4: Failed deployment recovery time\nwith _deployments as (\n SELECT\n cdc.cicd_deployment_id as deployment_id,\n max(cdc.finished_date) as deployment_finished_date\n FROM\n cicd_deployment_commits cdc\n JOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id\n JOIN project_pr_metrics ppm on cdc.id = ppm.deployment_commit_id\n and pm.`table` = 'cicd_scopes'\n WHERE\n pm.project_name in ($project)\n and cdc.result = 'SUCCESS'\n and cdc.environment = 'PRODUCTION'\n and (ppm.is_authored_by_bot is null or ppm.is_authored_by_bot in (${author_type}))\n GROUP BY\n 1\n HAVING\n $__timeFilter(max(cdc.finished_date))\n),\n_incidents_for_deployments as (\n SELECT\n fd.deployment_id as \"deployment_id\",\n fd.deployment_finished_date,\n -- date_format(fd.deployment_finished_date,'%y/%m') as deployment_finished_month,\n i.id as incident_caused_by_deployment,\n i.title as incident_title,\n i.url as incident_url,\n i.url as \"metric_hidden\",\n -- i.created_date as incident_create_date,\n i.resolution_date as incident_resolution_date,\n TIMESTAMPDIFF(\n HOUR,\n fd.deployment_finished_date,\n i.resolution_date\n ) as \"failed_deployment_recovery_time\"\n FROM\n incidents i\n left join project_incident_deployment_relationships pim on i.id = pim.id\n join _deployments fd on pim.deployment_id = fd.deployment_id\n WHERE\n $__timeFilter(i.resolution_date)\n)\nselect\n *\nFROM\n _incidents_for_deployments\nwhere\n incident_resolution_date IS NOT NULL", "refId": "A", "select": [ [ @@ -409,7 +409,7 @@ "format": "table", "hide": false, "rawQuery": true, - "rawSql": "-- ***** 2023 report ***** --\n-- Metric 4: Failed deployment recovery time\nwith _deployments as (\n SELECT\n cdc.cicd_deployment_id as deployment_id,\n max(cdc.finished_date) as deployment_finished_date\n FROM\n cicd_deployment_commits cdc\n JOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id\n and pm.`table` = 'cicd_scopes'\n WHERE\n pm.project_name in ($project)\n and cdc.result = 'SUCCESS'\n and cdc.environment = 'PRODUCTION'\n GROUP BY\n 1\n HAVING\n $__timeFilter(max(cdc.finished_date))\n),\n_incidents_for_deployments as (\n SELECT\n i.id as incident_id,\n i.created_date as incident_create_date,\n i.resolution_date as incident_resolution_date,\n fd.deployment_id as caused_by_deployment,\n fd.deployment_finished_date,\n date_format(fd.deployment_finished_date, '%y/%m') as deployment_finished_month\n FROM\n incidents i\n left join project_incident_deployment_relationships pim on i.id = pim.id\n join _deployments fd on pim.deployment_id = fd.deployment_id\n WHERE\n $__timeFilter(i.resolution_date)\n),\n-- ***** 2021 report ***** --\n-- Metric 4: Median time to restore service \n_incidents as (\n -- get the incidents created within the selected time period in the top-right corner\n SELECT\n distinct i.id,\n cast(lead_time_minutes as signed) as lead_time_minutes\n FROM\n incidents i\n join project_mapping pm on i.scope_id = pm.row_id\n and i.`table` = pm.`table`\n and pm.`table` = 'boards'\n WHERE\n pm.project_name in (${project})\n and $__timeFilter(i.created_date)\n)\nSELECT\n COUNT(incident_id) AS total_count\nFROM\n _incidents_for_deployments", + "rawSql": "-- ***** 2023 report ***** --\n-- Metric 4: Failed deployment recovery time\nwith _deployments as (\n SELECT\n cdc.cicd_deployment_id as deployment_id,\n max(cdc.finished_date) as deployment_finished_date\n FROM\n cicd_deployment_commits cdc\n JOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id\n JOIN project_pr_metrics ppm on cdc.id = ppm.deployment_commit_id\n and pm.`table` = 'cicd_scopes'\n WHERE\n pm.project_name in ($project)\n and cdc.result = 'SUCCESS'\n and cdc.environment = 'PRODUCTION'\n and (ppm.is_authored_by_bot is null or ppm.is_authored_by_bot in (${author_type}))\n GROUP BY\n 1\n HAVING\n $__timeFilter(max(cdc.finished_date))\n),\n_incidents_for_deployments as (\n SELECT\n i.id as incident_id,\n i.created_date as incident_create_date,\n i.resolution_date as incident_resolution_date,\n fd.deployment_id as caused_by_deployment,\n fd.deployment_finished_date,\n date_format(fd.deployment_finished_date, '%y/%m') as deployment_finished_month\n FROM\n incidents i\n left join project_incident_deployment_relationships pim on i.id = pim.id\n join _deployments fd on pim.deployment_id = fd.deployment_id\n WHERE\n $__timeFilter(i.resolution_date)\n),\n-- ***** 2021 report ***** --\n-- Metric 4: Median time to restore service \n_incidents as (\n -- get the incidents created within the selected time period in the top-right corner\n SELECT\n distinct i.id,\n cast(lead_time_minutes as signed) as lead_time_minutes\n FROM\n incidents i\n join project_mapping pm on i.scope_id = pm.row_id\n and i.`table` = pm.`table`\n and pm.`table` = 'boards'\n WHERE\n pm.project_name in (${project})\n and $__timeFilter(i.created_date)\n)\nSELECT\n COUNT(incident_id) AS total_count\nFROM\n _incidents_for_deployments", "refId": "D", "sql": { "columns": [ @@ -461,6 +461,30 @@ "skipUrlSync": false, "sort": 0, "type": "query" + }, + { + "current": { + "text": "$__all", + "value": "$__all" + }, + "description": "Filter Metrics by author type: Human or Bot.", + "includeAll": true, + "label": "Author Type", + "name": "author_type", + "options": [ + { + "selected": false, + "text": "Human", + "value": "0" + }, + { + "selected": false, + "text": "Bot", + "value": "1" + } + ], + "query": "Human : 0, Bot : 1", + "type": "custom" } ] }, diff --git a/grafana/dashboards/DORADetails-LeadTimeforChanges.json b/grafana/dashboards/DORADetails-LeadTimeforChanges.json index 20b1a393e42..72ee01fd849 100644 --- a/grafana/dashboards/DORADetails-LeadTimeforChanges.json +++ b/grafana/dashboards/DORADetails-LeadTimeforChanges.json @@ -132,7 +132,7 @@ "hide": false, "metricColumn": "none", "rawQuery": true, - "rawSql": "with _prs as(\n SELECT\n pr.id,\n pr.created_date as pr_issued_date,\n -- convert null to 0 if a PR has no cycle_time to make sure cycle_time equals the sum of the four metrics below\n\t\tcoalesce(prm.pr_cycle_time/60,0) as cycle_time\n FROM pull_requests pr\n left join project_pr_metrics prm on pr.id = prm.id\n join project_mapping pm on pr.base_repo_id = pm.row_id and pm.table = 'repos' \n WHERE\n $__timeFilter(prm.pr_deployed_date)\n -- and pr.created_date >= DATE_ADD(DATE_ADD($__timeFrom(), INTERVAL -DAY($__timeFrom())+1 DAY), INTERVAL +1 MONTH)\n and pm.project_name in (${project})\n GROUP BY 1,2,3\n)\n\nSELECT \n avg(cycle_time) as 'PR Cycle Time(h)'\nFROM _prs", + "rawSql": "with _prs as(\n SELECT\n pr.id,\n pr.created_date as pr_issued_date,\n -- convert null to 0 if a PR has no cycle_time to make sure cycle_time equals the sum of the four metrics below\n\t\tcoalesce(prm.pr_cycle_time/60,0) as cycle_time\n FROM pull_requests pr\n left join project_pr_metrics prm on pr.id = prm.id\n join project_mapping pm on pr.base_repo_id = pm.row_id and pm.table = 'repos' \n WHERE\n $__timeFilter(prm.pr_deployed_date)\n -- and pr.created_date >= DATE_ADD(DATE_ADD($__timeFrom(), INTERVAL -DAY($__timeFrom())+1 DAY), INTERVAL +1 MONTH)\n and pm.project_name in (${project})\n and (prm.is_authored_by_bot is null or prm.is_authored_by_bot in (${author_type}))\n GROUP BY 1,2,3\n)\n\nSELECT \n avg(cycle_time) as 'PR Cycle Time(h)'\nFROM _prs", "refId": "A", "select": [ [ @@ -240,7 +240,7 @@ "hide": false, "metricColumn": "none", "rawQuery": true, - "rawSql": "with _prs as(\n SELECT\n pr.id,\n pr.created_date as pr_issued_date,\n -- convert null to 0 if a PR has no coding_time to make sure cycle_time equals the sum of the four sub-metrics\n\t\tcoalesce(prm.pr_coding_time/60,0) as coding_time\n FROM pull_requests pr\n left join project_pr_metrics prm on pr.id = prm.id\n join project_mapping pm on pr.base_repo_id = pm.row_id and pm.table = 'repos' \n WHERE\n $__timeFilter(prm.pr_deployed_date)\n -- and pr.created_date >= DATE_ADD(DATE_ADD($__timeFrom(), INTERVAL -DAY($__timeFrom())+1 DAY), INTERVAL +1 MONTH)\n and pm.project_name in (${project})\n GROUP BY 1,2,3\n)\n\nSELECT \n avg(coding_time) as 'Coding Time(h)'\nFROM _prs\n", + "rawSql": "with _prs as(\n SELECT\n pr.id,\n pr.created_date as pr_issued_date,\n -- convert null to 0 if a PR has no coding_time to make sure cycle_time equals the sum of the four sub-metrics\n\t\tcoalesce(prm.pr_coding_time/60,0) as coding_time\n FROM pull_requests pr\n left join project_pr_metrics prm on pr.id = prm.id\n join project_mapping pm on pr.base_repo_id = pm.row_id and pm.table = 'repos' \n WHERE\n $__timeFilter(prm.pr_deployed_date)\n -- and pr.created_date >= DATE_ADD(DATE_ADD($__timeFrom(), INTERVAL -DAY($__timeFrom())+1 DAY), INTERVAL +1 MONTH)\n and pm.project_name in (${project})\n and (prm.is_authored_by_bot is null or prm.is_authored_by_bot in (${author_type}))\n GROUP BY 1,2,3\n)\n\nSELECT \n avg(coding_time) as 'Coding Time(h)'\nFROM _prs\n", "refId": "A", "select": [ [ @@ -379,7 +379,7 @@ "hide": false, "metricColumn": "none", "rawQuery": true, - "rawSql": "with _prs as(\n SELECT\n pr.id,\n pr.created_date as pr_issued_date,\n -- convert null to 0 if a PR has no pickup_time to make sure cycle_time equals the sum of the four sub-metrics\n\t\tcoalesce(prm.pr_pickup_time/60,0) as pickup_time\n FROM pull_requests pr\n left join project_pr_metrics prm on pr.id = prm.id\n join project_mapping pm on pr.base_repo_id = pm.row_id and pm.table = 'repos' \n WHERE\n $__timeFilter(prm.pr_deployed_date)\n -- and pr.created_date >= DATE_ADD(DATE_ADD($__timeFrom(), INTERVAL -DAY($__timeFrom())+1 DAY), INTERVAL +1 MONTH)\n and pm.project_name in (${project})\n GROUP BY 1,2,3\n)\n\nSELECT \n avg(pickup_time) as 'Pickup Time(h)'\nFROM _prs\n", + "rawSql": "with _prs as(\n SELECT\n pr.id,\n pr.created_date as pr_issued_date,\n -- convert null to 0 if a PR has no pickup_time to make sure cycle_time equals the sum of the four sub-metrics\n\t\tcoalesce(prm.pr_pickup_time/60,0) as pickup_time\n FROM pull_requests pr\n left join project_pr_metrics prm on pr.id = prm.id\n join project_mapping pm on pr.base_repo_id = pm.row_id and pm.table = 'repos' \n WHERE\n $__timeFilter(prm.pr_deployed_date)\n -- and pr.created_date >= DATE_ADD(DATE_ADD($__timeFrom(), INTERVAL -DAY($__timeFrom())+1 DAY), INTERVAL +1 MONTH)\n and pm.project_name in (${project})\n and (prm.is_authored_by_bot is null or prm.is_authored_by_bot in (${author_type}))\n GROUP BY 1,2,3\n)\n\nSELECT \n avg(pickup_time) as 'Pickup Time(h)'\nFROM _prs\n", "refId": "A", "select": [ [ @@ -518,7 +518,7 @@ "hide": false, "metricColumn": "none", "rawQuery": true, - "rawSql": "with _prs as(\n SELECT\n pr.id,\n pr.created_date as pr_issued_date,\n -- convert null to 0 if a PR has no review_time to make sure cycle_time equals the sum of the four sub-metrics\n\t\tcoalesce(prm.pr_review_time/60,0) as review_time\n FROM pull_requests pr\n left join project_pr_metrics prm on pr.id = prm.id\n join project_mapping pm on pr.base_repo_id = pm.row_id and pm.table = 'repos' \n WHERE\n $__timeFilter(prm.pr_deployed_date)\n -- and pr.created_date >= DATE_ADD(DATE_ADD($__timeFrom(), INTERVAL -DAY($__timeFrom())+1 DAY), INTERVAL +1 MONTH)\n and pm.project_name in (${project})\n GROUP BY 1,2,3\n)\n\nSELECT \n avg(review_time) as 'Review Time(h)'\nFROM _prs", + "rawSql": "with _prs as(\n SELECT\n pr.id,\n pr.created_date as pr_issued_date,\n -- convert null to 0 if a PR has no review_time to make sure cycle_time equals the sum of the four sub-metrics\n\t\tcoalesce(prm.pr_review_time/60,0) as review_time\n FROM pull_requests pr\n left join project_pr_metrics prm on pr.id = prm.id\n join project_mapping pm on pr.base_repo_id = pm.row_id and pm.table = 'repos' \n WHERE\n $__timeFilter(prm.pr_deployed_date)\n -- and pr.created_date >= DATE_ADD(DATE_ADD($__timeFrom(), INTERVAL -DAY($__timeFrom())+1 DAY), INTERVAL +1 MONTH)\n and pm.project_name in (${project})\n and (prm.is_authored_by_bot is null or prm.is_authored_by_bot in (${author_type}))\n GROUP BY 1,2,3\n)\n\nSELECT \n avg(review_time) as 'Review Time(h)'\nFROM _prs", "refId": "A", "select": [ [ @@ -657,7 +657,7 @@ "hide": false, "metricColumn": "none", "rawQuery": true, - "rawSql": "with _prs as(\n SELECT\n pr.id,\n pr.created_date as pr_issued_date,\n -- convert null to 0 if a PR has no deploy_time to make sure cycle_time equals the sum of the four sub-metrics\n\t\tcoalesce(prm.pr_deploy_time/60,0) as deploy_time\n FROM pull_requests pr\n left join project_pr_metrics prm on pr.id = prm.id\n join project_mapping pm on pr.base_repo_id = pm.row_id and pm.table = 'repos' \n WHERE\n $__timeFilter(prm.pr_deployed_date)\n -- and pr.created_date >= DATE_ADD(DATE_ADD($__timeFrom(), INTERVAL -DAY($__timeFrom())+1 DAY), INTERVAL +1 MONTH)\n and pm.project_name in (${project})\n GROUP BY 1,2,3\n)\n\nSELECT \n avg(deploy_time) as 'PR Deploy Time(h)'\nFROM _prs", + "rawSql": "with _prs as(\n SELECT\n pr.id,\n pr.created_date as pr_issued_date,\n -- convert null to 0 if a PR has no deploy_time to make sure cycle_time equals the sum of the four sub-metrics\n\t\tcoalesce(prm.pr_deploy_time/60,0) as deploy_time\n FROM pull_requests pr\n left join project_pr_metrics prm on pr.id = prm.id\n join project_mapping pm on pr.base_repo_id = pm.row_id and pm.table = 'repos' \n WHERE\n $__timeFilter(prm.pr_deployed_date)\n -- and pr.created_date >= DATE_ADD(DATE_ADD($__timeFrom(), INTERVAL -DAY($__timeFrom())+1 DAY), INTERVAL +1 MONTH)\n and pm.project_name in (${project})\n and (prm.is_authored_by_bot is null or prm.is_authored_by_bot in (${author_type}))\n GROUP BY 1,2,3\n)\n\nSELECT \n avg(deploy_time) as 'PR Deploy Time(h)'\nFROM _prs", "refId": "A", "select": [ [ @@ -833,7 +833,7 @@ "hide": false, "metricColumn": "none", "rawQuery": true, - "rawSql": "with _pr_stats as (\n-- get the cycle time of PRs deployed by the deployments finished each month\n\tSELECT\n\t\tdistinct\n\t\tpr.id,\n\t\tpr.title,\n\t\tpr.url,\n\t\tpr.created_date,\n\t\tppm.pr_coding_time,\n\t\tppm.pr_pickup_time,\n\t\tppm.pr_review_time,\n\t\tppm.pr_deploy_time,\n\t\tppm.first_commit_sha,\n\t\tprc.commit_authored_date,\n\t\tcdc.cicd_deployment_id,\n\t\tcdc.name, \n\t\tcdc.finished_date,\n\t\tppm.pr_cycle_time\n\tFROM\n\t\tpull_requests pr\n\t\tjoin project_pr_metrics ppm on ppm.id = pr.id\n\t\tjoin project_mapping pm on pr.base_repo_id = pm.row_id and pm.`table` = 'repos'\n\t\tjoin cicd_deployment_commits cdc on ppm.deployment_commit_id = cdc.id\n\t\tjoin pull_request_commits prc on prc.commit_sha = ppm.first_commit_sha\n\tWHERE\n\t\tpm.project_name in ($project) \n\t\tand pr.merged_date is not null\n\t\tand ppm.pr_cycle_time is not null\n\t\tand $__timeFilter(cdc.finished_date)\n)\n\nSELECT \n -- id as \"PR id\",\n\ttitle as \"PR title\",\n\turl as \"PR url\",\n\turl as metric_hidden,\n -- created_date as \"PR created_date\",\n\tfirst_commit_sha as \"First commit sha\",\n\tcommit_authored_date as \"First commit authored date\",\n\tcicd_deployment_id as \"Deployment id\",\n\t-- name as \"Deployment name\", \n\tfinished_date as \"Deployment finished_date\", \n\tpr_coding_time/60 as \"pr_coding_time\",\n\tpr_pickup_time/60 as \"pr_pickup_time\",\n\tpr_review_time/60 as \"pr_review_time\",\n\tpr_deploy_time/60 as \"pr_deploy_time\",\n pr_cycle_time/60 as change_lead_time\nFROM _pr_stats\n", + "rawSql": "with _pr_stats as (\n-- get the cycle time of PRs deployed by the deployments finished each month\n\tSELECT\n\t\tdistinct\n\t\tpr.id,\n\t\tpr.title,\n\t\tpr.url,\n\t\tpr.created_date,\n\t\tppm.pr_coding_time,\n\t\tppm.pr_pickup_time,\n\t\tppm.pr_review_time,\n\t\tppm.pr_deploy_time,\n\t\tppm.first_commit_sha,\n\t\tprc.commit_authored_date,\n\t\tcdc.cicd_deployment_id,\n\t\tcdc.name, \n\t\tcdc.finished_date,\n\t\tppm.pr_cycle_time\n\tFROM\n\t\tpull_requests pr\n\t\tjoin project_pr_metrics ppm on ppm.id = pr.id\n\t\tjoin project_mapping pm on pr.base_repo_id = pm.row_id and pm.`table` = 'repos'\n\t\tjoin cicd_deployment_commits cdc on ppm.deployment_commit_id = cdc.id\n\t\tjoin pull_request_commits prc on prc.commit_sha = ppm.first_commit_sha\n\tWHERE\n\t\tpm.project_name in ($project) \n\t\tand pr.merged_date is not null\n\t\tand ppm.pr_cycle_time is not null\n\t\tand (ppm.is_authored_by_bot is null or ppm.is_authored_by_bot in (${author_type}))\n\t\tand $__timeFilter(cdc.finished_date)\n)\n\nSELECT \n -- id as \"PR id\",\n\ttitle as \"PR title\",\n\turl as \"PR url\",\n\turl as metric_hidden,\n -- created_date as \"PR created_date\",\n\tfirst_commit_sha as \"First commit sha\",\n\tcommit_authored_date as \"First commit authored date\",\n\tcicd_deployment_id as \"Deployment id\",\n\t-- name as \"Deployment name\", \n\tfinished_date as \"Deployment finished_date\", \n\tpr_coding_time/60 as \"pr_coding_time\",\n\tpr_pickup_time/60 as \"pr_pickup_time\",\n\tpr_review_time/60 as \"pr_review_time\",\n\tpr_deploy_time/60 as \"pr_deploy_time\",\n pr_cycle_time/60 as change_lead_time\nFROM _pr_stats\n", "refId": "A", "select": [ [ @@ -951,6 +951,30 @@ "skipUrlSync": false, "sort": 0, "type": "query" + }, + { + "current": { + "text": "$__all", + "value": "$__all" + }, + "description": "Filter Metrics by author type: Human or Bot.", + "includeAll": true, + "label": "Author Type", + "name": "author_type", + "options": [ + { + "selected": false, + "text": "Human", + "value": "0" + }, + { + "selected": false, + "text": "Bot", + "value": "1" + } + ], + "query": "Human : 0, Bot : 1", + "type": "custom" } ] }, diff --git a/grafana/dashboards/DORADetails-TimetoRestoreService.json b/grafana/dashboards/DORADetails-TimetoRestoreService.json index 24f99a534a1..225ebe622ef 100644 --- a/grafana/dashboards/DORADetails-TimetoRestoreService.json +++ b/grafana/dashboards/DORADetails-TimetoRestoreService.json @@ -121,7 +121,7 @@ "format": "table", "hide": false, "rawQuery": true, - "rawSql": "-- ***** 2021 report ***** --\n-- Metric 4: Median time to restore service \nwith _deployments as (\n SELECT\n cdc.cicd_deployment_id as deployment_id,\n max(cdc.finished_date) as deployment_finished_date\n FROM\n cicd_deployment_commits cdc\n JOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id\n and pm.`table` = 'cicd_scopes'\n WHERE\n pm.project_name in ($project)\n and cdc.result = 'SUCCESS'\n and cdc.environment = 'PRODUCTION'\n GROUP BY\n 1\n HAVING\n $__timeFilter(max(cdc.finished_date))\n),\n_incidents as (\n -- get the incidents created within the selected time period in the top-right corner\n SELECT\n distinct i.id,\n cast(lead_time_minutes as signed) as lead_time_minutes\n FROM\n incidents i\n join project_mapping pm on i.scope_id = pm.row_id\n and pm.`table` = i.`table`\n WHERE\n pm.project_name in (${project})\n and $__timeFilter(i.resolution_date)\n),\n_median_mttr_ranks as(\n SELECT\n *,\n percent_rank() over(\n order by\n lead_time_minutes\n ) as ranks\n FROM\n _incidents\n),\n_median_mttr as(\n SELECT\n max(lead_time_minutes) as median_time_to_resolve\n FROM\n _median_mttr_ranks\n WHERE\n ranks <= 0.5\n)\nSELECT\n median_time_to_resolve / 60 AS median_time_to_resolve_in_hours\nFROM\n _median_mttr", + "rawSql": "-- ***** 2021 report ***** --\n-- Metric 4: Median time to restore service \nwith _deployments as (\n SELECT\n cdc.cicd_deployment_id as deployment_id,\n max(cdc.finished_date) as deployment_finished_date\n FROM\n cicd_deployment_commits cdc\n JOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id and pm.`table` = 'cicd_scopes'\n JOIN project_pr_metrics ppm on cdc.id = ppm.deployment_commit_id\n WHERE\n pm.project_name in ($project)\n and cdc.result = 'SUCCESS'\n and cdc.environment = 'PRODUCTION'\n and (ppm.is_authored_by_bot is null or ppm.is_authored_by_bot in (${author_type}))\n GROUP BY\n 1\n HAVING\n $__timeFilter(max(cdc.finished_date))\n),\n_incidents as (\n -- get the incidents created within the selected time period in the top-right corner\n SELECT\n distinct i.id,\n cast(lead_time_minutes as signed) as lead_time_minutes\n FROM\n incidents i\n left join project_incident_deployment_relationships pim on i.id = pim.id\n join _deployments fd on pim.deployment_id = fd.deployment_id\n join project_mapping pm on i.scope_id = pm.row_id\n and pm.`table` = i.`table`\n WHERE\n pm.project_name in (${project})\n and $__timeFilter(i.resolution_date)\n),\n_median_mttr_ranks as(\n SELECT\n *,\n percent_rank() over(\n order by\n lead_time_minutes\n ) as ranks\n FROM\n _incidents\n),\n_median_mttr as(\n SELECT\n max(lead_time_minutes) as median_time_to_resolve\n FROM\n _median_mttr_ranks\n WHERE\n ranks <= 0.5\n)\nSELECT\n median_time_to_resolve / 60 AS median_time_to_resolve_in_hours\nFROM\n _median_mttr", "refId": "D", "sql": { "columns": [ @@ -301,7 +301,7 @@ "metricColumn": "none", "queryType": "randomWalk", "rawQuery": true, - "rawSql": "-- ***** 2021 report ***** --\n-- Metric 4: Median time to restore service \nwith _incidents as (\n-- get the incidents created within the selected time period in the top-right corner\n SELECT\n distinct i.id as \"incident_id\",\n i.title,\n i.url,\n i.url as \"metric_hidden\",\n -- i.created_date,\n i.resolution_date,\n cast(lead_time_minutes/60 as signed) as time_to_restore_service\n FROM\n incidents i \n join project_mapping pm on i.scope_id = pm.row_id and pm.`table` = i.`table`\n WHERE\n pm.project_name in ($project) \n and $__timeFilter(i.resolution_date)\n)\n\nSELECT * \nFROM _incidents\nORDER BY resolution_date DESC", + "rawSql": "-- ***** 2021 report ***** --\n-- Metric 4: Median time to restore service \nwith _deployments as (\n SELECT\n cdc.cicd_deployment_id as deployment_id,\n max(cdc.finished_date) as deployment_finished_date\n FROM\n cicd_deployment_commits cdc\n JOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id\n JOIN project_pr_metrics ppm on cdc.id = ppm.deployment_commit_id\n and pm.`table` = 'cicd_scopes'\n WHERE\n pm.project_name in ($project)\n and cdc.result = 'SUCCESS'\n and cdc.environment = 'PRODUCTION'\n and (ppm.is_authored_by_bot is null or ppm.is_authored_by_bot in (${author_type}))\n GROUP BY\n 1\n HAVING\n $__timeFilter(max(cdc.finished_date))\n),\n_incidents as (\n-- get the incidents created within the selected time period in the top-right corner\n SELECT\n distinct i.id as \"incident_id\",\n i.title,\n i.url,\n i.url as \"metric_hidden\",\n -- i.created_date,\n i.resolution_date,\n cast(lead_time_minutes/60 as signed) as time_to_restore_service\n FROM\n incidents i\n left join project_incident_deployment_relationships pim on i.id = pim.id \n join project_mapping pm on i.scope_id = pm.row_id and pm.`table` = i.`table`\n join _deployments fd on pim.deployment_id = fd.deployment_id\n WHERE\n pm.project_name in ($project) \n and $__timeFilter(i.resolution_date)\n)\n\nSELECT * \nFROM _incidents\nORDER BY resolution_date DESC", "refId": "A", "select": [ [ @@ -396,7 +396,7 @@ "format": "table", "hide": false, "rawQuery": true, - "rawSql": "-- ***** 2021 report ***** --\n-- Metric 4: Median time to restore service \nwith _deployments as (\n SELECT\n cdc.cicd_deployment_id as deployment_id,\n max(cdc.finished_date) as deployment_finished_date\n FROM \n cicd_deployment_commits cdc\n JOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id and pm.`table` = 'cicd_scopes'\n WHERE\n pm.project_name in ($project)\n and cdc.result = 'SUCCESS'\n and cdc.environment = 'PRODUCTION'\n GROUP BY 1\n HAVING $__timeFilter(max(cdc.finished_date))\n),\n\n_incidents as (\n-- get the incidents created within the selected time period in the top-right corner\n SELECT\n distinct i.id,\n cast(lead_time_minutes as signed) as lead_time_minutes\n FROM\n incidents i \n join project_mapping pm on i.scope_id = pm.row_id and pm.`table` = i.`table`\n WHERE\n pm.project_name in (${project})\n and $__timeFilter(i.created_date)\n)\n\nSELECT\n COUNT(id) AS \"incident count\"\nFROM\n _incidents\n\n", + "rawSql": "-- ***** 2021 report ***** --\n-- Metric 4: Median time to restore service \nwith _deployments as (\n SELECT\n cdc.cicd_deployment_id as deployment_id,\n max(cdc.finished_date) as deployment_finished_date\n FROM \n cicd_deployment_commits cdc\n JOIN project_mapping pm on cdc.cicd_scope_id = pm.row_id and pm.`table` = 'cicd_scopes'\n JOIN project_pr_metrics ppm on cdc.id = ppm.deployment_commit_id\n WHERE\n pm.project_name in ($project)\n and cdc.result = 'SUCCESS'\n and cdc.environment = 'PRODUCTION'\n and (ppm.is_authored_by_bot is null or ppm.is_authored_by_bot in (${author_type}))\n GROUP BY 1\n HAVING $__timeFilter(max(cdc.finished_date))\n),\n\n_incidents as (\n-- get the incidents created within the selected time period in the top-right corner\n SELECT\n distinct i.id,\n cast(lead_time_minutes as signed) as lead_time_minutes\n FROM\n incidents i \n join project_mapping pm on i.scope_id = pm.row_id and pm.`table` = i.`table`\n join project_incident_deployment_relationships pim on i.id = pim.id\n join _deployments fd on pim.deployment_id = fd.deployment_id\n\n WHERE\n pm.project_name in (${project})\n and $__timeFilter(i.created_date)\n)\n\nSELECT\n COUNT(id) AS \"incident count\"\nFROM\n _incidents\n\n", "refId": "D", "sql": { "columns": [ @@ -449,6 +449,30 @@ "skipUrlSync": false, "sort": 0, "type": "query" + }, + { + "current": { + "text": "$__all", + "value": "$__all" + }, + "description": "Filter Metrics by author type: Human or Bot.", + "includeAll": true, + "label": "Author Type", + "name": "author_type", + "options": [ + { + "selected": false, + "text": "Human", + "value": "0" + }, + { + "selected": true, + "text": "Bot", + "value": "1" + } + ], + "query": "Human : 0, Bot : 1", + "type": "custom" } ] },