From 72a24d5905aae93b1995cc723297c193c14a5ca5 Mon Sep 17 00:00:00 2001 From: Chen-Wei Sun Date: Thu, 15 Oct 2026 07:48:21 +0800 Subject: [PATCH] fix(grafana): exclude PRs without a metrics row from PR time panels The PR time panels of the Engineering Throughput and Cycle Time dashboards (and the team view) LEFT JOIN project_pr_metrics and coalesce the metric to 0, so a merged PR without a project_pr_metrics row was averaged in as 0 hours. Projects without DORA enabled showed a flat 0 h on every panel. Inner join project_pr_metrics in the MySQL and PostgreSQL variants so those PRs are excluded. Projects where every merged PR has a row get the same values as before, and NULL sub-metrics within a row are still treated as 0. Closes #9225 --- ...ngineering-throughput-and-cycle-time-team-view.json | 10 +++++----- .../mysql/engineering-throughput-and-cycle-time.json | 10 +++++----- ...ngineering-throughput-and-cycle-time-team-view.json | 10 +++++----- .../engineering-throughput-and-cycle-time.json | 10 +++++----- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/grafana/dashboards/mysql/engineering-throughput-and-cycle-time-team-view.json b/grafana/dashboards/mysql/engineering-throughput-and-cycle-time-team-view.json index 175b18b61eb..80c26824089 100644 --- a/grafana/dashboards/mysql/engineering-throughput-and-cycle-time-team-view.json +++ b/grafana/dashboards/mysql/engineering-throughput-and-cycle-time-team-view.json @@ -2335,7 +2335,7 @@ "hide": false, "metricColumn": "none", "rawQuery": true, - "rawSql": "with _prs as(\n SELECT\n pr.id,\n pr.merged_date as pr_merged_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\t\tpr.author_id,\n u.id as user_id,\n u.name as user_name,\n t.id as team_id,\n t.name as team\n FROM pull_requests pr\n join project_mapping pm on pr.base_repo_id = pm.row_id and pm.table = 'repos' \n\t\tleft join project_pr_metrics prm on pr.id = prm.id\n left join user_accounts ua on pr.author_id = ua.account_id\n left join users u on ua.user_id = u.id\n left join team_users tu on u.id = tu.user_id\n left join teams t on tu.team_id = t.id\n WHERE\n $__timeFilter(pr.merged_date)\n and pm.project_name in (${project})\n GROUP BY 1,2,3,4,5,6,7,8\n)\n\nSELECT \n DATE_ADD(date(pr_merged_date), INTERVAL -$interval(date(pr_merged_date))+1 DAY) as time,\n avg(case when team_id in (${team1:singlequote}) then cycle_time end) as 'Team1: Avg Cycle Time(h)',\n avg(case when team_id in (${team2:singlequote}) then cycle_time end) as 'Team2: Avg Cycle Time(h)'\nFROM _prs\nGROUP BY 1\nORDER BY 1", + "rawSql": "with _prs as(\n SELECT\n pr.id,\n pr.merged_date as pr_merged_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\t\tpr.author_id,\n u.id as user_id,\n u.name as user_name,\n t.id as team_id,\n t.name as team\n FROM pull_requests pr\n join project_mapping pm on pr.base_repo_id = pm.row_id and pm.table = 'repos' \n\t\tjoin project_pr_metrics prm on pr.id = prm.id\n left join user_accounts ua on pr.author_id = ua.account_id\n left join users u on ua.user_id = u.id\n left join team_users tu on u.id = tu.user_id\n left join teams t on tu.team_id = t.id\n WHERE\n $__timeFilter(pr.merged_date)\n and pm.project_name in (${project})\n GROUP BY 1,2,3,4,5,6,7,8\n)\n\nSELECT \n DATE_ADD(date(pr_merged_date), INTERVAL -$interval(date(pr_merged_date))+1 DAY) as time,\n avg(case when team_id in (${team1:singlequote}) then cycle_time end) as 'Team1: Avg Cycle Time(h)',\n avg(case when team_id in (${team2:singlequote}) then cycle_time end) as 'Team2: Avg Cycle Time(h)'\nFROM _prs\nGROUP BY 1\nORDER BY 1", "refId": "A", "select": [ [ @@ -2502,7 +2502,7 @@ "hide": false, "metricColumn": "none", "rawQuery": true, - "rawSql": "with _prs as(\n SELECT\n pr.id,\n pr.merged_date as pr_merged_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\t\tpr.author_id,\n u.id as user_id,\n u.name as user_name,\n t.id as team_id,\n t.name as team\n FROM pull_requests pr\n join project_mapping pm on pr.base_repo_id = pm.row_id and pm.table = 'repos' \n\t\tleft join project_pr_metrics prm on pr.id = prm.id\n left join user_accounts ua on pr.author_id = ua.account_id\n left join users u on ua.user_id = u.id\n left join team_users tu on u.id = tu.user_id\n left join teams t on tu.team_id = t.id\n WHERE\n $__timeFilter(pr.merged_date)\n and pm.project_name in (${project})\n GROUP BY 1,2,3,4,5,6,7,8\n)\n\nSELECT \n DATE_ADD(date(pr_merged_date), INTERVAL -$interval(date(pr_merged_date))+1 DAY) as time,\n avg(case when team_id in (${team1:singlequote}) then coding_time end) as 'Team1: Avg Coding Time(h)',\n avg(case when team_id in (${team2:singlequote}) then coding_time end) as 'Team2: Avg Coding Time(h)'\nFROM _prs\nGROUP BY 1\nORDER BY 1", + "rawSql": "with _prs as(\n SELECT\n pr.id,\n pr.merged_date as pr_merged_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\t\tpr.author_id,\n u.id as user_id,\n u.name as user_name,\n t.id as team_id,\n t.name as team\n FROM pull_requests pr\n join project_mapping pm on pr.base_repo_id = pm.row_id and pm.table = 'repos' \n\t\tjoin project_pr_metrics prm on pr.id = prm.id\n left join user_accounts ua on pr.author_id = ua.account_id\n left join users u on ua.user_id = u.id\n left join team_users tu on u.id = tu.user_id\n left join teams t on tu.team_id = t.id\n WHERE\n $__timeFilter(pr.merged_date)\n and pm.project_name in (${project})\n GROUP BY 1,2,3,4,5,6,7,8\n)\n\nSELECT \n DATE_ADD(date(pr_merged_date), INTERVAL -$interval(date(pr_merged_date))+1 DAY) as time,\n avg(case when team_id in (${team1:singlequote}) then coding_time end) as 'Team1: Avg Coding Time(h)',\n avg(case when team_id in (${team2:singlequote}) then coding_time end) as 'Team2: Avg Coding Time(h)'\nFROM _prs\nGROUP BY 1\nORDER BY 1", "refId": "A", "select": [ [ @@ -2669,7 +2669,7 @@ "hide": false, "metricColumn": "none", "rawQuery": true, - "rawSql": "with _prs as(\n SELECT\n pr.id,\n pr.merged_date as pr_merged_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\t\tpr.author_id,\n u.id as user_id,\n u.name as user_name,\n t.id as team_id,\n t.name as team\n FROM pull_requests pr\n join project_mapping pm on pr.base_repo_id = pm.row_id and pm.table = 'repos' \n\t\tleft join project_pr_metrics prm on pr.id = prm.id\n left join user_accounts ua on pr.author_id = ua.account_id\n left join users u on ua.user_id = u.id\n left join team_users tu on u.id = tu.user_id\n left join teams t on tu.team_id = t.id\n WHERE\n $__timeFilter(pr.merged_date)\n and pm.project_name in (${project})\n GROUP BY 1,2,3,4,5,6,7,8\n)\n\nSELECT \n DATE_ADD(date(pr_merged_date), INTERVAL -$interval(date(pr_merged_date))+1 DAY) as time,\n avg(case when team_id in (${team1:singlequote}) then pickup_time end) as 'Team1: Avg Pickup Time(h)',\n avg(case when team_id in (${team2:singlequote}) then pickup_time end) as 'Team2: Avg Pickup Time(h)'\nFROM _prs\nGROUP BY 1\nORDER BY 1", + "rawSql": "with _prs as(\n SELECT\n pr.id,\n pr.merged_date as pr_merged_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\t\tpr.author_id,\n u.id as user_id,\n u.name as user_name,\n t.id as team_id,\n t.name as team\n FROM pull_requests pr\n join project_mapping pm on pr.base_repo_id = pm.row_id and pm.table = 'repos' \n\t\tjoin project_pr_metrics prm on pr.id = prm.id\n left join user_accounts ua on pr.author_id = ua.account_id\n left join users u on ua.user_id = u.id\n left join team_users tu on u.id = tu.user_id\n left join teams t on tu.team_id = t.id\n WHERE\n $__timeFilter(pr.merged_date)\n and pm.project_name in (${project})\n GROUP BY 1,2,3,4,5,6,7,8\n)\n\nSELECT \n DATE_ADD(date(pr_merged_date), INTERVAL -$interval(date(pr_merged_date))+1 DAY) as time,\n avg(case when team_id in (${team1:singlequote}) then pickup_time end) as 'Team1: Avg Pickup Time(h)',\n avg(case when team_id in (${team2:singlequote}) then pickup_time end) as 'Team2: Avg Pickup Time(h)'\nFROM _prs\nGROUP BY 1\nORDER BY 1", "refId": "A", "select": [ [ @@ -2836,7 +2836,7 @@ "hide": false, "metricColumn": "none", "rawQuery": true, - "rawSql": "with _prs as(\n SELECT\n pr.id,\n pr.merged_date as pr_merged_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\t\tpr.author_id,\n u.id as user_id,\n u.name as user_name,\n t.id as team_id,\n t.name as team\n FROM pull_requests pr\n join project_mapping pm on pr.base_repo_id = pm.row_id and pm.table = 'repos' \n\t\tleft join project_pr_metrics prm on pr.id = prm.id\n left join user_accounts ua on pr.author_id = ua.account_id\n left join users u on ua.user_id = u.id\n left join team_users tu on u.id = tu.user_id\n left join teams t on tu.team_id = t.id\n WHERE\n $__timeFilter(pr.merged_date)\n and pm.project_name in (${project})\n GROUP BY 1,2,3,4,5,6,7,8\n)\n\nSELECT \n DATE_ADD(date(pr_merged_date), INTERVAL -$interval(date(pr_merged_date))+1 DAY) as time,\n avg(case when team_id in (${team1:singlequote}) then review_time end) as 'Team1: Avg Review Time(h)',\n avg(case when team_id in (${team2:singlequote}) then review_time end) as 'Team2: Avg Review Time(h)'\nFROM _prs\nGROUP BY 1\nORDER BY 1", + "rawSql": "with _prs as(\n SELECT\n pr.id,\n pr.merged_date as pr_merged_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\t\tpr.author_id,\n u.id as user_id,\n u.name as user_name,\n t.id as team_id,\n t.name as team\n FROM pull_requests pr\n join project_mapping pm on pr.base_repo_id = pm.row_id and pm.table = 'repos' \n\t\tjoin project_pr_metrics prm on pr.id = prm.id\n left join user_accounts ua on pr.author_id = ua.account_id\n left join users u on ua.user_id = u.id\n left join team_users tu on u.id = tu.user_id\n left join teams t on tu.team_id = t.id\n WHERE\n $__timeFilter(pr.merged_date)\n and pm.project_name in (${project})\n GROUP BY 1,2,3,4,5,6,7,8\n)\n\nSELECT \n DATE_ADD(date(pr_merged_date), INTERVAL -$interval(date(pr_merged_date))+1 DAY) as time,\n avg(case when team_id in (${team1:singlequote}) then review_time end) as 'Team1: Avg Review Time(h)',\n avg(case when team_id in (${team2:singlequote}) then review_time end) as 'Team2: Avg Review Time(h)'\nFROM _prs\nGROUP BY 1\nORDER BY 1", "refId": "A", "select": [ [ @@ -3003,7 +3003,7 @@ "hide": false, "metricColumn": "none", "rawQuery": true, - "rawSql": "with _prs as(\n SELECT\n pr.id,\n pr.merged_date as pr_merged_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\t\tpr.author_id,\n u.id as user_id,\n u.name as user_name,\n t.id as team_id,\n t.name as team\n FROM pull_requests pr\n join project_mapping pm on pr.base_repo_id = pm.row_id and pm.table = 'repos' \n\t\tleft join project_pr_metrics prm on pr.id = prm.id\n left join user_accounts ua on pr.author_id = ua.account_id\n left join users u on ua.user_id = u.id\n left join team_users tu on u.id = tu.user_id\n left join teams t on tu.team_id = t.id\n WHERE\n $__timeFilter(pr.merged_date)\n and pm.project_name in (${project})\n GROUP BY 1,2,3,4,5,6,7,8\n)\n\nSELECT \n DATE_ADD(date(pr_merged_date), INTERVAL -$interval(date(pr_merged_date))+1 DAY) as time,\n avg(case when team_id in (${team1:singlequote}) then deploy_time end) as 'Team1: Avg Deploy Time(h)',\n avg(case when team_id in (${team2:singlequote}) then deploy_time end) as 'Team2: Avg Deploy Time(h)'\nFROM _prs\nGROUP BY 1\nORDER BY 1", + "rawSql": "with _prs as(\n SELECT\n pr.id,\n pr.merged_date as pr_merged_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\t\tpr.author_id,\n u.id as user_id,\n u.name as user_name,\n t.id as team_id,\n t.name as team\n FROM pull_requests pr\n join project_mapping pm on pr.base_repo_id = pm.row_id and pm.table = 'repos' \n\t\tjoin project_pr_metrics prm on pr.id = prm.id\n left join user_accounts ua on pr.author_id = ua.account_id\n left join users u on ua.user_id = u.id\n left join team_users tu on u.id = tu.user_id\n left join teams t on tu.team_id = t.id\n WHERE\n $__timeFilter(pr.merged_date)\n and pm.project_name in (${project})\n GROUP BY 1,2,3,4,5,6,7,8\n)\n\nSELECT \n DATE_ADD(date(pr_merged_date), INTERVAL -$interval(date(pr_merged_date))+1 DAY) as time,\n avg(case when team_id in (${team1:singlequote}) then deploy_time end) as 'Team1: Avg Deploy Time(h)',\n avg(case when team_id in (${team2:singlequote}) then deploy_time end) as 'Team2: Avg Deploy Time(h)'\nFROM _prs\nGROUP BY 1\nORDER BY 1", "refId": "A", "select": [ [ diff --git a/grafana/dashboards/mysql/engineering-throughput-and-cycle-time.json b/grafana/dashboards/mysql/engineering-throughput-and-cycle-time.json index 3db70532cd3..c1e59bb4892 100644 --- a/grafana/dashboards/mysql/engineering-throughput-and-cycle-time.json +++ b/grafana/dashboards/mysql/engineering-throughput-and-cycle-time.json @@ -1149,7 +1149,7 @@ "hide": false, "metricColumn": "none", "rawQuery": true, - "rawSql": "with _prs as(\n SELECT\n pr.id,\n pr.merged_date as pr_merged_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(pr.merged_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 DATE_ADD(date(pr_merged_date), INTERVAL - $interval(date(pr_merged_date))+1 DAY) as time,\n avg(cycle_time) as 'PR Cycle Time(h)'\nFROM _prs\nGROUP BY 1\nORDER BY 1", + "rawSql": "with _prs as(\n SELECT\n pr.id,\n pr.merged_date as pr_merged_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 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(pr.merged_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 DATE_ADD(date(pr_merged_date), INTERVAL - $interval(date(pr_merged_date))+1 DAY) as time,\n avg(cycle_time) as 'PR Cycle Time(h)'\nFROM _prs\nGROUP BY 1\nORDER BY 1", "refId": "A", "select": [ [ @@ -1285,7 +1285,7 @@ "hide": false, "metricColumn": "none", "rawQuery": true, - "rawSql": "with _prs as(\n SELECT\n pr.id,\n pr.merged_date as pr_merged_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(pr.merged_date)\n and pr.merged_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 DATE_ADD(date(pr_merged_date), INTERVAL -$interval(date(pr_merged_date))+1 DAY) as time,\n avg(coding_time) as 'Coding Time(h)'\nFROM _prs\nGROUP BY 1\nORDER BY 1", + "rawSql": "with _prs as(\n SELECT\n pr.id,\n pr.merged_date as pr_merged_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 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(pr.merged_date)\n and pr.merged_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 DATE_ADD(date(pr_merged_date), INTERVAL -$interval(date(pr_merged_date))+1 DAY) as time,\n avg(coding_time) as 'Coding Time(h)'\nFROM _prs\nGROUP BY 1\nORDER BY 1", "refId": "A", "select": [ [ @@ -1452,7 +1452,7 @@ "hide": false, "metricColumn": "none", "rawQuery": true, - "rawSql": "with _prs as(\n SELECT\n pr.id,\n pr.merged_date as pr_merged_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(pr.merged_date)\n and pr.merged_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 DATE_ADD(date(pr_merged_date), INTERVAL -$interval(date(pr_merged_date))+1 DAY) as time,\n avg(pickup_time) as 'Pickup Time(h)'\nFROM _prs\nGROUP BY 1\nORDER BY 1", + "rawSql": "with _prs as(\n SELECT\n pr.id,\n pr.merged_date as pr_merged_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 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(pr.merged_date)\n and pr.merged_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 DATE_ADD(date(pr_merged_date), INTERVAL -$interval(date(pr_merged_date))+1 DAY) as time,\n avg(pickup_time) as 'Pickup Time(h)'\nFROM _prs\nGROUP BY 1\nORDER BY 1", "refId": "A", "select": [ [ @@ -1619,7 +1619,7 @@ "hide": false, "metricColumn": "none", "rawQuery": true, - "rawSql": "with _prs as(\n SELECT\n pr.id,\n pr.merged_date as pr_merged_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(pr.created_date)\n and pr.merged_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 DATE_ADD(date(pr_merged_date), INTERVAL -$interval(date(pr_merged_date))+1 DAY) as time,\n avg(review_time) as 'Review Time(h)'\nFROM _prs\nGROUP BY 1\nORDER BY 1", + "rawSql": "with _prs as(\n SELECT\n pr.id,\n pr.merged_date as pr_merged_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 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(pr.created_date)\n and pr.merged_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 DATE_ADD(date(pr_merged_date), INTERVAL -$interval(date(pr_merged_date))+1 DAY) as time,\n avg(review_time) as 'Review Time(h)'\nFROM _prs\nGROUP BY 1\nORDER BY 1", "refId": "A", "select": [ [ @@ -1786,7 +1786,7 @@ "hide": false, "metricColumn": "none", "rawQuery": true, - "rawSql": "with _prs as(\n SELECT\n pr.id,\n pr.merged_date as pr_merged_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(pr.merged_date)\n and pr.merged_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 DATE_ADD(date(pr_merged_date), INTERVAL -$interval(date(pr_merged_date))+1 DAY) as time,\n avg(deploy_time) as 'PR Deploy Time(h)'\nFROM _prs\nGROUP BY 1\nORDER BY 1", + "rawSql": "with _prs as(\n SELECT\n pr.id,\n pr.merged_date as pr_merged_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 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(pr.merged_date)\n and pr.merged_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 DATE_ADD(date(pr_merged_date), INTERVAL -$interval(date(pr_merged_date))+1 DAY) as time,\n avg(deploy_time) as 'PR Deploy Time(h)'\nFROM _prs\nGROUP BY 1\nORDER BY 1", "refId": "A", "select": [ [ diff --git a/grafana/dashboards/postgresql/engineering-throughput-and-cycle-time-team-view.json b/grafana/dashboards/postgresql/engineering-throughput-and-cycle-time-team-view.json index 2e45236b144..b430f15e44d 100644 --- a/grafana/dashboards/postgresql/engineering-throughput-and-cycle-time-team-view.json +++ b/grafana/dashboards/postgresql/engineering-throughput-and-cycle-time-team-view.json @@ -2335,7 +2335,7 @@ "hide": false, "metricColumn": "none", "rawQuery": true, - "rawSql": "WITH _prs AS (SELECT pr.id, pr.merged_date AS pr_merged_date, COALESCE(CAST(prm.pr_cycle_time AS NUMERIC) / NULLIF(60, 0), 0) AS cycle_time /* convert null to 0 if a PR has no cycle_time to make sure cycle_time equals the sum of the four metrics below */, pr.author_id, u.id AS user_id, u.name AS user_name, t.id AS team_id, t.name AS team FROM pull_requests AS pr JOIN project_mapping AS pm ON pr.base_repo_id = pm.row_id AND pm.table = 'repos' LEFT JOIN project_pr_metrics AS prm ON pr.id = prm.id LEFT JOIN user_accounts AS ua ON pr.author_id = ua.account_id LEFT JOIN users AS u ON ua.user_id = u.id LEFT JOIN team_users AS tu ON u.id = tu.user_id LEFT JOIN teams AS t ON tu.team_id = t.id WHERE $__timeFilter(pr.merged_date) AND ('${project:csv}' = '' OR pm.project_name::text = ANY(ARRAY[${project:singlequote}]::text[])) GROUP BY 1, 2, 3, 4, 5, 6, 7, 8) SELECT CAST(pr_merged_date AS DATE) + INTERVAL '1 DAY' * (-CASE WHEN '$interval' = 'DAYOFMONTH' THEN EXTRACT(DAY FROM CAST(pr_merged_date AS DATE)) ELSE (EXTRACT(ISODOW FROM CAST(pr_merged_date AS DATE)) - 1) END + 1) AS time, AVG(CASE WHEN ('${team1:csv}' = '' OR team_id::text = ANY(ARRAY[${team1:singlequote}]::text[])) THEN cycle_time END) AS \"Team1: Avg Cycle Time(h)\", AVG(CASE WHEN ('${team2:csv}' = '' OR team_id::text = ANY(ARRAY[${team2:singlequote}]::text[])) THEN cycle_time END) AS \"Team2: Avg Cycle Time(h)\" FROM _prs GROUP BY 1 ORDER BY 1 NULLS FIRST", + "rawSql": "WITH _prs AS (SELECT pr.id, pr.merged_date AS pr_merged_date, COALESCE(CAST(prm.pr_cycle_time AS NUMERIC) / NULLIF(60, 0), 0) AS cycle_time /* convert null to 0 if a PR has no cycle_time to make sure cycle_time equals the sum of the four metrics below */, pr.author_id, u.id AS user_id, u.name AS user_name, t.id AS team_id, t.name AS team FROM pull_requests AS pr JOIN project_mapping AS pm ON pr.base_repo_id = pm.row_id AND pm.table = 'repos' JOIN project_pr_metrics AS prm ON pr.id = prm.id LEFT JOIN user_accounts AS ua ON pr.author_id = ua.account_id LEFT JOIN users AS u ON ua.user_id = u.id LEFT JOIN team_users AS tu ON u.id = tu.user_id LEFT JOIN teams AS t ON tu.team_id = t.id WHERE $__timeFilter(pr.merged_date) AND ('${project:csv}' = '' OR pm.project_name::text = ANY(ARRAY[${project:singlequote}]::text[])) GROUP BY 1, 2, 3, 4, 5, 6, 7, 8) SELECT CAST(pr_merged_date AS DATE) + INTERVAL '1 DAY' * (-CASE WHEN '$interval' = 'DAYOFMONTH' THEN EXTRACT(DAY FROM CAST(pr_merged_date AS DATE)) ELSE (EXTRACT(ISODOW FROM CAST(pr_merged_date AS DATE)) - 1) END + 1) AS time, AVG(CASE WHEN ('${team1:csv}' = '' OR team_id::text = ANY(ARRAY[${team1:singlequote}]::text[])) THEN cycle_time END) AS \"Team1: Avg Cycle Time(h)\", AVG(CASE WHEN ('${team2:csv}' = '' OR team_id::text = ANY(ARRAY[${team2:singlequote}]::text[])) THEN cycle_time END) AS \"Team2: Avg Cycle Time(h)\" FROM _prs GROUP BY 1 ORDER BY 1 NULLS FIRST", "refId": "A", "select": [ [ @@ -2502,7 +2502,7 @@ "hide": false, "metricColumn": "none", "rawQuery": true, - "rawSql": "WITH _prs AS (SELECT pr.id, pr.merged_date AS pr_merged_date, COALESCE(CAST(prm.pr_coding_time AS NUMERIC) / NULLIF(60, 0), 0) AS coding_time /* convert null to 0 if a PR has no coding_time to make sure cycle_time equals the sum of the four sub-metrics */, pr.author_id, u.id AS user_id, u.name AS user_name, t.id AS team_id, t.name AS team FROM pull_requests AS pr JOIN project_mapping AS pm ON pr.base_repo_id = pm.row_id AND pm.table = 'repos' LEFT JOIN project_pr_metrics AS prm ON pr.id = prm.id LEFT JOIN user_accounts AS ua ON pr.author_id = ua.account_id LEFT JOIN users AS u ON ua.user_id = u.id LEFT JOIN team_users AS tu ON u.id = tu.user_id LEFT JOIN teams AS t ON tu.team_id = t.id WHERE $__timeFilter(pr.merged_date) AND ('${project:csv}' = '' OR pm.project_name::text = ANY(ARRAY[${project:singlequote}]::text[])) GROUP BY 1, 2, 3, 4, 5, 6, 7, 8) SELECT CAST(pr_merged_date AS DATE) + INTERVAL '1 DAY' * (-CASE WHEN '$interval' = 'DAYOFMONTH' THEN EXTRACT(DAY FROM CAST(pr_merged_date AS DATE)) ELSE (EXTRACT(ISODOW FROM CAST(pr_merged_date AS DATE)) - 1) END + 1) AS time, AVG(CASE WHEN ('${team1:csv}' = '' OR team_id::text = ANY(ARRAY[${team1:singlequote}]::text[])) THEN coding_time END) AS \"Team1: Avg Coding Time(h)\", AVG(CASE WHEN ('${team2:csv}' = '' OR team_id::text = ANY(ARRAY[${team2:singlequote}]::text[])) THEN coding_time END) AS \"Team2: Avg Coding Time(h)\" FROM _prs GROUP BY 1 ORDER BY 1 NULLS FIRST", + "rawSql": "WITH _prs AS (SELECT pr.id, pr.merged_date AS pr_merged_date, COALESCE(CAST(prm.pr_coding_time AS NUMERIC) / NULLIF(60, 0), 0) AS coding_time /* convert null to 0 if a PR has no coding_time to make sure cycle_time equals the sum of the four sub-metrics */, pr.author_id, u.id AS user_id, u.name AS user_name, t.id AS team_id, t.name AS team FROM pull_requests AS pr JOIN project_mapping AS pm ON pr.base_repo_id = pm.row_id AND pm.table = 'repos' JOIN project_pr_metrics AS prm ON pr.id = prm.id LEFT JOIN user_accounts AS ua ON pr.author_id = ua.account_id LEFT JOIN users AS u ON ua.user_id = u.id LEFT JOIN team_users AS tu ON u.id = tu.user_id LEFT JOIN teams AS t ON tu.team_id = t.id WHERE $__timeFilter(pr.merged_date) AND ('${project:csv}' = '' OR pm.project_name::text = ANY(ARRAY[${project:singlequote}]::text[])) GROUP BY 1, 2, 3, 4, 5, 6, 7, 8) SELECT CAST(pr_merged_date AS DATE) + INTERVAL '1 DAY' * (-CASE WHEN '$interval' = 'DAYOFMONTH' THEN EXTRACT(DAY FROM CAST(pr_merged_date AS DATE)) ELSE (EXTRACT(ISODOW FROM CAST(pr_merged_date AS DATE)) - 1) END + 1) AS time, AVG(CASE WHEN ('${team1:csv}' = '' OR team_id::text = ANY(ARRAY[${team1:singlequote}]::text[])) THEN coding_time END) AS \"Team1: Avg Coding Time(h)\", AVG(CASE WHEN ('${team2:csv}' = '' OR team_id::text = ANY(ARRAY[${team2:singlequote}]::text[])) THEN coding_time END) AS \"Team2: Avg Coding Time(h)\" FROM _prs GROUP BY 1 ORDER BY 1 NULLS FIRST", "refId": "A", "select": [ [ @@ -2669,7 +2669,7 @@ "hide": false, "metricColumn": "none", "rawQuery": true, - "rawSql": "WITH _prs AS (SELECT pr.id, pr.merged_date AS pr_merged_date, COALESCE(CAST(prm.pr_pickup_time AS NUMERIC) / NULLIF(60, 0), 0) AS pickup_time /* convert null to 0 if a PR has no pickup_time to make sure cycle_time equals the sum of the four sub-metrics */, pr.author_id, u.id AS user_id, u.name AS user_name, t.id AS team_id, t.name AS team FROM pull_requests AS pr JOIN project_mapping AS pm ON pr.base_repo_id = pm.row_id AND pm.table = 'repos' LEFT JOIN project_pr_metrics AS prm ON pr.id = prm.id LEFT JOIN user_accounts AS ua ON pr.author_id = ua.account_id LEFT JOIN users AS u ON ua.user_id = u.id LEFT JOIN team_users AS tu ON u.id = tu.user_id LEFT JOIN teams AS t ON tu.team_id = t.id WHERE $__timeFilter(pr.merged_date) AND ('${project:csv}' = '' OR pm.project_name::text = ANY(ARRAY[${project:singlequote}]::text[])) GROUP BY 1, 2, 3, 4, 5, 6, 7, 8) SELECT CAST(pr_merged_date AS DATE) + INTERVAL '1 DAY' * (-CASE WHEN '$interval' = 'DAYOFMONTH' THEN EXTRACT(DAY FROM CAST(pr_merged_date AS DATE)) ELSE (EXTRACT(ISODOW FROM CAST(pr_merged_date AS DATE)) - 1) END + 1) AS time, AVG(CASE WHEN ('${team1:csv}' = '' OR team_id::text = ANY(ARRAY[${team1:singlequote}]::text[])) THEN pickup_time END) AS \"Team1: Avg Pickup Time(h)\", AVG(CASE WHEN ('${team2:csv}' = '' OR team_id::text = ANY(ARRAY[${team2:singlequote}]::text[])) THEN pickup_time END) AS \"Team2: Avg Pickup Time(h)\" FROM _prs GROUP BY 1 ORDER BY 1 NULLS FIRST", + "rawSql": "WITH _prs AS (SELECT pr.id, pr.merged_date AS pr_merged_date, COALESCE(CAST(prm.pr_pickup_time AS NUMERIC) / NULLIF(60, 0), 0) AS pickup_time /* convert null to 0 if a PR has no pickup_time to make sure cycle_time equals the sum of the four sub-metrics */, pr.author_id, u.id AS user_id, u.name AS user_name, t.id AS team_id, t.name AS team FROM pull_requests AS pr JOIN project_mapping AS pm ON pr.base_repo_id = pm.row_id AND pm.table = 'repos' JOIN project_pr_metrics AS prm ON pr.id = prm.id LEFT JOIN user_accounts AS ua ON pr.author_id = ua.account_id LEFT JOIN users AS u ON ua.user_id = u.id LEFT JOIN team_users AS tu ON u.id = tu.user_id LEFT JOIN teams AS t ON tu.team_id = t.id WHERE $__timeFilter(pr.merged_date) AND ('${project:csv}' = '' OR pm.project_name::text = ANY(ARRAY[${project:singlequote}]::text[])) GROUP BY 1, 2, 3, 4, 5, 6, 7, 8) SELECT CAST(pr_merged_date AS DATE) + INTERVAL '1 DAY' * (-CASE WHEN '$interval' = 'DAYOFMONTH' THEN EXTRACT(DAY FROM CAST(pr_merged_date AS DATE)) ELSE (EXTRACT(ISODOW FROM CAST(pr_merged_date AS DATE)) - 1) END + 1) AS time, AVG(CASE WHEN ('${team1:csv}' = '' OR team_id::text = ANY(ARRAY[${team1:singlequote}]::text[])) THEN pickup_time END) AS \"Team1: Avg Pickup Time(h)\", AVG(CASE WHEN ('${team2:csv}' = '' OR team_id::text = ANY(ARRAY[${team2:singlequote}]::text[])) THEN pickup_time END) AS \"Team2: Avg Pickup Time(h)\" FROM _prs GROUP BY 1 ORDER BY 1 NULLS FIRST", "refId": "A", "select": [ [ @@ -2836,7 +2836,7 @@ "hide": false, "metricColumn": "none", "rawQuery": true, - "rawSql": "WITH _prs AS (SELECT pr.id, pr.merged_date AS pr_merged_date, COALESCE(CAST(prm.pr_review_time AS NUMERIC) / NULLIF(60, 0), 0) AS review_time /* convert null to 0 if a PR has no review_time to make sure cycle_time equals the sum of the four sub-metrics */, pr.author_id, u.id AS user_id, u.name AS user_name, t.id AS team_id, t.name AS team FROM pull_requests AS pr JOIN project_mapping AS pm ON pr.base_repo_id = pm.row_id AND pm.table = 'repos' LEFT JOIN project_pr_metrics AS prm ON pr.id = prm.id LEFT JOIN user_accounts AS ua ON pr.author_id = ua.account_id LEFT JOIN users AS u ON ua.user_id = u.id LEFT JOIN team_users AS tu ON u.id = tu.user_id LEFT JOIN teams AS t ON tu.team_id = t.id WHERE $__timeFilter(pr.merged_date) AND ('${project:csv}' = '' OR pm.project_name::text = ANY(ARRAY[${project:singlequote}]::text[])) GROUP BY 1, 2, 3, 4, 5, 6, 7, 8) SELECT CAST(pr_merged_date AS DATE) + INTERVAL '1 DAY' * (-CASE WHEN '$interval' = 'DAYOFMONTH' THEN EXTRACT(DAY FROM CAST(pr_merged_date AS DATE)) ELSE (EXTRACT(ISODOW FROM CAST(pr_merged_date AS DATE)) - 1) END + 1) AS time, AVG(CASE WHEN ('${team1:csv}' = '' OR team_id::text = ANY(ARRAY[${team1:singlequote}]::text[])) THEN review_time END) AS \"Team1: Avg Review Time(h)\", AVG(CASE WHEN ('${team2:csv}' = '' OR team_id::text = ANY(ARRAY[${team2:singlequote}]::text[])) THEN review_time END) AS \"Team2: Avg Review Time(h)\" FROM _prs GROUP BY 1 ORDER BY 1 NULLS FIRST", + "rawSql": "WITH _prs AS (SELECT pr.id, pr.merged_date AS pr_merged_date, COALESCE(CAST(prm.pr_review_time AS NUMERIC) / NULLIF(60, 0), 0) AS review_time /* convert null to 0 if a PR has no review_time to make sure cycle_time equals the sum of the four sub-metrics */, pr.author_id, u.id AS user_id, u.name AS user_name, t.id AS team_id, t.name AS team FROM pull_requests AS pr JOIN project_mapping AS pm ON pr.base_repo_id = pm.row_id AND pm.table = 'repos' JOIN project_pr_metrics AS prm ON pr.id = prm.id LEFT JOIN user_accounts AS ua ON pr.author_id = ua.account_id LEFT JOIN users AS u ON ua.user_id = u.id LEFT JOIN team_users AS tu ON u.id = tu.user_id LEFT JOIN teams AS t ON tu.team_id = t.id WHERE $__timeFilter(pr.merged_date) AND ('${project:csv}' = '' OR pm.project_name::text = ANY(ARRAY[${project:singlequote}]::text[])) GROUP BY 1, 2, 3, 4, 5, 6, 7, 8) SELECT CAST(pr_merged_date AS DATE) + INTERVAL '1 DAY' * (-CASE WHEN '$interval' = 'DAYOFMONTH' THEN EXTRACT(DAY FROM CAST(pr_merged_date AS DATE)) ELSE (EXTRACT(ISODOW FROM CAST(pr_merged_date AS DATE)) - 1) END + 1) AS time, AVG(CASE WHEN ('${team1:csv}' = '' OR team_id::text = ANY(ARRAY[${team1:singlequote}]::text[])) THEN review_time END) AS \"Team1: Avg Review Time(h)\", AVG(CASE WHEN ('${team2:csv}' = '' OR team_id::text = ANY(ARRAY[${team2:singlequote}]::text[])) THEN review_time END) AS \"Team2: Avg Review Time(h)\" FROM _prs GROUP BY 1 ORDER BY 1 NULLS FIRST", "refId": "A", "select": [ [ @@ -3003,7 +3003,7 @@ "hide": false, "metricColumn": "none", "rawQuery": true, - "rawSql": "WITH _prs AS (SELECT pr.id, pr.merged_date AS pr_merged_date, COALESCE(CAST(prm.pr_deploy_time AS NUMERIC) / NULLIF(60, 0), 0) AS deploy_time /* convert null to 0 if a PR has no deploy_time to make sure cycle_time equals the sum of the four sub-metrics */, pr.author_id, u.id AS user_id, u.name AS user_name, t.id AS team_id, t.name AS team FROM pull_requests AS pr JOIN project_mapping AS pm ON pr.base_repo_id = pm.row_id AND pm.table = 'repos' LEFT JOIN project_pr_metrics AS prm ON pr.id = prm.id LEFT JOIN user_accounts AS ua ON pr.author_id = ua.account_id LEFT JOIN users AS u ON ua.user_id = u.id LEFT JOIN team_users AS tu ON u.id = tu.user_id LEFT JOIN teams AS t ON tu.team_id = t.id WHERE $__timeFilter(pr.merged_date) AND ('${project:csv}' = '' OR pm.project_name::text = ANY(ARRAY[${project:singlequote}]::text[])) GROUP BY 1, 2, 3, 4, 5, 6, 7, 8) SELECT CAST(pr_merged_date AS DATE) + INTERVAL '1 DAY' * (-CASE WHEN '$interval' = 'DAYOFMONTH' THEN EXTRACT(DAY FROM CAST(pr_merged_date AS DATE)) ELSE (EXTRACT(ISODOW FROM CAST(pr_merged_date AS DATE)) - 1) END + 1) AS time, AVG(CASE WHEN ('${team1:csv}' = '' OR team_id::text = ANY(ARRAY[${team1:singlequote}]::text[])) THEN deploy_time END) AS \"Team1: Avg Deploy Time(h)\", AVG(CASE WHEN ('${team2:csv}' = '' OR team_id::text = ANY(ARRAY[${team2:singlequote}]::text[])) THEN deploy_time END) AS \"Team2: Avg Deploy Time(h)\" FROM _prs GROUP BY 1 ORDER BY 1 NULLS FIRST", + "rawSql": "WITH _prs AS (SELECT pr.id, pr.merged_date AS pr_merged_date, COALESCE(CAST(prm.pr_deploy_time AS NUMERIC) / NULLIF(60, 0), 0) AS deploy_time /* convert null to 0 if a PR has no deploy_time to make sure cycle_time equals the sum of the four sub-metrics */, pr.author_id, u.id AS user_id, u.name AS user_name, t.id AS team_id, t.name AS team FROM pull_requests AS pr JOIN project_mapping AS pm ON pr.base_repo_id = pm.row_id AND pm.table = 'repos' JOIN project_pr_metrics AS prm ON pr.id = prm.id LEFT JOIN user_accounts AS ua ON pr.author_id = ua.account_id LEFT JOIN users AS u ON ua.user_id = u.id LEFT JOIN team_users AS tu ON u.id = tu.user_id LEFT JOIN teams AS t ON tu.team_id = t.id WHERE $__timeFilter(pr.merged_date) AND ('${project:csv}' = '' OR pm.project_name::text = ANY(ARRAY[${project:singlequote}]::text[])) GROUP BY 1, 2, 3, 4, 5, 6, 7, 8) SELECT CAST(pr_merged_date AS DATE) + INTERVAL '1 DAY' * (-CASE WHEN '$interval' = 'DAYOFMONTH' THEN EXTRACT(DAY FROM CAST(pr_merged_date AS DATE)) ELSE (EXTRACT(ISODOW FROM CAST(pr_merged_date AS DATE)) - 1) END + 1) AS time, AVG(CASE WHEN ('${team1:csv}' = '' OR team_id::text = ANY(ARRAY[${team1:singlequote}]::text[])) THEN deploy_time END) AS \"Team1: Avg Deploy Time(h)\", AVG(CASE WHEN ('${team2:csv}' = '' OR team_id::text = ANY(ARRAY[${team2:singlequote}]::text[])) THEN deploy_time END) AS \"Team2: Avg Deploy Time(h)\" FROM _prs GROUP BY 1 ORDER BY 1 NULLS FIRST", "refId": "A", "select": [ [ diff --git a/grafana/dashboards/postgresql/engineering-throughput-and-cycle-time.json b/grafana/dashboards/postgresql/engineering-throughput-and-cycle-time.json index 6abd47e0afd..5aa346dc94f 100644 --- a/grafana/dashboards/postgresql/engineering-throughput-and-cycle-time.json +++ b/grafana/dashboards/postgresql/engineering-throughput-and-cycle-time.json @@ -1149,7 +1149,7 @@ "hide": false, "metricColumn": "none", "rawQuery": true, - "rawSql": "WITH _prs AS (SELECT pr.id, pr.merged_date AS pr_merged_date, COALESCE(CAST(prm.pr_cycle_time AS NUMERIC) / NULLIF(60, 0), 0) AS cycle_time /* convert null to 0 if a PR has no cycle_time to make sure cycle_time equals the sum of the four metrics below */ FROM pull_requests AS pr LEFT JOIN project_pr_metrics AS prm ON pr.id = prm.id JOIN project_mapping AS pm ON pr.base_repo_id = pm.row_id AND pm.table = 'repos' WHERE $__timeFilter(pr.merged_date) AND pr.created_date >= $__timeFrom()::timestamp + INTERVAL '1 DAY' * (-EXTRACT(DAY FROM CAST($__timeFrom() AS DATE)) + 1) + INTERVAL '1 MONTH' AND ('${project:csv}' = '' OR pm.project_name::text = ANY(ARRAY[${project:singlequote}]::text[])) GROUP BY 1, 2, 3) SELECT CAST(pr_merged_date AS DATE) + INTERVAL '1 DAY' * (-CASE WHEN '$interval' = 'DAYOFMONTH' THEN EXTRACT(DAY FROM CAST(pr_merged_date AS DATE)) ELSE (EXTRACT(ISODOW FROM CAST(pr_merged_date AS DATE)) - 1) END + 1) AS time, AVG(cycle_time) AS \"PR Cycle Time(h)\" FROM _prs GROUP BY 1 ORDER BY 1 NULLS FIRST", + "rawSql": "WITH _prs AS (SELECT pr.id, pr.merged_date AS pr_merged_date, COALESCE(CAST(prm.pr_cycle_time AS NUMERIC) / NULLIF(60, 0), 0) AS cycle_time /* convert null to 0 if a PR has no cycle_time to make sure cycle_time equals the sum of the four metrics below */ FROM pull_requests AS pr JOIN project_pr_metrics AS prm ON pr.id = prm.id JOIN project_mapping AS pm ON pr.base_repo_id = pm.row_id AND pm.table = 'repos' WHERE $__timeFilter(pr.merged_date) AND pr.created_date >= $__timeFrom()::timestamp + INTERVAL '1 DAY' * (-EXTRACT(DAY FROM CAST($__timeFrom() AS DATE)) + 1) + INTERVAL '1 MONTH' AND ('${project:csv}' = '' OR pm.project_name::text = ANY(ARRAY[${project:singlequote}]::text[])) GROUP BY 1, 2, 3) SELECT CAST(pr_merged_date AS DATE) + INTERVAL '1 DAY' * (-CASE WHEN '$interval' = 'DAYOFMONTH' THEN EXTRACT(DAY FROM CAST(pr_merged_date AS DATE)) ELSE (EXTRACT(ISODOW FROM CAST(pr_merged_date AS DATE)) - 1) END + 1) AS time, AVG(cycle_time) AS \"PR Cycle Time(h)\" FROM _prs GROUP BY 1 ORDER BY 1 NULLS FIRST", "refId": "A", "select": [ [ @@ -1285,7 +1285,7 @@ "hide": false, "metricColumn": "none", "rawQuery": true, - "rawSql": "WITH _prs AS (SELECT pr.id, pr.merged_date AS pr_merged_date, COALESCE(CAST(prm.pr_coding_time AS NUMERIC) / NULLIF(60, 0), 0) AS coding_time /* convert null to 0 if a PR has no coding_time to make sure cycle_time equals the sum of the four sub-metrics */ FROM pull_requests AS pr LEFT JOIN project_pr_metrics AS prm ON pr.id = prm.id JOIN project_mapping AS pm ON pr.base_repo_id = pm.row_id AND pm.table = 'repos' WHERE $__timeFilter(pr.merged_date) AND pr.merged_date >= $__timeFrom()::timestamp + INTERVAL '1 DAY' * (-EXTRACT(DAY FROM CAST($__timeFrom() AS DATE)) + 1) + INTERVAL '1 MONTH' AND ('${project:csv}' = '' OR pm.project_name::text = ANY(ARRAY[${project:singlequote}]::text[])) GROUP BY 1, 2, 3) SELECT CAST(pr_merged_date AS DATE) + INTERVAL '1 DAY' * (-CASE WHEN '$interval' = 'DAYOFMONTH' THEN EXTRACT(DAY FROM CAST(pr_merged_date AS DATE)) ELSE (EXTRACT(ISODOW FROM CAST(pr_merged_date AS DATE)) - 1) END + 1) AS time, AVG(coding_time) AS \"Coding Time(h)\" FROM _prs GROUP BY 1 ORDER BY 1 NULLS FIRST", + "rawSql": "WITH _prs AS (SELECT pr.id, pr.merged_date AS pr_merged_date, COALESCE(CAST(prm.pr_coding_time AS NUMERIC) / NULLIF(60, 0), 0) AS coding_time /* convert null to 0 if a PR has no coding_time to make sure cycle_time equals the sum of the four sub-metrics */ FROM pull_requests AS pr JOIN project_pr_metrics AS prm ON pr.id = prm.id JOIN project_mapping AS pm ON pr.base_repo_id = pm.row_id AND pm.table = 'repos' WHERE $__timeFilter(pr.merged_date) AND pr.merged_date >= $__timeFrom()::timestamp + INTERVAL '1 DAY' * (-EXTRACT(DAY FROM CAST($__timeFrom() AS DATE)) + 1) + INTERVAL '1 MONTH' AND ('${project:csv}' = '' OR pm.project_name::text = ANY(ARRAY[${project:singlequote}]::text[])) GROUP BY 1, 2, 3) SELECT CAST(pr_merged_date AS DATE) + INTERVAL '1 DAY' * (-CASE WHEN '$interval' = 'DAYOFMONTH' THEN EXTRACT(DAY FROM CAST(pr_merged_date AS DATE)) ELSE (EXTRACT(ISODOW FROM CAST(pr_merged_date AS DATE)) - 1) END + 1) AS time, AVG(coding_time) AS \"Coding Time(h)\" FROM _prs GROUP BY 1 ORDER BY 1 NULLS FIRST", "refId": "A", "select": [ [ @@ -1452,7 +1452,7 @@ "hide": false, "metricColumn": "none", "rawQuery": true, - "rawSql": "WITH _prs AS (SELECT pr.id, pr.merged_date AS pr_merged_date, COALESCE(CAST(prm.pr_pickup_time AS NUMERIC) / NULLIF(60, 0), 0) AS pickup_time /* convert null to 0 if a PR has no pickup_time to make sure cycle_time equals the sum of the four sub-metrics */ FROM pull_requests AS pr LEFT JOIN project_pr_metrics AS prm ON pr.id = prm.id JOIN project_mapping AS pm ON pr.base_repo_id = pm.row_id AND pm.table = 'repos' WHERE $__timeFilter(pr.merged_date) AND pr.merged_date >= $__timeFrom()::timestamp + INTERVAL '1 DAY' * (-EXTRACT(DAY FROM CAST($__timeFrom() AS DATE)) + 1) + INTERVAL '1 MONTH' AND ('${project:csv}' = '' OR pm.project_name::text = ANY(ARRAY[${project:singlequote}]::text[])) GROUP BY 1, 2, 3) SELECT CAST(pr_merged_date AS DATE) + INTERVAL '1 DAY' * (-CASE WHEN '$interval' = 'DAYOFMONTH' THEN EXTRACT(DAY FROM CAST(pr_merged_date AS DATE)) ELSE (EXTRACT(ISODOW FROM CAST(pr_merged_date AS DATE)) - 1) END + 1) AS time, AVG(pickup_time) AS \"Pickup Time(h)\" FROM _prs GROUP BY 1 ORDER BY 1 NULLS FIRST", + "rawSql": "WITH _prs AS (SELECT pr.id, pr.merged_date AS pr_merged_date, COALESCE(CAST(prm.pr_pickup_time AS NUMERIC) / NULLIF(60, 0), 0) AS pickup_time /* convert null to 0 if a PR has no pickup_time to make sure cycle_time equals the sum of the four sub-metrics */ FROM pull_requests AS pr JOIN project_pr_metrics AS prm ON pr.id = prm.id JOIN project_mapping AS pm ON pr.base_repo_id = pm.row_id AND pm.table = 'repos' WHERE $__timeFilter(pr.merged_date) AND pr.merged_date >= $__timeFrom()::timestamp + INTERVAL '1 DAY' * (-EXTRACT(DAY FROM CAST($__timeFrom() AS DATE)) + 1) + INTERVAL '1 MONTH' AND ('${project:csv}' = '' OR pm.project_name::text = ANY(ARRAY[${project:singlequote}]::text[])) GROUP BY 1, 2, 3) SELECT CAST(pr_merged_date AS DATE) + INTERVAL '1 DAY' * (-CASE WHEN '$interval' = 'DAYOFMONTH' THEN EXTRACT(DAY FROM CAST(pr_merged_date AS DATE)) ELSE (EXTRACT(ISODOW FROM CAST(pr_merged_date AS DATE)) - 1) END + 1) AS time, AVG(pickup_time) AS \"Pickup Time(h)\" FROM _prs GROUP BY 1 ORDER BY 1 NULLS FIRST", "refId": "A", "select": [ [ @@ -1619,7 +1619,7 @@ "hide": false, "metricColumn": "none", "rawQuery": true, - "rawSql": "WITH _prs AS (SELECT pr.id, pr.merged_date AS pr_merged_date, COALESCE(CAST(prm.pr_review_time AS NUMERIC) / NULLIF(60, 0), 0) AS review_time /* convert null to 0 if a PR has no review_time to make sure cycle_time equals the sum of the four sub-metrics */ FROM pull_requests AS pr LEFT JOIN project_pr_metrics AS prm ON pr.id = prm.id JOIN project_mapping AS pm ON pr.base_repo_id = pm.row_id AND pm.table = 'repos' WHERE $__timeFilter(pr.created_date) AND pr.merged_date >= $__timeFrom()::timestamp + INTERVAL '1 DAY' * (-EXTRACT(DAY FROM CAST($__timeFrom() AS DATE)) + 1) + INTERVAL '1 MONTH' AND ('${project:csv}' = '' OR pm.project_name::text = ANY(ARRAY[${project:singlequote}]::text[])) GROUP BY 1, 2, 3) SELECT CAST(pr_merged_date AS DATE) + INTERVAL '1 DAY' * (-CASE WHEN '$interval' = 'DAYOFMONTH' THEN EXTRACT(DAY FROM CAST(pr_merged_date AS DATE)) ELSE (EXTRACT(ISODOW FROM CAST(pr_merged_date AS DATE)) - 1) END + 1) AS time, AVG(review_time) AS \"Review Time(h)\" FROM _prs GROUP BY 1 ORDER BY 1 NULLS FIRST", + "rawSql": "WITH _prs AS (SELECT pr.id, pr.merged_date AS pr_merged_date, COALESCE(CAST(prm.pr_review_time AS NUMERIC) / NULLIF(60, 0), 0) AS review_time /* convert null to 0 if a PR has no review_time to make sure cycle_time equals the sum of the four sub-metrics */ FROM pull_requests AS pr JOIN project_pr_metrics AS prm ON pr.id = prm.id JOIN project_mapping AS pm ON pr.base_repo_id = pm.row_id AND pm.table = 'repos' WHERE $__timeFilter(pr.created_date) AND pr.merged_date >= $__timeFrom()::timestamp + INTERVAL '1 DAY' * (-EXTRACT(DAY FROM CAST($__timeFrom() AS DATE)) + 1) + INTERVAL '1 MONTH' AND ('${project:csv}' = '' OR pm.project_name::text = ANY(ARRAY[${project:singlequote}]::text[])) GROUP BY 1, 2, 3) SELECT CAST(pr_merged_date AS DATE) + INTERVAL '1 DAY' * (-CASE WHEN '$interval' = 'DAYOFMONTH' THEN EXTRACT(DAY FROM CAST(pr_merged_date AS DATE)) ELSE (EXTRACT(ISODOW FROM CAST(pr_merged_date AS DATE)) - 1) END + 1) AS time, AVG(review_time) AS \"Review Time(h)\" FROM _prs GROUP BY 1 ORDER BY 1 NULLS FIRST", "refId": "A", "select": [ [ @@ -1786,7 +1786,7 @@ "hide": false, "metricColumn": "none", "rawQuery": true, - "rawSql": "WITH _prs AS (SELECT pr.id, pr.merged_date AS pr_merged_date, COALESCE(CAST(prm.pr_deploy_time AS NUMERIC) / NULLIF(60, 0), 0) AS deploy_time /* convert null to 0 if a PR has no deploy_time to make sure cycle_time equals the sum of the four sub-metrics */ FROM pull_requests AS pr LEFT JOIN project_pr_metrics AS prm ON pr.id = prm.id JOIN project_mapping AS pm ON pr.base_repo_id = pm.row_id AND pm.table = 'repos' WHERE $__timeFilter(pr.merged_date) AND pr.merged_date >= $__timeFrom()::timestamp + INTERVAL '1 DAY' * (-EXTRACT(DAY FROM CAST($__timeFrom() AS DATE)) + 1) + INTERVAL '1 MONTH' AND ('${project:csv}' = '' OR pm.project_name::text = ANY(ARRAY[${project:singlequote}]::text[])) GROUP BY 1, 2, 3) SELECT CAST(pr_merged_date AS DATE) + INTERVAL '1 DAY' * (-CASE WHEN '$interval' = 'DAYOFMONTH' THEN EXTRACT(DAY FROM CAST(pr_merged_date AS DATE)) ELSE (EXTRACT(ISODOW FROM CAST(pr_merged_date AS DATE)) - 1) END + 1) AS time, AVG(deploy_time) AS \"PR Deploy Time(h)\" FROM _prs GROUP BY 1 ORDER BY 1 NULLS FIRST", + "rawSql": "WITH _prs AS (SELECT pr.id, pr.merged_date AS pr_merged_date, COALESCE(CAST(prm.pr_deploy_time AS NUMERIC) / NULLIF(60, 0), 0) AS deploy_time /* convert null to 0 if a PR has no deploy_time to make sure cycle_time equals the sum of the four sub-metrics */ FROM pull_requests AS pr JOIN project_pr_metrics AS prm ON pr.id = prm.id JOIN project_mapping AS pm ON pr.base_repo_id = pm.row_id AND pm.table = 'repos' WHERE $__timeFilter(pr.merged_date) AND pr.merged_date >= $__timeFrom()::timestamp + INTERVAL '1 DAY' * (-EXTRACT(DAY FROM CAST($__timeFrom() AS DATE)) + 1) + INTERVAL '1 MONTH' AND ('${project:csv}' = '' OR pm.project_name::text = ANY(ARRAY[${project:singlequote}]::text[])) GROUP BY 1, 2, 3) SELECT CAST(pr_merged_date AS DATE) + INTERVAL '1 DAY' * (-CASE WHEN '$interval' = 'DAYOFMONTH' THEN EXTRACT(DAY FROM CAST(pr_merged_date AS DATE)) ELSE (EXTRACT(ISODOW FROM CAST(pr_merged_date AS DATE)) - 1) END + 1) AS time, AVG(deploy_time) AS \"PR Deploy Time(h)\" FROM _prs GROUP BY 1 ORDER BY 1 NULLS FIRST", "refId": "A", "select": [ [