You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@devlake.apache.org by kl...@apache.org on 2026/08/28 09:44:30 UTC
(devlake) branch main updated: feat(grafana): migrate Kiro engineering dashboards (#9078)
This is an automated email from the ASF dual-hosted git repository.
klesh pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/devlake.git
The following commit(s) were added to refs/heads/main by this push:
new f110addad feat(grafana): migrate Kiro engineering dashboards (#9078)
f110addad is described below
commit f110addad86930c4c792a3d22051e922346f3656
Author: Warren Chen <wa...@gmail.com>
AuthorDate: Fri Aug 28 17:44:24 2026 +0800
feat(grafana): migrate Kiro engineering dashboards (#9078)
* feat(kiro): add S3 collection and plugin APIs
Signed-off-by: warren <wa...@gmail.com>
* feat(config-ui): add Kiro connection support
Signed-off-by: warren <wa...@gmail.com>
* feat(grafana): add core Kiro dashboards
Signed-off-by: warren <wa...@gmail.com>
* feat(grafana): migrate Kiro engineering dashboards
Signed-off-by: warren <wa...@gmail.com>
* fix(kiro): use portable timestamp precision
Signed-off-by: warren <wa...@gmail.com>
* fix(kiro): keep q_dev in table info checks
Signed-off-by: warren <wa...@gmail.com>
---------
Signed-off-by: warren <wa...@gmail.com>
---
grafana/dashboards/mysql/ai-cost-efficiency.json | 423 ++++++++++++++---
.../mysql/developer-productivity-hours.json | 208 ++++++--
grafana/dashboards/mysql/kiro-credits-dora.json | 523 +++++++++++++++++----
grafana/dashboards/mysql/language-ai-heatmap.json | 227 +++++++--
grafana/dashboards/mysql/multi-ai-comparison.json | 343 +++++++++++---
.../mysql/steering-adoption-tracker.json | 286 ++++++++---
.../dashboards/postgresql/ai-cost-efficiency.json | 101 ++--
.../postgresql/developer-productivity-hours.json | 51 +-
.../dashboards/postgresql/kiro-credits-dora.json | 116 +++--
.../dashboards/postgresql/language-ai-heatmap.json | 55 ++-
.../dashboards/postgresql/multi-ai-comparison.json | 98 ++--
.../postgresql/steering-adoption-tracker.json | 77 ++-
12 files changed, 1993 insertions(+), 515 deletions(-)
diff --git a/grafana/dashboards/mysql/ai-cost-efficiency.json b/grafana/dashboards/mysql/ai-cost-efficiency.json
index d52905d0c..68cfe8027 100644
--- a/grafana/dashboards/mysql/ai-cost-efficiency.json
+++ b/grafana/dashboards/mysql/ai-cost-efficiency.json
@@ -26,42 +26,74 @@
"targetBlank": true,
"title": "Kiro Usage Dashboard",
"type": "link",
- "url": "/d/qdev_user_report"
+ "url": "/d/kiro_user_report"
}
],
"panels": [
{
"collapsed": false,
- "gridPos": { "h": 1, "w": 24, "x": 0, "y": 0 },
+ "gridPos": {
+ "h": 1,
+ "w": 24,
+ "x": 0,
+ "y": 0
+ },
"id": 1,
"panels": [],
"title": "Summary",
"type": "row"
},
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"fieldConfig": {
"defaults": {
- "color": { "mode": "thresholds" },
+ "color": {
+ "mode": "thresholds"
+ },
"mappings": [],
- "thresholds": { "mode": "absolute", "steps": [{ "color": "blue", "value": null }] }
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "blue",
+ "value": null
+ }
+ ]
+ }
},
"overrides": []
},
- "gridPos": { "h": 6, "w": 6, "x": 0, "y": 1 },
+ "gridPos": {
+ "h": 6,
+ "w": 6,
+ "x": 0,
+ "y": 1
+ },
"id": 2,
"options": {
"colorMode": "value",
"graphMode": "area",
- "reduceOptions": { "calcs": ["sum"], "fields": "", "values": false },
+ "reduceOptions": {
+ "calcs": [
+ "sum"
+ ],
+ "fields": "",
+ "values": false
+ },
"textMode": "auto"
},
"targets": [
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"format": "table",
"rawQuery": true,
- "rawSql": "SELECT ROUND(SUM(credits_used)) AS 'Total Credits'\nFROM _tool_q_dev_user_report WHERE $__timeFilter(date)",
+ "rawSql": "SELECT ROUND(SUM(credits_used)) AS 'Total Credits'\nFROM _tool_kiro_user_report WHERE $__timeFilter(date)",
"refId": "A"
}
],
@@ -69,29 +101,56 @@
"type": "stat"
},
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"fieldConfig": {
"defaults": {
- "color": { "mode": "thresholds" },
+ "color": {
+ "mode": "thresholds"
+ },
"mappings": [],
- "thresholds": { "mode": "absolute", "steps": [{ "color": "green", "value": null }] }
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ }
+ ]
+ }
},
"overrides": []
},
- "gridPos": { "h": 6, "w": 6, "x": 6, "y": 1 },
+ "gridPos": {
+ "h": 6,
+ "w": 6,
+ "x": 6,
+ "y": 1
+ },
"id": 3,
"options": {
"colorMode": "value",
"graphMode": "area",
- "reduceOptions": { "calcs": ["sum"], "fields": "", "values": false },
+ "reduceOptions": {
+ "calcs": [
+ "sum"
+ ],
+ "fields": "",
+ "values": false
+ },
"textMode": "auto"
},
"targets": [
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"format": "table",
"rawQuery": true,
- "rawSql": "SELECT ROUND(SUM(r.credits_used) / NULLIF(COUNT(DISTINCT pr.id), 0), 1) AS 'Credits / PR'\nFROM _tool_q_dev_user_report r\nCROSS JOIN (\n SELECT DISTINCT id FROM pull_requests\n WHERE merged_date IS NOT NULL AND $__timeFilter(merged_date)\n) pr\nWHERE $__timeFilter(r.date)",
+ "rawSql": "SELECT ROUND(SUM(r.credits_used) / NULLIF(COUNT(DISTINCT pr.id), 0), 1) AS 'Credits / PR'\nFROM _tool_kiro_user_report r\nCROSS JOIN (\n SELECT DISTINCT id FROM pull_requests\n WHERE merged_date IS NOT NULL AND $__timeFilter(merged_date)\n) pr\nWHERE $__timeFilter(r.date)",
"refId": "A"
}
],
@@ -99,29 +158,56 @@
"type": "stat"
},
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"fieldConfig": {
"defaults": {
- "color": { "mode": "thresholds" },
+ "color": {
+ "mode": "thresholds"
+ },
"mappings": [],
- "thresholds": { "mode": "absolute", "steps": [{ "color": "green", "value": null }] }
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ }
+ ]
+ }
},
"overrides": []
},
- "gridPos": { "h": 6, "w": 6, "x": 12, "y": 1 },
+ "gridPos": {
+ "h": 6,
+ "w": 6,
+ "x": 12,
+ "y": 1
+ },
"id": 4,
"options": {
"colorMode": "value",
"graphMode": "area",
- "reduceOptions": { "calcs": ["sum"], "fields": "", "values": false },
+ "reduceOptions": {
+ "calcs": [
+ "sum"
+ ],
+ "fields": "",
+ "values": false
+ },
"textMode": "auto"
},
"targets": [
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"format": "table",
"rawQuery": true,
- "rawSql": "SELECT ROUND(SUM(r.credits_used) / NULLIF(COUNT(DISTINCT cdc.cicd_deployment_id), 0), 1) AS 'Credits / Deploy'\nFROM _tool_q_dev_user_report r\nCROSS JOIN (\n SELECT DISTINCT cicd_deployment_id\n FROM cicd_deployment_commits\n WHERE result = 'SUCCESS' AND environment = 'PRODUCTION'\n AND $__timeFilter(finished_date)\n) cdc\nWHERE $__timeFilter(r.date)",
+ "rawSql": "SELECT ROUND(SUM(r.credits_used) / NULLIF(COUNT(DISTINCT cdc.cicd_deployment_id), 0), 1) AS 'Credits / Deploy'\nFROM _tool_kiro_user_report r\nCROSS JOIN (\n SELECT DISTINCT cicd_deployment_id\n FROM cicd_deployment_commits\n WHERE result = 'SUCCESS' AND environment = 'PRODUCTION'\n AND $__timeFilter(finished_date)\n) cdc\nWHERE $__timeFilter(r.date)",
"refId": "A"
}
],
@@ -129,29 +215,56 @@
"type": "stat"
},
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"fieldConfig": {
"defaults": {
- "color": { "mode": "thresholds" },
+ "color": {
+ "mode": "thresholds"
+ },
"mappings": [],
- "thresholds": { "mode": "absolute", "steps": [{ "color": "green", "value": null }] }
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ }
+ ]
+ }
},
"overrides": []
},
- "gridPos": { "h": 6, "w": 6, "x": 18, "y": 1 },
+ "gridPos": {
+ "h": 6,
+ "w": 6,
+ "x": 18,
+ "y": 1
+ },
"id": 5,
"options": {
"colorMode": "value",
"graphMode": "area",
- "reduceOptions": { "calcs": ["sum"], "fields": "", "values": false },
+ "reduceOptions": {
+ "calcs": [
+ "sum"
+ ],
+ "fields": "",
+ "values": false
+ },
"textMode": "auto"
},
"targets": [
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"format": "table",
"rawQuery": true,
- "rawSql": "SELECT ROUND(SUM(r.credits_used) / NULLIF(COUNT(DISTINCT i.id), 0), 1) AS 'Credits / Issue'\nFROM _tool_q_dev_user_report r\nCROSS JOIN (\n SELECT DISTINCT id FROM issues\n WHERE resolution_date IS NOT NULL AND type != 'INCIDENT'\n AND $__timeFilter(resolution_date)\n) i\nWHERE $__timeFilter(r.date)",
+ "rawSql": "SELECT ROUND(SUM(r.credits_used) / NULLIF(COUNT(DISTINCT i.id), 0), 1) AS 'Credits / Issue'\nFROM _tool_kiro_user_report r\nCROSS JOIN (\n SELECT DISTINCT id FROM issues\n WHERE resolution_date IS NOT NULL AND type != 'INCIDENT'\n AND $__timeFilter(resolution_date)\n) i\nWHERE $__timeFilter(r.date)",
"refId": "A"
}
],
@@ -160,40 +273,80 @@
},
{
"collapsed": false,
- "gridPos": { "h": 1, "w": 24, "x": 0, "y": 7 },
+ "gridPos": {
+ "h": 1,
+ "w": 24,
+ "x": 0,
+ "y": 7
+ },
"id": 10,
"panels": [],
"title": "Weekly Trends",
"type": "row"
},
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"description": "Weekly cost per merged PR",
"fieldConfig": {
"defaults": {
- "color": { "mode": "palette-classic" },
+ "color": {
+ "mode": "palette-classic"
+ },
"custom": {
- "axisBorderShow": false, "axisLabel": "", "axisPlacement": "auto",
- "drawStyle": "line", "fillOpacity": 10, "lineInterpolation": "smooth", "lineWidth": 2,
- "pointSize": 5, "showPoints": "never", "spanNulls": true,
- "stacking": { "mode": "none" }, "thresholdsStyle": { "mode": "off" }
+ "axisBorderShow": false,
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "lineInterpolation": "smooth",
+ "lineWidth": 2,
+ "pointSize": 5,
+ "showPoints": "never",
+ "spanNulls": true,
+ "stacking": {
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
},
"unit": "short"
},
"overrides": []
},
- "gridPos": { "h": 8, "w": 12, "x": 0, "y": 8 },
+ "gridPos": {
+ "h": 8,
+ "w": 12,
+ "x": 0,
+ "y": 8
+ },
"id": 11,
"options": {
- "legend": { "calcs": ["mean", "min"], "displayMode": "table", "placement": "right", "showLegend": true },
- "tooltip": { "mode": "multi" }
+ "legend": {
+ "calcs": [
+ "mean",
+ "min"
+ ],
+ "displayMode": "table",
+ "placement": "right",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi"
+ }
},
"targets": [
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"format": "time_series",
"rawQuery": true,
- "rawSql": "WITH _credits AS (\n SELECT DATE_SUB(DATE(date), INTERVAL WEEKDAY(DATE(date)) DAY) AS week_start,\n SUM(credits_used) AS credits\n FROM _tool_q_dev_user_report WHERE $__timeFilter(date)\n GROUP BY DATE_SUB(DATE(date), INTERVAL WEEKDAY(DATE(date)) DAY)\n),\n_prs AS (\n SELECT DATE_SUB(DATE(merged_date), INTERVAL WEEKDAY(DATE(merged_date)) DAY) AS week_start,\n COUNT(*) AS prs\n FROM pull_requests\n WHERE merged_date IS NOT NULL AND $__timeFilter(merged_dat [...]
+ "rawSql": "WITH _credits AS (\n SELECT DATE_SUB(DATE(date), INTERVAL WEEKDAY(DATE(date)) DAY) AS week_start,\n SUM(credits_used) AS credits\n FROM _tool_kiro_user_report WHERE $__timeFilter(date)\n GROUP BY DATE_SUB(DATE(date), INTERVAL WEEKDAY(DATE(date)) DAY)\n),\n_prs AS (\n SELECT DATE_SUB(DATE(merged_date), INTERVAL WEEKDAY(DATE(merged_date)) DAY) AS week_start,\n COUNT(*) AS prs\n FROM pull_requests\n WHERE merged_date IS NOT NULL AND $__timeFilter(merged_date [...]
"refId": "A"
}
],
@@ -201,33 +354,68 @@
"type": "timeseries"
},
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"description": "Weekly cost per production deployment",
"fieldConfig": {
"defaults": {
- "color": { "mode": "palette-classic" },
+ "color": {
+ "mode": "palette-classic"
+ },
"custom": {
- "axisBorderShow": false, "axisLabel": "", "axisPlacement": "auto",
- "drawStyle": "line", "fillOpacity": 10, "lineInterpolation": "smooth", "lineWidth": 2,
- "pointSize": 5, "showPoints": "never", "spanNulls": true,
- "stacking": { "mode": "none" }, "thresholdsStyle": { "mode": "off" }
+ "axisBorderShow": false,
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "lineInterpolation": "smooth",
+ "lineWidth": 2,
+ "pointSize": 5,
+ "showPoints": "never",
+ "spanNulls": true,
+ "stacking": {
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
},
"unit": "short"
},
"overrides": []
},
- "gridPos": { "h": 8, "w": 12, "x": 12, "y": 8 },
+ "gridPos": {
+ "h": 8,
+ "w": 12,
+ "x": 12,
+ "y": 8
+ },
"id": 12,
"options": {
- "legend": { "calcs": ["mean", "min"], "displayMode": "table", "placement": "right", "showLegend": true },
- "tooltip": { "mode": "multi" }
+ "legend": {
+ "calcs": [
+ "mean",
+ "min"
+ ],
+ "displayMode": "table",
+ "placement": "right",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi"
+ }
},
"targets": [
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"format": "time_series",
"rawQuery": true,
- "rawSql": "WITH _credits AS (\n SELECT DATE_SUB(DATE(date), INTERVAL WEEKDAY(DATE(date)) DAY) AS week_start,\n SUM(credits_used) AS credits\n FROM _tool_q_dev_user_report WHERE $__timeFilter(date)\n GROUP BY DATE_SUB(DATE(date), INTERVAL WEEKDAY(DATE(date)) DAY)\n),\n_deploys AS (\n SELECT DATE_SUB(DATE(finished_date), INTERVAL WEEKDAY(DATE(finished_date)) DAY) AS week_start,\n COUNT(DISTINCT cicd_deployment_id) AS deploys\n FROM cicd_deployment_commits\n WHERE resu [...]
+ "rawSql": "WITH _credits AS (\n SELECT DATE_SUB(DATE(date), INTERVAL WEEKDAY(DATE(date)) DAY) AS week_start,\n SUM(credits_used) AS credits\n FROM _tool_kiro_user_report WHERE $__timeFilter(date)\n GROUP BY DATE_SUB(DATE(date), INTERVAL WEEKDAY(DATE(date)) DAY)\n),\n_deploys AS (\n SELECT DATE_SUB(DATE(finished_date), INTERVAL WEEKDAY(DATE(finished_date)) DAY) AS week_start,\n COUNT(DISTINCT cicd_deployment_id) AS deploys\n FROM cicd_deployment_commits\n WHERE resul [...]
"refId": "A"
}
],
@@ -235,33 +423,68 @@
"type": "timeseries"
},
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"description": "Weekly cost per resolved issue",
"fieldConfig": {
"defaults": {
- "color": { "mode": "palette-classic" },
+ "color": {
+ "mode": "palette-classic"
+ },
"custom": {
- "axisBorderShow": false, "axisLabel": "", "axisPlacement": "auto",
- "drawStyle": "line", "fillOpacity": 10, "lineInterpolation": "smooth", "lineWidth": 2,
- "pointSize": 5, "showPoints": "never", "spanNulls": true,
- "stacking": { "mode": "none" }, "thresholdsStyle": { "mode": "off" }
+ "axisBorderShow": false,
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "lineInterpolation": "smooth",
+ "lineWidth": 2,
+ "pointSize": 5,
+ "showPoints": "never",
+ "spanNulls": true,
+ "stacking": {
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
},
"unit": "short"
},
"overrides": []
},
- "gridPos": { "h": 8, "w": 12, "x": 0, "y": 16 },
+ "gridPos": {
+ "h": 8,
+ "w": 12,
+ "x": 0,
+ "y": 16
+ },
"id": 13,
"options": {
- "legend": { "calcs": ["mean", "min"], "displayMode": "table", "placement": "right", "showLegend": true },
- "tooltip": { "mode": "multi" }
+ "legend": {
+ "calcs": [
+ "mean",
+ "min"
+ ],
+ "displayMode": "table",
+ "placement": "right",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi"
+ }
},
"targets": [
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"format": "time_series",
"rawQuery": true,
- "rawSql": "WITH _credits AS (\n SELECT DATE_SUB(DATE(date), INTERVAL WEEKDAY(DATE(date)) DAY) AS week_start,\n SUM(credits_used) AS credits\n FROM _tool_q_dev_user_report WHERE $__timeFilter(date)\n GROUP BY DATE_SUB(DATE(date), INTERVAL WEEKDAY(DATE(date)) DAY)\n),\n_issues AS (\n SELECT DATE_SUB(DATE(resolution_date), INTERVAL WEEKDAY(DATE(resolution_date)) DAY) AS week_start,\n COUNT(*) AS resolved\n FROM issues\n WHERE resolution_date IS NOT NULL AND type != 'IN [...]
+ "rawSql": "WITH _credits AS (\n SELECT DATE_SUB(DATE(date), INTERVAL WEEKDAY(DATE(date)) DAY) AS week_start,\n SUM(credits_used) AS credits\n FROM _tool_kiro_user_report WHERE $__timeFilter(date)\n GROUP BY DATE_SUB(DATE(date), INTERVAL WEEKDAY(DATE(date)) DAY)\n),\n_issues AS (\n SELECT DATE_SUB(DATE(resolution_date), INTERVAL WEEKDAY(DATE(resolution_date)) DAY) AS week_start,\n COUNT(*) AS resolved\n FROM issues\n WHERE resolution_date IS NOT NULL AND type != 'INC [...]
"refId": "A"
}
],
@@ -269,33 +492,68 @@
"type": "timeseries"
},
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"description": "Is cost efficiency improving over time?",
"fieldConfig": {
"defaults": {
- "color": { "mode": "palette-classic" },
+ "color": {
+ "mode": "palette-classic"
+ },
"custom": {
- "axisBorderShow": false, "axisLabel": "", "axisPlacement": "auto",
- "drawStyle": "line", "fillOpacity": 10, "lineInterpolation": "smooth", "lineWidth": 2,
- "pointSize": 5, "showPoints": "never", "spanNulls": true,
- "stacking": { "mode": "none" }, "thresholdsStyle": { "mode": "off" }
+ "axisBorderShow": false,
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "lineInterpolation": "smooth",
+ "lineWidth": 2,
+ "pointSize": 5,
+ "showPoints": "never",
+ "spanNulls": true,
+ "stacking": {
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
},
"unit": "short"
},
"overrides": []
},
- "gridPos": { "h": 8, "w": 12, "x": 12, "y": 16 },
+ "gridPos": {
+ "h": 8,
+ "w": 12,
+ "x": 12,
+ "y": 16
+ },
"id": 14,
"options": {
- "legend": { "calcs": ["mean", "sum"], "displayMode": "table", "placement": "right", "showLegend": true },
- "tooltip": { "mode": "multi" }
+ "legend": {
+ "calcs": [
+ "mean",
+ "sum"
+ ],
+ "displayMode": "table",
+ "placement": "right",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi"
+ }
},
"targets": [
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"format": "time_series",
"rawQuery": true,
- "rawSql": "SELECT\n DATE_SUB(DATE(date), INTERVAL WEEKDAY(DATE(date)) DAY) AS time,\n SUM(credits_used) AS 'Credits',\n SUM(total_messages) AS 'Messages',\n SUM(chat_conversations) AS 'Conversations'\nFROM _tool_q_dev_user_report\nWHERE $__timeFilter(date)\nGROUP BY DATE_SUB(DATE(date), INTERVAL WEEKDAY(DATE(date)) DAY)\nORDER BY time",
+ "rawSql": "SELECT\n DATE_SUB(DATE(date), INTERVAL WEEKDAY(DATE(date)) DAY) AS time,\n SUM(credits_used) AS 'Credits',\n SUM(total_messages) AS 'Messages',\n SUM(chat_conversations) AS 'Conversations'\nFROM _tool_kiro_user_report\nWHERE $__timeFilter(date)\nGROUP BY DATE_SUB(DATE(date), INTERVAL WEEKDAY(DATE(date)) DAY)\nORDER BY time",
"refId": "A"
}
],
@@ -306,9 +564,18 @@
"preload": false,
"refresh": "5m",
"schemaVersion": 41,
- "tags": ["q_dev", "kiro", "cost", "efficiency"],
- "templating": { "list": [] },
- "time": { "from": "now-90d", "to": "now" },
+ "tags": [
+ "kiro",
+ "cost",
+ "efficiency"
+ ],
+ "templating": {
+ "list": []
+ },
+ "time": {
+ "from": "now-90d",
+ "to": "now"
+ },
"timepicker": {},
"timezone": "utc",
"title": "AI Cost-Efficiency",
diff --git a/grafana/dashboards/mysql/developer-productivity-hours.json b/grafana/dashboards/mysql/developer-productivity-hours.json
index 2259f6d5b..c5b4504aa 100644
--- a/grafana/dashboards/mysql/developer-productivity-hours.json
+++ b/grafana/dashboards/mysql/developer-productivity-hours.json
@@ -19,31 +19,60 @@
"links": [],
"panels": [
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"description": "Chat and completion events by hour of day",
"fieldConfig": {
"defaults": {
- "color": { "mode": "palette-classic" },
+ "color": {
+ "mode": "palette-classic"
+ },
"custom": {
- "drawStyle": "bars", "fillOpacity": 80, "lineWidth": 1,
- "stacking": { "mode": "normal" }, "thresholdsStyle": { "mode": "off" }
+ "drawStyle": "bars",
+ "fillOpacity": 80,
+ "lineWidth": 1,
+ "stacking": {
+ "mode": "normal"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
},
"unit": "short"
},
"overrides": []
},
- "gridPos": { "h": 8, "w": 24, "x": 0, "y": 0 },
+ "gridPos": {
+ "h": 8,
+ "w": 24,
+ "x": 0,
+ "y": 0
+ },
"id": 1,
"options": {
- "legend": { "calcs": ["sum"], "displayMode": "table", "placement": "right", "showLegend": true },
- "tooltip": { "mode": "multi" }
+ "legend": {
+ "calcs": [
+ "sum"
+ ],
+ "displayMode": "table",
+ "placement": "right",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi"
+ }
},
"targets": [
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"format": "table",
"rawQuery": true,
- "rawSql": "SELECT LPAD(CAST(hr AS CHAR), 2, '0') AS 'Hour',\n SUM(chat) AS 'Chat Events', SUM(comp) AS 'Completion Events'\nFROM (\n SELECT HOUR(timestamp) AS hr, COUNT(*) AS chat, 0 AS comp\n FROM _tool_q_dev_chat_log WHERE $__timeFilter(timestamp)\n GROUP BY HOUR(timestamp)\n UNION ALL\n SELECT HOUR(timestamp) AS hr, 0 AS chat, COUNT(*) AS comp\n FROM _tool_q_dev_completion_log WHERE $__timeFilter(timestamp)\n GROUP BY HOUR(timestamp)\n) t GROUP BY hr ORDER BY hr",
+ "rawSql": "SELECT LPAD(CAST(hr AS CHAR), 2, '0') AS 'Hour',\n SUM(chat) AS 'Chat Events', SUM(comp) AS 'Completion Events'\nFROM (\n SELECT HOUR(timestamp) AS hr, COUNT(*) AS chat, 0 AS comp\n FROM _tool_kiro_chat_log WHERE $__timeFilter(timestamp)\n GROUP BY HOUR(timestamp)\n UNION ALL\n SELECT HOUR(timestamp) AS hr, 0 AS chat, COUNT(*) AS comp\n FROM _tool_kiro_completion_log WHERE $__timeFilter(timestamp)\n GROUP BY HOUR(timestamp)\n) t GROUP BY hr ORDER BY hr",
"refId": "A"
}
],
@@ -51,32 +80,64 @@
"type": "barchart"
},
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"description": "Average prompt complexity and response richness by hour",
"fieldConfig": {
"defaults": {
- "color": { "mode": "palette-classic" },
+ "color": {
+ "mode": "palette-classic"
+ },
"custom": {
- "drawStyle": "line", "fillOpacity": 10, "lineInterpolation": "smooth", "lineWidth": 2,
- "showPoints": "auto", "spanNulls": true,
- "stacking": { "mode": "none" }, "thresholdsStyle": { "mode": "off" }
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "lineInterpolation": "smooth",
+ "lineWidth": 2,
+ "showPoints": "auto",
+ "spanNulls": true,
+ "stacking": {
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
},
"unit": "short"
},
"overrides": []
},
- "gridPos": { "h": 8, "w": 12, "x": 0, "y": 8 },
+ "gridPos": {
+ "h": 8,
+ "w": 12,
+ "x": 0,
+ "y": 8
+ },
"id": 2,
"options": {
- "legend": { "calcs": ["mean", "max"], "displayMode": "table", "placement": "right", "showLegend": true },
- "tooltip": { "mode": "multi" }
+ "legend": {
+ "calcs": [
+ "mean",
+ "max"
+ ],
+ "displayMode": "table",
+ "placement": "right",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi"
+ }
},
"targets": [
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"format": "table",
"rawQuery": true,
- "rawSql": "SELECT LPAD(CAST(HOUR(timestamp) AS CHAR), 2, '0') AS 'Hour',\n ROUND(AVG(prompt_length)) AS 'Avg Prompt Length',\n ROUND(AVG(response_length)) AS 'Avg Response Length'\nFROM _tool_q_dev_chat_log\nWHERE $__timeFilter(timestamp)\nGROUP BY HOUR(timestamp)\nORDER BY HOUR(timestamp)",
+ "rawSql": "SELECT LPAD(CAST(hr AS CHAR), 2, '0') AS 'Hour', ROUND(avg_prompt) AS 'Avg Prompt Length', ROUND(avg_response) AS 'Avg Response Length' FROM (SELECT HOUR(timestamp) AS hr, AVG(prompt_length) AS avg_prompt, AVG(response_length) AS avg_response FROM _tool_kiro_chat_log WHERE $__timeFilter(timestamp) GROUP BY HOUR(timestamp)) hourly ORDER BY hr",
"refId": "A"
}
],
@@ -84,31 +145,60 @@
"type": "barchart"
},
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"description": "Steering and spec mode usage concentration by hour",
"fieldConfig": {
"defaults": {
- "color": { "mode": "palette-classic" },
+ "color": {
+ "mode": "palette-classic"
+ },
"custom": {
- "drawStyle": "bars", "fillOpacity": 80, "lineWidth": 1,
- "stacking": { "mode": "normal" }, "thresholdsStyle": { "mode": "off" }
+ "drawStyle": "bars",
+ "fillOpacity": 80,
+ "lineWidth": 1,
+ "stacking": {
+ "mode": "normal"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
},
"unit": "short"
},
"overrides": []
},
- "gridPos": { "h": 8, "w": 12, "x": 12, "y": 8 },
+ "gridPos": {
+ "h": 8,
+ "w": 12,
+ "x": 12,
+ "y": 8
+ },
"id": 3,
"options": {
- "legend": { "calcs": ["sum"], "displayMode": "table", "placement": "right", "showLegend": true },
- "tooltip": { "mode": "multi" }
+ "legend": {
+ "calcs": [
+ "sum"
+ ],
+ "displayMode": "table",
+ "placement": "right",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi"
+ }
},
"targets": [
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"format": "table",
"rawQuery": true,
- "rawSql": "SELECT LPAD(CAST(HOUR(timestamp) AS CHAR), 2, '0') AS 'Hour',\n SUM(CASE WHEN has_steering = 1 THEN 1 ELSE 0 END) AS 'Steering',\n SUM(CASE WHEN is_spec_mode = 1 THEN 1 ELSE 0 END) AS 'Spec Mode',\n SUM(CASE WHEN has_steering = 0 AND is_spec_mode = 0 THEN 1 ELSE 0 END) AS 'Plain Chat'\nFROM _tool_q_dev_chat_log\nWHERE $__timeFilter(timestamp)\nGROUP BY HOUR(timestamp)\nORDER BY HOUR(timestamp)",
+ "rawSql": "SELECT LPAD(CAST(hr AS CHAR), 2, '0') AS 'Hour', steering AS 'Steering', spec_mode AS 'Spec Mode', plain_chat AS 'Plain Chat' FROM (SELECT HOUR(timestamp) AS hr, SUM(CASE WHEN has_steering = 1 THEN 1 ELSE 0 END) AS steering, SUM(CASE WHEN is_spec_mode = 1 THEN 1 ELSE 0 END) AS spec_mode, SUM(CASE WHEN has_steering = 0 AND is_spec_mode = 0 THEN 1 ELSE 0 END) AS plain_chat FROM _tool_kiro_chat_log WHERE $__timeFilter(timestamp) GROUP BY HOUR(timestamp)) hourly ORDER BY hr",
"refId": "A"
}
],
@@ -116,31 +206,60 @@
"type": "barchart"
},
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"description": "Day-of-week activity pattern",
"fieldConfig": {
"defaults": {
- "color": { "mode": "palette-classic" },
+ "color": {
+ "mode": "palette-classic"
+ },
"custom": {
- "drawStyle": "bars", "fillOpacity": 80, "lineWidth": 1,
- "stacking": { "mode": "normal" }, "thresholdsStyle": { "mode": "off" }
+ "drawStyle": "bars",
+ "fillOpacity": 80,
+ "lineWidth": 1,
+ "stacking": {
+ "mode": "normal"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
},
"unit": "short"
},
"overrides": []
},
- "gridPos": { "h": 8, "w": 24, "x": 0, "y": 16 },
+ "gridPos": {
+ "h": 8,
+ "w": 24,
+ "x": 0,
+ "y": 16
+ },
"id": 4,
"options": {
- "legend": { "calcs": ["sum"], "displayMode": "table", "placement": "right", "showLegend": true },
- "tooltip": { "mode": "multi" }
+ "legend": {
+ "calcs": [
+ "sum"
+ ],
+ "displayMode": "table",
+ "placement": "right",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi"
+ }
},
"targets": [
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"format": "table",
"rawQuery": true,
- "rawSql": "SELECT\n CASE DAYOFWEEK(timestamp)\n WHEN 1 THEN 'Sun' WHEN 2 THEN 'Mon' WHEN 3 THEN 'Tue'\n WHEN 4 THEN 'Wed' WHEN 5 THEN 'Thu' WHEN 6 THEN 'Fri' WHEN 7 THEN 'Sat'\n END AS 'Day',\n SUM(chat) AS 'Chat Events', SUM(comp) AS 'Completions'\nFROM (\n SELECT timestamp, COUNT(*) AS chat, 0 AS comp FROM _tool_q_dev_chat_log WHERE $__timeFilter(timestamp) GROUP BY timestamp\n UNION ALL\n SELECT timestamp, 0, COUNT(*) FROM _tool_q_dev_completion_log WHERE $__time [...]
+ "rawSql": "SELECT CASE weekday_num WHEN 1 THEN 'Sun' WHEN 2 THEN 'Mon' WHEN 3 THEN 'Tue' WHEN 4 THEN 'Wed' WHEN 5 THEN 'Thu' WHEN 6 THEN 'Fri' WHEN 7 THEN 'Sat' END AS 'Day', SUM(chat) AS 'Chat Events', SUM(comp) AS 'Completions' FROM (SELECT DAYOFWEEK(timestamp) AS weekday_num, COUNT(*) AS chat, 0 AS comp FROM _tool_kiro_chat_log WHERE $__timeFilter(timestamp) GROUP BY DAYOFWEEK(timestamp) UNION ALL SELECT DAYOFWEEK(timestamp) AS weekday_num, 0 AS chat, COUNT(*) AS comp FROM _ [...]
"refId": "A"
}
],
@@ -151,9 +270,18 @@
"preload": false,
"refresh": "5m",
"schemaVersion": 41,
- "tags": ["q_dev", "kiro", "productivity", "hours"],
- "templating": { "list": [] },
- "time": { "from": "now-90d", "to": "now" },
+ "tags": [
+ "kiro",
+ "productivity",
+ "hours"
+ ],
+ "templating": {
+ "list": []
+ },
+ "time": {
+ "from": "now-90d",
+ "to": "now"
+ },
"timepicker": {},
"timezone": "utc",
"title": "Developer AI Productivity Hours",
diff --git a/grafana/dashboards/mysql/kiro-credits-dora.json b/grafana/dashboards/mysql/kiro-credits-dora.json
index 46614cc08..e587f1002 100644
--- a/grafana/dashboards/mysql/kiro-credits-dora.json
+++ b/grafana/dashboards/mysql/kiro-credits-dora.json
@@ -37,7 +37,7 @@
"targetBlank": true,
"title": "Kiro Usage Dashboard",
"type": "link",
- "url": "/d/qdev_user_report"
+ "url": "/d/kiro_user_report"
}
],
"panels": [
@@ -46,10 +46,19 @@
"type": "datasource",
"uid": "grafana"
},
- "gridPos": { "h": 3, "w": 24, "x": 0, "y": 0 },
+ "gridPos": {
+ "h": 3,
+ "w": 24,
+ "x": 0,
+ "y": 0
+ },
"id": 1,
"options": {
- "code": { "language": "plaintext", "showLineNumbers": false, "showMiniMap": false },
+ "code": {
+ "language": "plaintext",
+ "showLineNumbers": false,
+ "showMiniMap": false
+ },
"content": "## Kiro Credits + DORA Correlation\nThis dashboard correlates **Kiro AI usage (credits and messages)** with **DORA** performance indicators at a weekly aggregate level.\n\n- **Pearson's r** measures linear correlation: negative r suggests higher AI usage may correlate with shorter cycle times.\n- Data is aggregated by **week** and joined on `week_start`.",
"mode": "markdown"
},
@@ -58,48 +67,91 @@
},
{
"collapsed": false,
- "gridPos": { "h": 1, "w": 24, "x": 0, "y": 3 },
+ "gridPos": {
+ "h": 1,
+ "w": 24,
+ "x": 0,
+ "y": 3
+ },
"id": 2,
"panels": [],
"title": "Overview",
"type": "row"
},
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"description": "Pearson correlation coefficient between weekly Kiro credits and PR cycle time",
"fieldConfig": {
"defaults": {
- "color": { "mode": "thresholds" },
- "mappings": [{ "options": { "match": "null", "result": { "text": "Need more data" } }, "type": "special" }],
+ "color": {
+ "mode": "thresholds"
+ },
+ "mappings": [
+ {
+ "options": {
+ "match": "null",
+ "result": {
+ "text": "Need more data"
+ }
+ },
+ "type": "special"
+ }
+ ],
"thresholds": {
"mode": "absolute",
"steps": [
- { "color": "green", "value": null },
- { "color": "yellow", "value": -0.3 },
- { "color": "orange", "value": 0.3 }
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "yellow",
+ "value": -0.3
+ },
+ {
+ "color": "orange",
+ "value": 0.3
+ }
]
}
},
"overrides": []
},
- "gridPos": { "h": 6, "w": 8, "x": 0, "y": 4 },
+ "gridPos": {
+ "h": 6,
+ "w": 8,
+ "x": 0,
+ "y": 4
+ },
"id": 3,
"options": {
"colorMode": "value",
"graphMode": "none",
"justifyMode": "auto",
"orientation": "auto",
- "reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
+ "reduceOptions": {
+ "calcs": [
+ "lastNotNull"
+ ],
+ "fields": "",
+ "values": false
+ },
"showPercentChange": false,
"textMode": "auto"
},
"targets": [
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"editorMode": "code",
"format": "table",
"rawQuery": true,
- "rawSql": "WITH _kiro_weekly AS (\n SELECT\n DATE_SUB(DATE(date), INTERVAL WEEKDAY(DATE(date)) DAY) AS week_start,\n SUM(credits_used) AS weekly_credits\n FROM _tool_q_dev_user_report\n WHERE $__timeFilter(date)\n GROUP BY DATE_SUB(DATE(date), INTERVAL WEEKDAY(DATE(date)) DAY)\n),\n_pr_weekly AS (\n SELECT\n DATE_SUB(DATE(pr_merged_date), INTERVAL WEEKDAY(DATE(pr_merged_date)) DAY) AS week_start,\n AVG(pr_cycle_time) / 60.0 AS avg_cycle_hours\n FROM project_pr [...]
+ "rawSql": "WITH _kiro_weekly AS (\n SELECT\n DATE_SUB(DATE(date), INTERVAL WEEKDAY(DATE(date)) DAY) AS week_start,\n SUM(credits_used) AS weekly_credits\n FROM _tool_kiro_user_report\n WHERE $__timeFilter(date)\n GROUP BY DATE_SUB(DATE(date), INTERVAL WEEKDAY(DATE(date)) DAY)\n),\n_pr_weekly AS (\n SELECT\n DATE_SUB(DATE(pr_merged_date), INTERVAL WEEKDAY(DATE(pr_merged_date)) DAY) AS week_start,\n AVG(pr_cycle_time) / 60.0 AS avg_cycle_hours\n FROM project_pr_ [...]
"refId": "A"
}
],
@@ -107,30 +159,57 @@
"type": "stat"
},
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"description": "Total Kiro credits consumed in period",
"fieldConfig": {
"defaults": {
- "color": { "mode": "thresholds" },
+ "color": {
+ "mode": "thresholds"
+ },
"mappings": [],
- "thresholds": { "mode": "absolute", "steps": [{ "color": "blue", "value": null }] }
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "blue",
+ "value": null
+ }
+ ]
+ }
},
"overrides": []
},
- "gridPos": { "h": 6, "w": 4, "x": 8, "y": 4 },
+ "gridPos": {
+ "h": 6,
+ "w": 4,
+ "x": 8,
+ "y": 4
+ },
"id": 4,
"options": {
"colorMode": "value",
"graphMode": "area",
- "reduceOptions": { "calcs": ["sum"], "fields": "", "values": false },
+ "reduceOptions": {
+ "calcs": [
+ "sum"
+ ],
+ "fields": "",
+ "values": false
+ },
"textMode": "auto"
},
"targets": [
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"format": "table",
"rawQuery": true,
- "rawSql": "SELECT SUM(credits_used) AS 'Credits Used'\nFROM _tool_q_dev_user_report\nWHERE $__timeFilter(date)",
+ "rawSql": "SELECT SUM(credits_used) AS 'Credits Used'\nFROM _tool_kiro_user_report\nWHERE $__timeFilter(date)",
"refId": "A"
}
],
@@ -138,28 +217,55 @@
"type": "stat"
},
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"description": "Median PR cycle time in hours",
"fieldConfig": {
"defaults": {
- "color": { "mode": "thresholds" },
+ "color": {
+ "mode": "thresholds"
+ },
"mappings": [],
- "thresholds": { "mode": "absolute", "steps": [{ "color": "green", "value": null }] },
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ }
+ ]
+ },
"unit": "h"
},
"overrides": []
},
- "gridPos": { "h": 6, "w": 4, "x": 12, "y": 4 },
+ "gridPos": {
+ "h": 6,
+ "w": 4,
+ "x": 12,
+ "y": 4
+ },
"id": 5,
"options": {
"colorMode": "value",
"graphMode": "area",
- "reduceOptions": { "calcs": ["sum"], "fields": "", "values": false },
+ "reduceOptions": {
+ "calcs": [
+ "sum"
+ ],
+ "fields": "",
+ "values": false
+ },
"textMode": "auto"
},
"targets": [
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"format": "table",
"rawQuery": true,
"rawSql": "WITH _ranked AS (\n SELECT pr_cycle_time / 60.0 AS ct,\n PERCENT_RANK() OVER (ORDER BY pr_cycle_time) AS prank\n FROM project_pr_metrics\n WHERE pr_merged_date IS NOT NULL AND pr_cycle_time IS NOT NULL\n AND $__timeFilter(pr_merged_date)\n)\nSELECT ROUND(MAX(ct), 1) AS 'Median Cycle Time'\nFROM _ranked WHERE prank <= 0.5",
@@ -170,18 +276,36 @@
"type": "stat"
},
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"description": "Cycle time comparison: weeks with above-median vs below-median AI credits usage",
"fieldConfig": {
"defaults": {
- "color": { "mode": "palette-classic" },
+ "color": {
+ "mode": "palette-classic"
+ },
"mappings": [],
- "thresholds": { "mode": "absolute", "steps": [{ "color": "green", "value": null }] },
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ }
+ ]
+ },
"unit": "h"
},
"overrides": []
},
- "gridPos": { "h": 6, "w": 8, "x": 16, "y": 4 },
+ "gridPos": {
+ "h": 6,
+ "w": 8,
+ "x": 16,
+ "y": 4
+ },
"id": 6,
"options": {
"barRadius": 0.1,
@@ -189,14 +313,19 @@
"orientation": "horizontal",
"showValue": "auto",
"stacking": "none",
- "tooltip": { "mode": "single" }
+ "tooltip": {
+ "mode": "single"
+ }
},
"targets": [
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"format": "table",
"rawQuery": true,
- "rawSql": "WITH _kiro_weekly AS (\n SELECT DATE_SUB(DATE(date), INTERVAL WEEKDAY(DATE(date)) DAY) AS week_start,\n SUM(credits_used) AS weekly_credits\n FROM _tool_q_dev_user_report WHERE $__timeFilter(date)\n GROUP BY DATE_SUB(DATE(date), INTERVAL WEEKDAY(DATE(date)) DAY)\n),\n_pr_weekly AS (\n SELECT DATE_SUB(DATE(pr_merged_date), INTERVAL WEEKDAY(DATE(pr_merged_date)) DAY) AS week_start,\n AVG(pr_cycle_time) / 60.0 AS avg_ct\n FROM project_pr_metrics\n WHERE pr_m [...]
+ "rawSql": "WITH _kiro_weekly AS (SELECT DATE_SUB(DATE(date), INTERVAL WEEKDAY(DATE(date)) DAY) AS week_start, SUM(credits_used) AS weekly_credits FROM _tool_kiro_user_report WHERE $__timeFilter(date) GROUP BY DATE_SUB(DATE(date), INTERVAL WEEKDAY(DATE(date)) DAY)), _pr_weekly AS (SELECT DATE_SUB(DATE(pr_merged_date), INTERVAL WEEKDAY(DATE(pr_merged_date)) DAY) AS week_start, AVG(pr_cycle_time) / 60.0 AS avg_ct FROM project_pr_metrics WHERE pr_merged_date IS NOT NULL AND pr_cycl [...]
"refId": "A"
}
],
@@ -205,40 +334,80 @@
},
{
"collapsed": false,
- "gridPos": { "h": 1, "w": 24, "x": 0, "y": 10 },
+ "gridPos": {
+ "h": 1,
+ "w": 24,
+ "x": 0,
+ "y": 10
+ },
"id": 10,
"panels": [],
"title": "Weekly Trends",
"type": "row"
},
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"description": "Weekly Kiro credits consumed",
"fieldConfig": {
"defaults": {
- "color": { "mode": "palette-classic" },
+ "color": {
+ "mode": "palette-classic"
+ },
"custom": {
- "axisBorderShow": false, "axisLabel": "", "axisPlacement": "auto",
- "drawStyle": "line", "fillOpacity": 10, "lineInterpolation": "smooth", "lineWidth": 2,
- "pointSize": 5, "showPoints": "never", "spanNulls": true,
- "stacking": { "mode": "none" }, "thresholdsStyle": { "mode": "off" }
+ "axisBorderShow": false,
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "lineInterpolation": "smooth",
+ "lineWidth": 2,
+ "pointSize": 5,
+ "showPoints": "never",
+ "spanNulls": true,
+ "stacking": {
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
},
"unit": "short"
},
"overrides": []
},
- "gridPos": { "h": 8, "w": 12, "x": 0, "y": 11 },
+ "gridPos": {
+ "h": 8,
+ "w": 12,
+ "x": 0,
+ "y": 11
+ },
"id": 11,
"options": {
- "legend": { "calcs": ["mean", "sum"], "displayMode": "table", "placement": "right", "showLegend": true },
- "tooltip": { "mode": "multi" }
+ "legend": {
+ "calcs": [
+ "mean",
+ "sum"
+ ],
+ "displayMode": "table",
+ "placement": "right",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi"
+ }
},
"targets": [
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"format": "time_series",
"rawQuery": true,
- "rawSql": "SELECT\n DATE_SUB(DATE(date), INTERVAL WEEKDAY(DATE(date)) DAY) AS time,\n SUM(credits_used) AS 'Credits Used',\n COUNT(DISTINCT user_id) AS 'Active Users'\nFROM _tool_q_dev_user_report\nWHERE $__timeFilter(date)\nGROUP BY DATE_SUB(DATE(date), INTERVAL WEEKDAY(DATE(date)) DAY)\nORDER BY time",
+ "rawSql": "SELECT\n DATE_SUB(DATE(date), INTERVAL WEEKDAY(DATE(date)) DAY) AS time,\n SUM(credits_used) AS 'Credits Used',\n COUNT(DISTINCT user_id) AS 'Active Users'\nFROM _tool_kiro_user_report\nWHERE $__timeFilter(date)\nGROUP BY DATE_SUB(DATE(date), INTERVAL WEEKDAY(DATE(date)) DAY)\nORDER BY time",
"refId": "A"
}
],
@@ -246,30 +415,65 @@
"type": "timeseries"
},
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"description": "Weekly average PR cycle time in hours",
"fieldConfig": {
"defaults": {
- "color": { "mode": "palette-classic" },
+ "color": {
+ "mode": "palette-classic"
+ },
"custom": {
- "axisBorderShow": false, "axisLabel": "", "axisPlacement": "auto",
- "drawStyle": "line", "fillOpacity": 10, "lineInterpolation": "smooth", "lineWidth": 2,
- "pointSize": 5, "showPoints": "never", "spanNulls": true,
- "stacking": { "mode": "none" }, "thresholdsStyle": { "mode": "off" }
+ "axisBorderShow": false,
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "lineInterpolation": "smooth",
+ "lineWidth": 2,
+ "pointSize": 5,
+ "showPoints": "never",
+ "spanNulls": true,
+ "stacking": {
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
},
"unit": "h"
},
"overrides": []
},
- "gridPos": { "h": 8, "w": 12, "x": 12, "y": 11 },
+ "gridPos": {
+ "h": 8,
+ "w": 12,
+ "x": 12,
+ "y": 11
+ },
"id": 12,
"options": {
- "legend": { "calcs": ["mean", "max"], "displayMode": "table", "placement": "right", "showLegend": true },
- "tooltip": { "mode": "multi" }
+ "legend": {
+ "calcs": [
+ "mean",
+ "max"
+ ],
+ "displayMode": "table",
+ "placement": "right",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi"
+ }
},
"targets": [
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"format": "time_series",
"rawQuery": true,
"rawSql": "SELECT\n DATE_SUB(DATE(pr_merged_date), INTERVAL WEEKDAY(DATE(pr_merged_date)) DAY) AS time,\n ROUND(AVG(pr_cycle_time) / 60.0, 1) AS 'Avg Cycle Time (hrs)',\n COUNT(*) AS 'PRs Merged'\nFROM project_pr_metrics\nWHERE pr_merged_date IS NOT NULL AND pr_cycle_time IS NOT NULL\n AND $__timeFilter(pr_merged_date)\nGROUP BY DATE_SUB(DATE(pr_merged_date), INTERVAL WEEKDAY(DATE(pr_merged_date)) DAY)\nORDER BY time",
@@ -281,37 +485,79 @@
},
{
"collapsed": false,
- "gridPos": { "h": 1, "w": 24, "x": 0, "y": 19 },
+ "gridPos": {
+ "h": 1,
+ "w": 24,
+ "x": 0,
+ "y": 19
+ },
"id": 20,
"panels": [],
"title": "Deployment Frequency",
"type": "row"
},
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"description": "Pearson correlation between weekly credits and deployment count",
"fieldConfig": {
"defaults": {
- "color": { "mode": "thresholds" },
- "mappings": [{ "options": { "match": "null", "result": { "text": "Need more data" } }, "type": "special" }],
- "thresholds": { "mode": "absolute", "steps": [{ "color": "green", "value": null }] }
+ "color": {
+ "mode": "thresholds"
+ },
+ "mappings": [
+ {
+ "options": {
+ "match": "null",
+ "result": {
+ "text": "Need more data"
+ }
+ },
+ "type": "special"
+ }
+ ],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ }
+ ]
+ }
},
"overrides": []
},
- "gridPos": { "h": 6, "w": 6, "x": 0, "y": 20 },
+ "gridPos": {
+ "h": 6,
+ "w": 6,
+ "x": 0,
+ "y": 20
+ },
"id": 21,
"options": {
"colorMode": "value",
"graphMode": "none",
- "reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
+ "reduceOptions": {
+ "calcs": [
+ "lastNotNull"
+ ],
+ "fields": "",
+ "values": false
+ },
"textMode": "auto"
},
"targets": [
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"format": "table",
"rawQuery": true,
- "rawSql": "WITH _kiro_weekly AS (\n SELECT DATE_SUB(DATE(date), INTERVAL WEEKDAY(DATE(date)) DAY) AS week_start,\n SUM(credits_used) AS weekly_credits\n FROM _tool_q_dev_user_report WHERE $__timeFilter(date)\n GROUP BY DATE_SUB(DATE(date), INTERVAL WEEKDAY(DATE(date)) DAY)\n),\n_deploy_weekly AS (\n SELECT DATE_SUB(DATE(cdc.finished_date), INTERVAL WEEKDAY(DATE(cdc.finished_date)) DAY) AS week_start,\n COUNT(DISTINCT cdc.cicd_deployment_id) AS deploys\n FROM cicd_dep [...]
+ "rawSql": "WITH _kiro_weekly AS (\n SELECT DATE_SUB(DATE(date), INTERVAL WEEKDAY(DATE(date)) DAY) AS week_start,\n SUM(credits_used) AS weekly_credits\n FROM _tool_kiro_user_report WHERE $__timeFilter(date)\n GROUP BY DATE_SUB(DATE(date), INTERVAL WEEKDAY(DATE(date)) DAY)\n),\n_deploy_weekly AS (\n SELECT DATE_SUB(DATE(cdc.finished_date), INTERVAL WEEKDAY(DATE(cdc.finished_date)) DAY) AS week_start,\n COUNT(DISTINCT cdc.cicd_deployment_id) AS deploys\n FROM cicd_depl [...]
"refId": "A"
}
],
@@ -319,33 +565,68 @@
"type": "stat"
},
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"description": "Weekly credits overlaid with deployment count",
"fieldConfig": {
"defaults": {
- "color": { "mode": "palette-classic" },
+ "color": {
+ "mode": "palette-classic"
+ },
"custom": {
- "axisBorderShow": false, "axisLabel": "", "axisPlacement": "auto",
- "drawStyle": "line", "fillOpacity": 10, "lineInterpolation": "smooth", "lineWidth": 2,
- "pointSize": 5, "showPoints": "never", "spanNulls": true,
- "stacking": { "mode": "none" }, "thresholdsStyle": { "mode": "off" }
+ "axisBorderShow": false,
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "lineInterpolation": "smooth",
+ "lineWidth": 2,
+ "pointSize": 5,
+ "showPoints": "never",
+ "spanNulls": true,
+ "stacking": {
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
},
"unit": "short"
},
"overrides": []
},
- "gridPos": { "h": 8, "w": 18, "x": 6, "y": 20 },
+ "gridPos": {
+ "h": 8,
+ "w": 18,
+ "x": 6,
+ "y": 20
+ },
"id": 22,
"options": {
- "legend": { "calcs": ["mean", "sum"], "displayMode": "table", "placement": "right", "showLegend": true },
- "tooltip": { "mode": "multi" }
+ "legend": {
+ "calcs": [
+ "mean",
+ "sum"
+ ],
+ "displayMode": "table",
+ "placement": "right",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi"
+ }
},
"targets": [
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"format": "time_series",
"rawQuery": true,
- "rawSql": "SELECT time, SUM(credits) AS 'Credits Used', SUM(deploys) AS 'Deployments'\nFROM (\n SELECT DATE_SUB(DATE(date), INTERVAL WEEKDAY(DATE(date)) DAY) AS time,\n SUM(credits_used) AS credits, 0 AS deploys\n FROM _tool_q_dev_user_report WHERE $__timeFilter(date)\n GROUP BY DATE_SUB(DATE(date), INTERVAL WEEKDAY(DATE(date)) DAY)\n UNION ALL\n SELECT DATE_SUB(DATE(cdc.finished_date), INTERVAL WEEKDAY(DATE(cdc.finished_date)) DAY) AS time,\n 0 AS credits, COUNT(DIS [...]
+ "rawSql": "SELECT time, SUM(credits) AS 'Credits Used', SUM(deploys) AS 'Deployments'\nFROM (\n SELECT DATE_SUB(DATE(date), INTERVAL WEEKDAY(DATE(date)) DAY) AS time,\n SUM(credits_used) AS credits, 0 AS deploys\n FROM _tool_kiro_user_report WHERE $__timeFilter(date)\n GROUP BY DATE_SUB(DATE(date), INTERVAL WEEKDAY(DATE(date)) DAY)\n UNION ALL\n SELECT DATE_SUB(DATE(cdc.finished_date), INTERVAL WEEKDAY(DATE(cdc.finished_date)) DAY) AS time,\n 0 AS credits, COUNT(DIST [...]
"refId": "A"
}
],
@@ -354,40 +635,80 @@
},
{
"collapsed": false,
- "gridPos": { "h": 1, "w": 24, "x": 0, "y": 28 },
+ "gridPos": {
+ "h": 1,
+ "w": 24,
+ "x": 0,
+ "y": 28
+ },
"id": 30,
"panels": [],
"title": "Change Failure Rate",
"type": "row"
},
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"description": "Change failure rate: % of deployments that caused incidents",
"fieldConfig": {
"defaults": {
- "color": { "mode": "palette-classic" },
+ "color": {
+ "mode": "palette-classic"
+ },
"custom": {
- "axisBorderShow": false, "axisLabel": "", "axisPlacement": "auto",
- "drawStyle": "line", "fillOpacity": 10, "lineInterpolation": "smooth", "lineWidth": 2,
- "pointSize": 5, "showPoints": "never", "spanNulls": true,
- "stacking": { "mode": "none" }, "thresholdsStyle": { "mode": "off" }
+ "axisBorderShow": false,
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "lineInterpolation": "smooth",
+ "lineWidth": 2,
+ "pointSize": 5,
+ "showPoints": "never",
+ "spanNulls": true,
+ "stacking": {
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
},
"unit": "short"
},
"overrides": []
},
- "gridPos": { "h": 8, "w": 24, "x": 0, "y": 29 },
+ "gridPos": {
+ "h": 8,
+ "w": 24,
+ "x": 0,
+ "y": 29
+ },
"id": 31,
"options": {
- "legend": { "calcs": ["mean", "sum"], "displayMode": "table", "placement": "right", "showLegend": true },
- "tooltip": { "mode": "multi" }
+ "legend": {
+ "calcs": [
+ "mean",
+ "sum"
+ ],
+ "displayMode": "table",
+ "placement": "right",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi"
+ }
},
"targets": [
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"format": "time_series",
"rawQuery": true,
- "rawSql": "SELECT time, SUM(credits) AS 'Credits Used', SUM(cfr) AS 'Change Failure Rate'\nFROM (\n SELECT DATE_SUB(DATE(date), INTERVAL WEEKDAY(DATE(date)) DAY) AS time,\n SUM(credits_used) AS credits, 0 AS cfr\n FROM _tool_q_dev_user_report WHERE $__timeFilter(date)\n GROUP BY DATE_SUB(DATE(date), INTERVAL WEEKDAY(DATE(date)) DAY)\n UNION ALL\n SELECT DATE_SUB(DATE(d.deployment_finished_date), INTERVAL WEEKDAY(DATE(d.deployment_finished_date)) DAY) AS time,\n 0 AS [...]
+ "rawSql": "SELECT time, SUM(credits) AS 'Credits Used', SUM(cfr) AS 'Change Failure Rate'\nFROM (\n SELECT DATE_SUB(DATE(date), INTERVAL WEEKDAY(DATE(date)) DAY) AS time,\n SUM(credits_used) AS credits, 0 AS cfr\n FROM _tool_kiro_user_report WHERE $__timeFilter(date)\n GROUP BY DATE_SUB(DATE(date), INTERVAL WEEKDAY(DATE(date)) DAY)\n UNION ALL\n SELECT DATE_SUB(DATE(d.deployment_finished_date), INTERVAL WEEKDAY(DATE(d.deployment_finished_date)) DAY) AS time,\n 0 AS c [...]
"refId": "A"
}
],
@@ -398,12 +719,27 @@
"preload": false,
"refresh": "5m",
"schemaVersion": 41,
- "tags": ["q_dev", "dora", "kiro", "correlation"],
+ "tags": [
+ "kiro",
+ "dora",
+ "correlation"
+ ],
"templating": {
"list": [
{
- "current": { "selected": true, "text": ["All"], "value": ["$__all"] },
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "current": {
+ "selected": true,
+ "text": [
+ "All"
+ ],
+ "value": [
+ "$__all"
+ ]
+ },
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"definition": "SELECT DISTINCT name FROM projects",
"hide": 0,
"includeAll": true,
@@ -417,7 +753,10 @@
}
]
},
- "time": { "from": "now-90d", "to": "now" },
+ "time": {
+ "from": "now-90d",
+ "to": "now"
+ },
"timepicker": {},
"timezone": "utc",
"title": "Kiro Credits + DORA Correlation",
diff --git a/grafana/dashboards/mysql/language-ai-heatmap.json b/grafana/dashboards/mysql/language-ai-heatmap.json
index 789b291e5..46927ea06 100644
--- a/grafana/dashboards/mysql/language-ai-heatmap.json
+++ b/grafana/dashboards/mysql/language-ai-heatmap.json
@@ -19,25 +19,60 @@
"links": [],
"panels": [
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"description": "Completion requests, avg context size, and completion rate per language",
"fieldConfig": {
"defaults": {
- "color": { "mode": "thresholds" },
- "custom": { "align": "auto", "cellOptions": { "type": "auto" }, "filterable": true },
- "thresholds": { "mode": "absolute", "steps": [{ "color": "green" }] }
+ "color": {
+ "mode": "thresholds"
+ },
+ "custom": {
+ "align": "auto",
+ "cellOptions": {
+ "type": "auto"
+ },
+ "filterable": true
+ },
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green"
+ }
+ ]
+ }
},
"overrides": []
},
- "gridPos": { "h": 9, "w": 24, "x": 0, "y": 0 },
+ "gridPos": {
+ "h": 9,
+ "w": 24,
+ "x": 0,
+ "y": 0
+ },
"id": 1,
- "options": { "cellHeight": "sm", "showHeader": true, "sortBy": [{ "desc": true, "displayName": "Requests" }] },
+ "options": {
+ "cellHeight": "sm",
+ "showHeader": true,
+ "sortBy": [
+ {
+ "desc": true,
+ "displayName": "Requests"
+ }
+ ]
+ },
"targets": [
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"format": "table",
"rawQuery": true,
- "rawSql": "SELECT\n CASE WHEN file_extension = '' THEN '(unknown)' ELSE file_extension END AS 'Language',\n COUNT(*) AS 'Requests',\n ROUND(AVG(completions_count), 2) AS 'Avg Completions',\n ROUND(AVG(left_context_length)) AS 'Avg Left Context',\n ROUND(AVG(right_context_length)) AS 'Avg Right Context',\n ROUND(AVG(left_context_length + right_context_length)) AS 'Avg Total Context',\n COUNT(DISTINCT user_id) AS 'Users'\nFROM _tool_q_dev_completion_log\nWHERE $__timeFilte [...]
+ "rawSql": "SELECT\n CASE WHEN file_extension = '' THEN '(unknown)' ELSE file_extension END AS 'Language',\n COUNT(*) AS 'Requests',\n ROUND(AVG(completions_count), 2) AS 'Avg Completions',\n ROUND(AVG(left_context_length)) AS 'Avg Left Context',\n ROUND(AVG(right_context_length)) AS 'Avg Right Context',\n ROUND(AVG(left_context_length + right_context_length)) AS 'Avg Total Context',\n COUNT(DISTINCT user_id) AS 'Users'\nFROM _tool_kiro_completion_log\nWHERE $__timeFilter [...]
"refId": "A"
}
],
@@ -45,31 +80,60 @@
"type": "table"
},
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"description": "Daily completion requests by language",
"fieldConfig": {
"defaults": {
- "color": { "mode": "palette-classic" },
+ "color": {
+ "mode": "palette-classic"
+ },
"custom": {
- "drawStyle": "bars", "fillOpacity": 80, "lineWidth": 1,
- "stacking": { "mode": "normal" }, "thresholdsStyle": { "mode": "off" }
+ "drawStyle": "bars",
+ "fillOpacity": 80,
+ "lineWidth": 1,
+ "stacking": {
+ "mode": "normal"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
},
"unit": "short"
},
"overrides": []
},
- "gridPos": { "h": 8, "w": 24, "x": 0, "y": 9 },
+ "gridPos": {
+ "h": 8,
+ "w": 24,
+ "x": 0,
+ "y": 9
+ },
"id": 2,
"options": {
- "legend": { "calcs": ["sum"], "displayMode": "table", "placement": "right", "showLegend": true },
- "tooltip": { "mode": "multi" }
+ "legend": {
+ "calcs": [
+ "sum"
+ ],
+ "displayMode": "table",
+ "placement": "right",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi"
+ }
},
"targets": [
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"format": "time_series",
"rawQuery": true,
- "rawSql": "SELECT DATE(timestamp) AS time,\n CASE WHEN file_extension = '' THEN '(unknown)' ELSE file_extension END AS metric,\n COUNT(*) AS value\nFROM _tool_q_dev_completion_log\nWHERE $__timeFilter(timestamp)\nGROUP BY DATE(timestamp), file_extension\nORDER BY time",
+ "rawSql": "SELECT DATE(timestamp) AS time,\n CASE WHEN file_extension = '' THEN '(unknown)' ELSE file_extension END AS metric,\n COUNT(*) AS value\nFROM _tool_kiro_completion_log\nWHERE $__timeFilter(timestamp)\nGROUP BY DATE(timestamp), file_extension\nORDER BY time",
"refId": "A"
}
],
@@ -77,64 +141,134 @@
"type": "timeseries"
},
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
- "description": "Which file types are most active during chat sessions",
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
+ "description": "Chat logs do not contain active file types. This uses completion-log file extensions and returned lines.",
"fieldConfig": {
"defaults": {
- "color": { "mode": "palette-classic" },
+ "color": {
+ "mode": "palette-classic"
+ },
"mappings": [],
- "thresholds": { "mode": "absolute", "steps": [{ "color": "green" }] }
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green"
+ }
+ ]
+ }
},
"overrides": []
},
- "gridPos": { "h": 8, "w": 12, "x": 0, "y": 17 },
+ "gridPos": {
+ "h": 8,
+ "w": 12,
+ "x": 0,
+ "y": 17
+ },
"id": 3,
"options": {
- "displayLabels": ["name", "percent"],
- "legend": { "displayMode": "table", "placement": "right", "showLegend": true, "values": ["value", "percent"] },
+ "displayLabels": [
+ "name",
+ "percent"
+ ],
+ "legend": {
+ "displayMode": "table",
+ "placement": "right",
+ "showLegend": true,
+ "values": [
+ "value",
+ "percent"
+ ]
+ },
"pieType": "donut",
- "reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": true },
- "tooltip": { "mode": "single" }
+ "reduceOptions": {
+ "calcs": [
+ "lastNotNull"
+ ],
+ "fields": "",
+ "values": true
+ },
+ "tooltip": {
+ "mode": "single"
+ }
},
"targets": [
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"format": "table",
"rawQuery": true,
- "rawSql": "SELECT\n CASE WHEN active_file_extension = '' OR active_file_extension IS NULL THEN '(no file)' ELSE active_file_extension END AS 'File Type',\n COUNT(*) AS 'Chat Events'\nFROM _tool_q_dev_chat_log\nWHERE $__timeFilter(timestamp)\nGROUP BY active_file_extension\nORDER BY COUNT(*) DESC\nLIMIT 10",
+ "rawSql": "SELECT CASE WHEN file_extension = '' THEN '(unknown)' ELSE file_extension END AS 'File Type', SUM(returned_line_count) AS 'Returned Lines' FROM _tool_kiro_completion_log WHERE $__timeFilter(timestamp) GROUP BY file_extension ORDER BY SUM(returned_line_count) DESC",
"refId": "A"
}
],
- "title": "Active File Types During Chat",
+ "title": "Returned Lines by File Type",
"type": "piechart"
},
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"description": "Context size trends for top languages",
"fieldConfig": {
"defaults": {
- "color": { "mode": "palette-classic" },
+ "color": {
+ "mode": "palette-classic"
+ },
"custom": {
- "drawStyle": "line", "fillOpacity": 10, "lineInterpolation": "smooth", "lineWidth": 2,
- "showPoints": "never", "spanNulls": true,
- "stacking": { "mode": "none" }, "thresholdsStyle": { "mode": "off" }
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "lineInterpolation": "smooth",
+ "lineWidth": 2,
+ "showPoints": "never",
+ "spanNulls": true,
+ "stacking": {
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
},
"unit": "short"
},
"overrides": []
},
- "gridPos": { "h": 8, "w": 12, "x": 12, "y": 17 },
+ "gridPos": {
+ "h": 8,
+ "w": 12,
+ "x": 12,
+ "y": 17
+ },
"id": 4,
"options": {
- "legend": { "calcs": ["mean"], "displayMode": "table", "placement": "right", "showLegend": true },
- "tooltip": { "mode": "multi" }
+ "legend": {
+ "calcs": [
+ "mean"
+ ],
+ "displayMode": "table",
+ "placement": "right",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi"
+ }
},
"targets": [
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"format": "time_series",
"rawQuery": true,
- "rawSql": "SELECT DATE(timestamp) AS time,\n file_extension AS metric,\n ROUND(AVG(left_context_length + right_context_length)) AS value\nFROM _tool_q_dev_completion_log\nWHERE $__timeFilter(timestamp)\n AND file_extension IN (SELECT file_extension FROM _tool_q_dev_completion_log GROUP BY file_extension ORDER BY COUNT(*) DESC LIMIT 5)\nGROUP BY DATE(timestamp), file_extension\nORDER BY time",
+ "rawSql": "WITH top_extensions AS (SELECT file_extension FROM _tool_kiro_completion_log GROUP BY file_extension ORDER BY COUNT(*) DESC LIMIT 5) SELECT DATE(c.timestamp) AS time, c.file_extension AS metric, ROUND(AVG(c.left_context_length + c.right_context_length)) AS value FROM _tool_kiro_completion_log c INNER JOIN top_extensions t ON c.file_extension = t.file_extension WHERE $__timeFilter(c.timestamp) GROUP BY DATE(c.timestamp), c.file_extension ORDER BY time",
"refId": "A"
}
],
@@ -145,9 +279,18 @@
"preload": false,
"refresh": "5m",
"schemaVersion": 41,
- "tags": ["q_dev", "kiro", "language", "completions"],
- "templating": { "list": [] },
- "time": { "from": "now-90d", "to": "now" },
+ "tags": [
+ "kiro",
+ "language",
+ "completions"
+ ],
+ "templating": {
+ "list": []
+ },
+ "time": {
+ "from": "now-90d",
+ "to": "now"
+ },
"timepicker": {},
"timezone": "utc",
"title": "Kiro Language AI Heatmap",
diff --git a/grafana/dashboards/mysql/multi-ai-comparison.json b/grafana/dashboards/mysql/multi-ai-comparison.json
index 617cda776..150844414 100644
--- a/grafana/dashboards/mysql/multi-ai-comparison.json
+++ b/grafana/dashboards/mysql/multi-ai-comparison.json
@@ -26,7 +26,7 @@
"targetBlank": true,
"title": "Kiro Usage",
"type": "link",
- "url": "/d/qdev_user_report"
+ "url": "/d/kiro_user_report"
},
{
"asDropdown": false,
@@ -46,11 +46,20 @@
"type": "datasource",
"uid": "grafana"
},
- "gridPos": { "h": 3, "w": 24, "x": 0, "y": 0 },
+ "gridPos": {
+ "h": 3,
+ "w": 24,
+ "x": 0,
+ "y": 0
+ },
"id": 1,
"options": {
- "code": { "language": "plaintext", "showLineNumbers": false, "showMiniMap": false },
- "content": "## Multi-AI Tool Comparison: Copilot vs Kiro\nCompare GitHub Copilot and Kiro (Amazon Q Developer) adoption and usage side by side.\n\n**Note:** Copilot metrics come from `_tool_copilot_enterprise_daily_metrics` (enterprise-level aggregates). Kiro metrics come from `_tool_q_dev_user_report` and `_tool_q_dev_user_data`. Select the Copilot connection and scope using the dropdowns above.",
+ "code": {
+ "language": "plaintext",
+ "showLineNumbers": false,
+ "showMiniMap": false
+ },
+ "content": "## Multi-AI Tool Comparison: Copilot vs Kiro\nCompare GitHub Copilot and Kiro adoption and activity side by side.\n\n**Semantic boundary:** Copilot exports code-generation and acceptance events. Kiro exports usage reports and completion responses, but no acceptance event. Returned Kiro lines and Copilot LOC added are displayed with explicit labels and must not be treated as equivalent productivity measures.",
"mode": "markdown"
},
"title": "About",
@@ -58,44 +67,87 @@
},
{
"collapsed": false,
- "gridPos": { "h": 1, "w": 24, "x": 0, "y": 3 },
+ "gridPos": {
+ "h": 1,
+ "w": 24,
+ "x": 0,
+ "y": 3
+ },
"id": 2,
"panels": [],
"title": "Active Users",
"type": "row"
},
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"description": "Weekly active users for both tools",
"fieldConfig": {
"defaults": {
- "color": { "mode": "palette-classic" },
+ "color": {
+ "mode": "palette-classic"
+ },
"custom": {
- "axisBorderShow": false, "axisLabel": "", "axisPlacement": "auto",
- "drawStyle": "line", "fillOpacity": 10, "lineInterpolation": "smooth", "lineWidth": 2,
- "pointSize": 5, "showPoints": "never", "spanNulls": true,
- "stacking": { "mode": "none" }, "thresholdsStyle": { "mode": "off" }
+ "axisBorderShow": false,
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "lineInterpolation": "smooth",
+ "lineWidth": 2,
+ "pointSize": 5,
+ "showPoints": "never",
+ "spanNulls": true,
+ "stacking": {
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
},
"unit": "short"
},
"overrides": []
},
- "gridPos": { "h": 8, "w": 24, "x": 0, "y": 4 },
+ "gridPos": {
+ "h": 8,
+ "w": 24,
+ "x": 0,
+ "y": 4
+ },
"id": 3,
"options": {
- "legend": { "calcs": ["mean", "max"], "displayMode": "table", "placement": "right", "showLegend": true },
- "tooltip": { "mode": "multi" }
+ "legend": {
+ "calcs": [
+ "mean",
+ "max"
+ ],
+ "displayMode": "table",
+ "placement": "right",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi"
+ }
},
"targets": [
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"format": "time_series",
"rawQuery": true,
- "rawSql": "SELECT\n DATE_SUB(DATE(date), INTERVAL WEEKDAY(DATE(date)) DAY) AS time,\n COUNT(DISTINCT user_id) AS 'Kiro Active Users'\nFROM _tool_q_dev_user_report\nWHERE $__timeFilter(date)\nGROUP BY DATE_SUB(DATE(date), INTERVAL WEEKDAY(DATE(date)) DAY)\nORDER BY time",
+ "rawSql": "SELECT\n DATE_SUB(DATE(date), INTERVAL WEEKDAY(DATE(date)) DAY) AS time,\n COUNT(DISTINCT user_id) AS 'Kiro Active Users'\nFROM _tool_kiro_user_report\nWHERE $__timeFilter(date)\nGROUP BY DATE_SUB(DATE(date), INTERVAL WEEKDAY(DATE(date)) DAY)\nORDER BY time",
"refId": "A"
},
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"format": "time_series",
"rawQuery": true,
"rawSql": "SELECT\n DATE_SUB(DATE(day), INTERVAL WEEKDAY(DATE(day)) DAY) AS time,\n MAX(daily_active_users) AS 'Copilot Active Users'\nFROM _tool_copilot_enterprise_daily_metrics\nWHERE connection_id = ${copilot_connection_id}\n AND scope_id = '${copilot_scope_id}'\n AND $__timeFilter(day)\nGROUP BY DATE_SUB(DATE(day), INTERVAL WEEKDAY(DATE(day)) DAY)\nORDER BY time",
@@ -107,71 +159,146 @@
},
{
"collapsed": false,
- "gridPos": { "h": 1, "w": 24, "x": 0, "y": 12 },
+ "gridPos": {
+ "h": 1,
+ "w": 24,
+ "x": 0,
+ "y": 12
+ },
"id": 10,
"panels": [],
- "title": "Code Generation",
+ "title": "Assistant Activity",
"type": "row"
},
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
- "description": "Weekly code generation and acceptance events",
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
+ "description": "Kiro completion requests and requests returning suggestions. Returned does not mean accepted.",
"fieldConfig": {
"defaults": {
- "color": { "mode": "palette-classic" },
+ "color": {
+ "mode": "palette-classic"
+ },
"custom": {
- "axisBorderShow": false, "axisLabel": "", "axisPlacement": "auto",
- "drawStyle": "line", "fillOpacity": 10, "lineInterpolation": "smooth", "lineWidth": 2,
- "pointSize": 5, "showPoints": "never", "spanNulls": true,
- "stacking": { "mode": "none" }, "thresholdsStyle": { "mode": "off" }
+ "axisBorderShow": false,
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "lineInterpolation": "smooth",
+ "lineWidth": 2,
+ "pointSize": 5,
+ "showPoints": "never",
+ "spanNulls": true,
+ "stacking": {
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
},
"unit": "short"
},
"overrides": []
},
- "gridPos": { "h": 8, "w": 12, "x": 0, "y": 13 },
+ "gridPos": {
+ "h": 8,
+ "w": 12,
+ "x": 0,
+ "y": 13
+ },
"id": 11,
"options": {
- "legend": { "calcs": ["mean", "sum"], "displayMode": "table", "placement": "right", "showLegend": true },
- "tooltip": { "mode": "multi" }
+ "legend": {
+ "calcs": [
+ "mean",
+ "sum"
+ ],
+ "displayMode": "table",
+ "placement": "right",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi"
+ }
},
"targets": [
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"format": "time_series",
"rawQuery": true,
- "rawSql": "SELECT\n DATE_SUB(DATE(date), INTERVAL WEEKDAY(DATE(date)) DAY) AS time,\n SUM(inline_suggestions_count) AS 'Kiro: Suggestions',\n SUM(inline_acceptance_count) AS 'Kiro: Accepted'\nFROM _tool_q_dev_user_data\nWHERE $__timeFilter(date)\nGROUP BY DATE_SUB(DATE(date), INTERVAL WEEKDAY(DATE(date)) DAY)\nORDER BY time",
+ "rawSql": "SELECT DATE_SUB(DATE(timestamp), INTERVAL WEEKDAY(DATE(timestamp)) DAY) AS time, COUNT(*) AS 'Kiro: Completion Requests', SUM(CASE WHEN completions_count > 0 THEN 1 ELSE 0 END) AS 'Kiro: Requests with Results' FROM _tool_kiro_completion_log WHERE $__timeFilter(timestamp) GROUP BY DATE_SUB(DATE(timestamp), INTERVAL WEEKDAY(DATE(timestamp)) DAY) ORDER BY time",
"refId": "A"
}
],
- "title": "Kiro: Code Suggestions & Acceptance",
+ "title": "Kiro Completion Requests & Results",
"type": "timeseries"
},
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"description": "Weekly Copilot code generation and acceptance events",
"fieldConfig": {
"defaults": {
- "color": { "mode": "palette-classic" },
+ "color": {
+ "mode": "palette-classic"
+ },
"custom": {
- "axisBorderShow": false, "axisLabel": "", "axisPlacement": "auto",
- "drawStyle": "line", "fillOpacity": 10, "lineInterpolation": "smooth", "lineWidth": 2,
- "pointSize": 5, "showPoints": "never", "spanNulls": true,
- "stacking": { "mode": "none" }, "thresholdsStyle": { "mode": "off" }
+ "axisBorderShow": false,
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "lineInterpolation": "smooth",
+ "lineWidth": 2,
+ "pointSize": 5,
+ "showPoints": "never",
+ "spanNulls": true,
+ "stacking": {
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
},
"unit": "short"
},
"overrides": []
},
- "gridPos": { "h": 8, "w": 12, "x": 12, "y": 13 },
+ "gridPos": {
+ "h": 8,
+ "w": 12,
+ "x": 12,
+ "y": 13
+ },
"id": 12,
"options": {
- "legend": { "calcs": ["mean", "sum"], "displayMode": "table", "placement": "right", "showLegend": true },
- "tooltip": { "mode": "multi" }
+ "legend": {
+ "calcs": [
+ "mean",
+ "sum"
+ ],
+ "displayMode": "table",
+ "placement": "right",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi"
+ }
},
"targets": [
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"format": "time_series",
"rawQuery": true,
"rawSql": "SELECT\n DATE_SUB(DATE(day), INTERVAL WEEKDAY(DATE(day)) DAY) AS time,\n SUM(code_generation_activity_count) AS 'Copilot: Suggestions',\n SUM(code_acceptance_activity_count) AS 'Copilot: Accepted'\nFROM _tool_copilot_enterprise_daily_metrics\nWHERE connection_id = ${copilot_connection_id}\n AND scope_id = '${copilot_scope_id}'\n AND $__timeFilter(day)\nGROUP BY DATE_SUB(DATE(day), INTERVAL WEEKDAY(DATE(day)) DAY)\nORDER BY time",
@@ -183,59 +310,117 @@
},
{
"collapsed": false,
- "gridPos": { "h": 1, "w": 24, "x": 0, "y": 21 },
+ "gridPos": {
+ "h": 1,
+ "w": 24,
+ "x": 0,
+ "y": 21
+ },
"id": 20,
"panels": [],
- "title": "Lines of Code & Acceptance Rate",
+ "title": "Returned Lines & Acceptance Availability",
"type": "row"
},
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
- "description": "Weekly AI-generated lines of code accepted",
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
+ "description": "Different semantics: Kiro counts lines returned to the IDE; Copilot counts LOC added. Do not interpret as an acceptance comparison.",
"fieldConfig": {
"defaults": {
- "color": { "mode": "palette-classic" },
+ "color": {
+ "mode": "palette-classic"
+ },
"custom": {
- "axisBorderShow": false, "axisLabel": "", "axisPlacement": "auto",
- "drawStyle": "line", "fillOpacity": 10, "lineInterpolation": "smooth", "lineWidth": 2,
- "pointSize": 5, "showPoints": "never", "spanNulls": true,
- "stacking": { "mode": "none" }, "thresholdsStyle": { "mode": "off" }
+ "axisBorderShow": false,
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "lineInterpolation": "smooth",
+ "lineWidth": 2,
+ "pointSize": 5,
+ "showPoints": "never",
+ "spanNulls": true,
+ "stacking": {
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
},
"unit": "short"
},
"overrides": []
},
- "gridPos": { "h": 8, "w": 12, "x": 0, "y": 22 },
+ "gridPos": {
+ "h": 8,
+ "w": 12,
+ "x": 0,
+ "y": 22
+ },
"id": 21,
"options": {
- "legend": { "calcs": ["mean", "sum"], "displayMode": "table", "placement": "right", "showLegend": true },
- "tooltip": { "mode": "multi" }
+ "legend": {
+ "calcs": [
+ "mean",
+ "sum"
+ ],
+ "displayMode": "table",
+ "placement": "right",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi"
+ }
},
"targets": [
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"format": "time_series",
"rawQuery": true,
- "rawSql": "SELECT time, SUM(kiro_loc) AS 'Kiro LOC Accepted', SUM(copilot_loc) AS 'Copilot LOC Added'\nFROM (\n SELECT DATE_SUB(DATE(date), INTERVAL WEEKDAY(DATE(date)) DAY) AS time,\n SUM(inline_ai_code_lines + chat_ai_code_lines) AS kiro_loc, 0 AS copilot_loc\n FROM _tool_q_dev_user_data WHERE $__timeFilter(date)\n GROUP BY DATE_SUB(DATE(date), INTERVAL WEEKDAY(DATE(date)) DAY)\n UNION ALL\n SELECT DATE_SUB(DATE(day), INTERVAL WEEKDAY(DATE(day)) DAY) AS time,\n 0 A [...]
+ "rawSql": "SELECT time, SUM(kiro_lines) AS 'Kiro Returned Lines', SUM(copilot_loc) AS 'Copilot LOC Added' FROM (SELECT DATE_SUB(DATE(timestamp), INTERVAL WEEKDAY(DATE(timestamp)) DAY) AS time, SUM(returned_line_count) AS kiro_lines, 0 AS copilot_loc FROM _tool_kiro_completion_log WHERE $__timeFilter(timestamp) GROUP BY DATE_SUB(DATE(timestamp), INTERVAL WEEKDAY(DATE(timestamp)) DAY) UNION ALL SELECT DATE_SUB(DATE(day), INTERVAL WEEKDAY(DATE(day)) DAY) AS time, 0 AS kiro_lines, [...]
"refId": "A"
}
],
- "title": "LOC Accepted: Kiro vs Copilot",
+ "title": "Kiro Returned Lines vs Copilot LOC Added",
"type": "timeseries"
},
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
- "description": "Overall acceptance rates for both tools",
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
+ "description": "Kiro exports no suggestion-acceptance event, so its value is NULL. Copilot acceptance remains available.",
"fieldConfig": {
"defaults": {
- "color": { "mode": "palette-classic" },
+ "color": {
+ "mode": "palette-classic"
+ },
"mappings": [],
- "thresholds": { "mode": "absolute", "steps": [{ "color": "green", "value": null }] },
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ }
+ ]
+ },
"unit": "percent"
},
"overrides": []
},
- "gridPos": { "h": 8, "w": 12, "x": 12, "y": 22 },
+ "gridPos": {
+ "h": 8,
+ "w": 12,
+ "x": 12,
+ "y": 22
+ },
"id": 22,
"options": {
"barRadius": 0.1,
@@ -243,30 +428,42 @@
"orientation": "horizontal",
"showValue": "auto",
"stacking": "none",
- "tooltip": { "mode": "single" }
+ "tooltip": {
+ "mode": "single"
+ }
},
"targets": [
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"format": "table",
"rawQuery": true,
- "rawSql": "SELECT 'Kiro' AS Tool,\n ROUND(SUM(inline_acceptance_count) * 100.0 / NULLIF(SUM(inline_suggestions_count), 0), 1) AS 'Acceptance Rate'\nFROM _tool_q_dev_user_data\nWHERE $__timeFilter(date)\nUNION ALL\nSELECT 'Copilot' AS Tool,\n ROUND(SUM(code_acceptance_activity_count) * 100.0 / NULLIF(SUM(code_generation_activity_count), 0), 1)\nFROM _tool_copilot_enterprise_daily_metrics\nWHERE connection_id = ${copilot_connection_id}\n AND scope_id = '${copilot_scope_id}'\n [...]
+ "rawSql": "SELECT 'Kiro (not exported)' AS 'Tool', CAST(NULL AS DECIMAL(10,2)) AS 'Acceptance Rate' UNION ALL SELECT 'Copilot' AS 'Tool', ROUND(SUM(code_acceptance_activity_count) * 100.0 / NULLIF(SUM(code_generation_activity_count), 0), 1) AS 'Acceptance Rate' FROM _tool_copilot_enterprise_daily_metrics WHERE connection_id = ${copilot_connection_id} AND scope_id = '${copilot_scope_id}' AND $__timeFilter(day)",
"refId": "A"
}
],
- "title": "Acceptance Rate Comparison",
+ "title": "Acceptance Rate Availability",
"type": "bargauge"
}
],
"preload": false,
"refresh": "5m",
"schemaVersion": 41,
- "tags": ["q_dev", "copilot", "kiro", "comparison"],
+ "tags": [
+ "kiro",
+ "copilot",
+ "comparison"
+ ],
"templating": {
"list": [
{
"current": {},
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"definition": "SELECT DISTINCT connection_id FROM _tool_copilot_scopes ORDER BY connection_id DESC",
"hide": 0,
"label": "Copilot Connection",
@@ -278,7 +475,10 @@
},
{
"current": {},
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"definition": "SELECT DISTINCT id FROM _tool_copilot_scopes WHERE connection_id = CAST('${copilot_connection_id}' AS UNSIGNED)",
"hide": 0,
"label": "Copilot Scope",
@@ -290,7 +490,10 @@
}
]
},
- "time": { "from": "now-90d", "to": "now" },
+ "time": {
+ "from": "now-90d",
+ "to": "now"
+ },
"timepicker": {},
"timezone": "utc",
"title": "Multi-AI Tool Comparison",
diff --git a/grafana/dashboards/mysql/steering-adoption-tracker.json b/grafana/dashboards/mysql/steering-adoption-tracker.json
index 14711cfd6..fa17c3d6f 100644
--- a/grafana/dashboards/mysql/steering-adoption-tracker.json
+++ b/grafana/dashboards/mysql/steering-adoption-tracker.json
@@ -19,29 +19,56 @@
"links": [],
"panels": [
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"fieldConfig": {
"defaults": {
- "color": { "mode": "thresholds" },
+ "color": {
+ "mode": "thresholds"
+ },
"mappings": [],
- "thresholds": { "mode": "absolute", "steps": [{ "color": "blue" }] },
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "blue"
+ }
+ ]
+ },
"unit": "percent"
},
"overrides": []
},
- "gridPos": { "h": 6, "w": 8, "x": 0, "y": 0 },
+ "gridPos": {
+ "h": 6,
+ "w": 8,
+ "x": 0,
+ "y": 0
+ },
"id": 1,
"options": {
- "colorMode": "value", "graphMode": "area",
- "reduceOptions": { "calcs": ["sum"], "fields": "", "values": false },
+ "colorMode": "value",
+ "graphMode": "area",
+ "reduceOptions": {
+ "calcs": [
+ "sum"
+ ],
+ "fields": "",
+ "values": false
+ },
"textMode": "auto"
},
"targets": [
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"format": "table",
"rawQuery": true,
- "rawSql": "SELECT ROUND(COUNT(DISTINCT CASE WHEN has_steering = 1 THEN user_id END) * 100.0 / NULLIF(COUNT(DISTINCT user_id), 0), 0) AS 'value'\nFROM _tool_q_dev_chat_log WHERE $__timeFilter(timestamp)",
+ "rawSql": "SELECT ROUND(COUNT(DISTINCT CASE WHEN has_steering = 1 THEN user_id END) * 100.0 / NULLIF(COUNT(DISTINCT user_id), 0), 0) AS 'value'\nFROM _tool_kiro_chat_log WHERE $__timeFilter(timestamp)",
"refId": "A"
}
],
@@ -49,29 +76,56 @@
"type": "stat"
},
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"fieldConfig": {
"defaults": {
- "color": { "mode": "thresholds" },
+ "color": {
+ "mode": "thresholds"
+ },
"mappings": [],
- "thresholds": { "mode": "absolute", "steps": [{ "color": "purple" }] },
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "purple"
+ }
+ ]
+ },
"unit": "percent"
},
"overrides": []
},
- "gridPos": { "h": 6, "w": 8, "x": 8, "y": 0 },
+ "gridPos": {
+ "h": 6,
+ "w": 8,
+ "x": 8,
+ "y": 0
+ },
"id": 2,
"options": {
- "colorMode": "value", "graphMode": "area",
- "reduceOptions": { "calcs": ["sum"], "fields": "", "values": false },
+ "colorMode": "value",
+ "graphMode": "area",
+ "reduceOptions": {
+ "calcs": [
+ "sum"
+ ],
+ "fields": "",
+ "values": false
+ },
"textMode": "auto"
},
"targets": [
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"format": "table",
"rawQuery": true,
- "rawSql": "SELECT ROUND(COUNT(DISTINCT CASE WHEN is_spec_mode = 1 THEN user_id END) * 100.0 / NULLIF(COUNT(DISTINCT user_id), 0), 0) AS 'value'\nFROM _tool_q_dev_chat_log WHERE $__timeFilter(timestamp)",
+ "rawSql": "SELECT ROUND(COUNT(DISTINCT CASE WHEN is_spec_mode = 1 THEN user_id END) * 100.0 / NULLIF(COUNT(DISTINCT user_id), 0), 0) AS 'value'\nFROM _tool_kiro_chat_log WHERE $__timeFilter(timestamp)",
"refId": "A"
}
],
@@ -79,29 +133,56 @@
"type": "stat"
},
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"fieldConfig": {
"defaults": {
- "color": { "mode": "thresholds" },
+ "color": {
+ "mode": "thresholds"
+ },
"mappings": [],
- "thresholds": { "mode": "absolute", "steps": [{ "color": "green" }] },
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green"
+ }
+ ]
+ },
"unit": "percent"
},
"overrides": []
},
- "gridPos": { "h": 6, "w": 8, "x": 16, "y": 0 },
+ "gridPos": {
+ "h": 6,
+ "w": 8,
+ "x": 16,
+ "y": 0
+ },
"id": 3,
"options": {
- "colorMode": "value", "graphMode": "area",
- "reduceOptions": { "calcs": ["sum"], "fields": "", "values": false },
+ "colorMode": "value",
+ "graphMode": "area",
+ "reduceOptions": {
+ "calcs": [
+ "sum"
+ ],
+ "fields": "",
+ "values": false
+ },
"textMode": "auto"
},
"targets": [
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"format": "table",
"rawQuery": true,
- "rawSql": "SELECT ROUND(SUM(CASE WHEN has_steering = 1 THEN 1 ELSE 0 END) * 100.0 / COUNT(*), 1) AS 'value'\nFROM _tool_q_dev_chat_log WHERE $__timeFilter(timestamp)",
+ "rawSql": "SELECT ROUND(SUM(CASE WHEN has_steering = 1 THEN 1 ELSE 0 END) * 100.0 / COUNT(*), 1) AS 'value'\nFROM _tool_kiro_chat_log WHERE $__timeFilter(timestamp)",
"refId": "A"
}
],
@@ -109,32 +190,64 @@
"type": "stat"
},
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"description": "Weekly trend of steering and spec mode adoption rate",
"fieldConfig": {
"defaults": {
- "color": { "mode": "palette-classic" },
+ "color": {
+ "mode": "palette-classic"
+ },
"custom": {
- "drawStyle": "line", "fillOpacity": 10, "lineInterpolation": "smooth", "lineWidth": 2,
- "showPoints": "never", "spanNulls": true,
- "stacking": { "mode": "none" }, "thresholdsStyle": { "mode": "off" }
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "lineInterpolation": "smooth",
+ "lineWidth": 2,
+ "showPoints": "never",
+ "spanNulls": true,
+ "stacking": {
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
},
"unit": "percentunit"
},
"overrides": []
},
- "gridPos": { "h": 8, "w": 24, "x": 0, "y": 6 },
+ "gridPos": {
+ "h": 8,
+ "w": 24,
+ "x": 0,
+ "y": 6
+ },
"id": 4,
"options": {
- "legend": { "calcs": ["mean", "max"], "displayMode": "table", "placement": "right", "showLegend": true },
- "tooltip": { "mode": "multi" }
+ "legend": {
+ "calcs": [
+ "mean",
+ "max"
+ ],
+ "displayMode": "table",
+ "placement": "right",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi"
+ }
},
"targets": [
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"format": "time_series",
"rawQuery": true,
- "rawSql": "SELECT\n DATE_SUB(DATE(timestamp), INTERVAL WEEKDAY(DATE(timestamp)) DAY) AS time,\n SUM(CASE WHEN has_steering = 1 THEN 1 ELSE 0 END) / COUNT(*) AS 'Steering Rate',\n SUM(CASE WHEN is_spec_mode = 1 THEN 1 ELSE 0 END) / COUNT(*) AS 'Spec Mode Rate'\nFROM _tool_q_dev_chat_log\nWHERE $__timeFilter(timestamp)\nGROUP BY DATE_SUB(DATE(timestamp), INTERVAL WEEKDAY(DATE(timestamp)) DAY)\nORDER BY time",
+ "rawSql": "SELECT\n DATE_SUB(DATE(timestamp), INTERVAL WEEKDAY(DATE(timestamp)) DAY) AS time,\n SUM(CASE WHEN has_steering = 1 THEN 1 ELSE 0 END) / COUNT(*) AS 'Steering Rate',\n SUM(CASE WHEN is_spec_mode = 1 THEN 1 ELSE 0 END) / COUNT(*) AS 'Spec Mode Rate'\nFROM _tool_kiro_chat_log\nWHERE $__timeFilter(timestamp)\nGROUP BY DATE_SUB(DATE(timestamp), INTERVAL WEEKDAY(DATE(timestamp)) DAY)\nORDER BY time",
"refId": "A"
}
],
@@ -142,29 +255,54 @@
"type": "timeseries"
},
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"description": "Compare prompt and response quality between steering and non-steering sessions",
"fieldConfig": {
"defaults": {
- "color": { "mode": "palette-classic" },
- "thresholds": { "mode": "absolute", "steps": [{ "color": "green" }] },
+ "color": {
+ "mode": "palette-classic"
+ },
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green"
+ }
+ ]
+ },
"unit": "short"
},
"overrides": []
},
- "gridPos": { "h": 8, "w": 12, "x": 0, "y": 14 },
+ "gridPos": {
+ "h": 8,
+ "w": 12,
+ "x": 0,
+ "y": 14
+ },
"id": 5,
"options": {
- "barRadius": 0.1, "barWidth": 0.5,
- "orientation": "horizontal", "showValue": "auto", "stacking": "none",
- "tooltip": { "mode": "single" }
+ "barRadius": 0.1,
+ "barWidth": 0.5,
+ "orientation": "horizontal",
+ "showValue": "auto",
+ "stacking": "none",
+ "tooltip": {
+ "mode": "single"
+ }
},
"targets": [
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"format": "table",
"rawQuery": true,
- "rawSql": "SELECT 'With Steering' AS 'Mode', ROUND(AVG(prompt_length)) AS 'Avg Prompt', ROUND(AVG(response_length)) AS 'Avg Response'\nFROM _tool_q_dev_chat_log WHERE has_steering = 1 AND $__timeFilter(timestamp)\nUNION ALL\nSELECT 'Without Steering', ROUND(AVG(prompt_length)), ROUND(AVG(response_length))\nFROM _tool_q_dev_chat_log WHERE has_steering = 0 AND $__timeFilter(timestamp)",
+ "rawSql": "SELECT 'With Steering' AS 'Mode', ROUND(AVG(prompt_length)) AS 'Avg Prompt', ROUND(AVG(response_length)) AS 'Avg Response'\nFROM _tool_kiro_chat_log WHERE has_steering = 1 AND $__timeFilter(timestamp)\nUNION ALL\nSELECT 'Without Steering', ROUND(AVG(prompt_length)), ROUND(AVG(response_length))\nFROM _tool_kiro_chat_log WHERE has_steering = 0 AND $__timeFilter(timestamp)",
"refId": "A"
}
],
@@ -172,25 +310,54 @@
"type": "bargauge"
},
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
- "description": "Per-user steering and spec mode usage",
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
+ "description": "Per-user steering and spec-mode use, with names resolved from usage reports.",
"fieldConfig": {
"defaults": {
- "color": { "mode": "thresholds" },
- "custom": { "align": "auto", "cellOptions": { "type": "auto" }, "filterable": true },
- "thresholds": { "mode": "absolute", "steps": [{ "color": "green" }] }
+ "color": {
+ "mode": "thresholds"
+ },
+ "custom": {
+ "align": "auto",
+ "cellOptions": {
+ "type": "auto"
+ },
+ "filterable": true
+ },
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green"
+ }
+ ]
+ }
},
"overrides": []
},
- "gridPos": { "h": 8, "w": 12, "x": 12, "y": 14 },
+ "gridPos": {
+ "h": 8,
+ "w": 12,
+ "x": 12,
+ "y": 14
+ },
"id": 6,
- "options": { "cellHeight": "sm", "showHeader": true },
+ "options": {
+ "cellHeight": "sm",
+ "showHeader": true
+ },
"targets": [
{
- "datasource": {"type": "mysql", "uid": "devlake-mysql-api"},
+ "datasource": {
+ "type": "mysql",
+ "uid": "devlake-mysql-api"
+ },
"format": "table",
"rawQuery": true,
- "rawSql": "SELECT\n COALESCE(MAX(display_name), user_id) AS 'User',\n COUNT(*) AS 'Total Chats',\n SUM(CASE WHEN has_steering = 1 THEN 1 ELSE 0 END) AS 'Steering',\n SUM(CASE WHEN is_spec_mode = 1 THEN 1 ELSE 0 END) AS 'Spec Mode',\n ROUND(SUM(CASE WHEN has_steering = 1 THEN 1 ELSE 0 END) * 100.0 / COUNT(*), 1) AS 'Steering %'\nFROM _tool_q_dev_chat_log\nWHERE $__timeFilter(timestamp)\nGROUP BY user_id\nORDER BY COUNT(*) DESC",
+ "rawSql": "WITH names AS (SELECT user_id, MAX(display_name) AS display_name FROM _tool_kiro_user_report WHERE $__timeFilter(date) GROUP BY user_id) SELECT COALESCE(n.display_name, c.user_id) AS 'User', COUNT(*) AS 'Total Chats', SUM(CASE WHEN has_steering = 1 THEN 1 ELSE 0 END) AS 'Steering', SUM(CASE WHEN is_spec_mode = 1 THEN 1 ELSE 0 END) AS 'Spec Mode', ROUND(SUM(CASE WHEN has_steering = 1 THEN 1 ELSE 0 END) * 100.0 / NULLIF(COUNT(*), 0), 1) AS 'Steering %' FROM _tool_kiro_ [...]
"refId": "A"
}
],
@@ -201,9 +368,18 @@
"preload": false,
"refresh": "5m",
"schemaVersion": 41,
- "tags": ["q_dev", "kiro", "steering", "adoption"],
- "templating": { "list": [] },
- "time": { "from": "now-90d", "to": "now" },
+ "tags": [
+ "kiro",
+ "steering",
+ "adoption"
+ ],
+ "templating": {
+ "list": []
+ },
+ "time": {
+ "from": "now-90d",
+ "to": "now"
+ },
"timepicker": {},
"timezone": "utc",
"title": "Kiro Steering & Spec Mode Adoption",
diff --git a/grafana/dashboards/postgresql/ai-cost-efficiency.json b/grafana/dashboards/postgresql/ai-cost-efficiency.json
index 497a05b0f..2b7723c70 100644
--- a/grafana/dashboards/postgresql/ai-cost-efficiency.json
+++ b/grafana/dashboards/postgresql/ai-cost-efficiency.json
@@ -26,7 +26,7 @@
"targetBlank": true,
"title": "Kiro Usage Dashboard",
"type": "link",
- "url": "/d/qdev_user_report"
+ "url": "/d/kiro_user_report"
}
],
"panels": [
@@ -44,7 +44,10 @@
"type": "row"
},
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"fieldConfig": {
"defaults": {
"color": {
@@ -84,10 +87,13 @@
},
"targets": [
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"format": "table",
"rawQuery": true,
- "rawSql": "SELECT ROUND(SUM(credits_used)) AS \"Total Credits\" FROM _tool_q_dev_user_report WHERE $__timeFilter(date)",
+ "rawSql": "SELECT ROUND(SUM(credits_used)) AS \"Total Credits\" FROM _tool_kiro_user_report WHERE $__timeFilter(date)",
"refId": "A"
}
],
@@ -95,7 +101,10 @@
"type": "stat"
},
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"fieldConfig": {
"defaults": {
"color": {
@@ -135,10 +144,13 @@
},
"targets": [
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"format": "table",
"rawQuery": true,
- "rawSql": "SELECT ROUND(CAST(CAST(SUM(r.credits_used) AS NUMERIC) / NULLIF(NULLIF(COUNT(DISTINCT pr.id), 0), 0) AS DECIMAL), 1) AS \"Credits / PR\" FROM _tool_q_dev_user_report AS r CROSS JOIN (SELECT DISTINCT id FROM pull_requests WHERE NOT merged_date IS NULL AND $__timeFilter(merged_date)) AS pr WHERE $__timeFilter(r.date)",
+ "rawSql": "SELECT ROUND(CAST(CAST(SUM(r.credits_used) AS NUMERIC) / NULLIF(NULLIF(COUNT(DISTINCT pr.id), 0), 0) AS DECIMAL), 1) AS \"Credits / PR\" FROM _tool_kiro_user_report AS r CROSS JOIN (SELECT DISTINCT id FROM pull_requests WHERE NOT merged_date IS NULL AND $__timeFilter(merged_date)) AS pr WHERE $__timeFilter(r.date)",
"refId": "A"
}
],
@@ -146,7 +158,10 @@
"type": "stat"
},
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"fieldConfig": {
"defaults": {
"color": {
@@ -186,10 +201,13 @@
},
"targets": [
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"format": "table",
"rawQuery": true,
- "rawSql": "SELECT ROUND(CAST(CAST(SUM(r.credits_used) AS NUMERIC) / NULLIF(NULLIF(COUNT(DISTINCT cdc.cicd_deployment_id), 0), 0) AS DECIMAL), 1) AS \"Credits / Deploy\" FROM _tool_q_dev_user_report AS r CROSS JOIN (SELECT DISTINCT cicd_deployment_id FROM cicd_deployment_commits WHERE result = 'SUCCESS' AND environment = 'PRODUCTION' AND $__timeFilter(finished_date)) AS cdc WHERE $__timeFilter(r.date)",
+ "rawSql": "SELECT ROUND(CAST(CAST(SUM(r.credits_used) AS NUMERIC) / NULLIF(NULLIF(COUNT(DISTINCT cdc.cicd_deployment_id), 0), 0) AS DECIMAL), 1) AS \"Credits / Deploy\" FROM _tool_kiro_user_report AS r CROSS JOIN (SELECT DISTINCT cicd_deployment_id FROM cicd_deployment_commits WHERE result = 'SUCCESS' AND environment = 'PRODUCTION' AND $__timeFilter(finished_date)) AS cdc WHERE $__timeFilter(r.date)",
"refId": "A"
}
],
@@ -197,7 +215,10 @@
"type": "stat"
},
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"fieldConfig": {
"defaults": {
"color": {
@@ -237,10 +258,13 @@
},
"targets": [
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"format": "table",
"rawQuery": true,
- "rawSql": "SELECT ROUND(CAST(CAST(SUM(r.credits_used) AS NUMERIC) / NULLIF(NULLIF(COUNT(DISTINCT i.id), 0), 0) AS DECIMAL), 1) AS \"Credits / Issue\" FROM _tool_q_dev_user_report AS r CROSS JOIN (SELECT DISTINCT id FROM issues WHERE NOT resolution_date IS NULL AND type <> 'INCIDENT' AND $__timeFilter(resolution_date)) AS i WHERE $__timeFilter(r.date)",
+ "rawSql": "SELECT ROUND(CAST(CAST(SUM(r.credits_used) AS NUMERIC) / NULLIF(NULLIF(COUNT(DISTINCT i.id), 0), 0) AS DECIMAL), 1) AS \"Credits / Issue\" FROM _tool_kiro_user_report AS r CROSS JOIN (SELECT DISTINCT id FROM issues WHERE NOT resolution_date IS NULL AND type <> 'INCIDENT' AND $__timeFilter(resolution_date)) AS i WHERE $__timeFilter(r.date)",
"refId": "A"
}
],
@@ -261,7 +285,10 @@
"type": "row"
},
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"description": "Weekly cost per merged PR",
"fieldConfig": {
"defaults": {
@@ -313,10 +340,13 @@
},
"targets": [
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"format": "time_series",
"rawQuery": true,
- "rawSql": "WITH _credits AS (SELECT CAST(date AS DATE) - (EXTRACT(ISODOW FROM CAST(date AS DATE)) - 1) * INTERVAL '1 day' AS week_start, SUM(credits_used) AS credits FROM _tool_q_dev_user_report WHERE $__timeFilter(date) GROUP BY CAST(date AS DATE) - (EXTRACT(ISODOW FROM CAST(date AS DATE)) - 1) * INTERVAL '1 day'), _prs AS (SELECT CAST(merged_date AS DATE) - (EXTRACT(ISODOW FROM CAST(merged_date AS DATE)) - 1) * INTERVAL '1 day' AS week_start, COUNT(*) AS prs FROM pull_request [...]
+ "rawSql": "WITH _credits AS (SELECT CAST(date AS DATE) - (EXTRACT(ISODOW FROM CAST(date AS DATE)) - 1) * INTERVAL '1 day' AS week_start, SUM(credits_used) AS credits FROM _tool_kiro_user_report WHERE $__timeFilter(date) GROUP BY CAST(date AS DATE) - (EXTRACT(ISODOW FROM CAST(date AS DATE)) - 1) * INTERVAL '1 day'), _prs AS (SELECT CAST(merged_date AS DATE) - (EXTRACT(ISODOW FROM CAST(merged_date AS DATE)) - 1) * INTERVAL '1 day' AS week_start, COUNT(*) AS prs FROM pull_requests [...]
"refId": "A"
}
],
@@ -324,7 +354,10 @@
"type": "timeseries"
},
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"description": "Weekly cost per production deployment",
"fieldConfig": {
"defaults": {
@@ -376,10 +409,13 @@
},
"targets": [
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"format": "time_series",
"rawQuery": true,
- "rawSql": "WITH _credits AS (SELECT CAST(date AS DATE) - (EXTRACT(ISODOW FROM CAST(date AS DATE)) - 1) * INTERVAL '1 day' AS week_start, SUM(credits_used) AS credits FROM _tool_q_dev_user_report WHERE $__timeFilter(date) GROUP BY CAST(date AS DATE) - (EXTRACT(ISODOW FROM CAST(date AS DATE)) - 1) * INTERVAL '1 day'), _deploys AS (SELECT CAST(finished_date AS DATE) - (EXTRACT(ISODOW FROM CAST(finished_date AS DATE)) - 1) * INTERVAL '1 day' AS week_start, COUNT(DISTINCT cicd_deplo [...]
+ "rawSql": "WITH _credits AS (SELECT CAST(date AS DATE) - (EXTRACT(ISODOW FROM CAST(date AS DATE)) - 1) * INTERVAL '1 day' AS week_start, SUM(credits_used) AS credits FROM _tool_kiro_user_report WHERE $__timeFilter(date) GROUP BY CAST(date AS DATE) - (EXTRACT(ISODOW FROM CAST(date AS DATE)) - 1) * INTERVAL '1 day'), _deploys AS (SELECT CAST(finished_date AS DATE) - (EXTRACT(ISODOW FROM CAST(finished_date AS DATE)) - 1) * INTERVAL '1 day' AS week_start, COUNT(DISTINCT cicd_deploy [...]
"refId": "A"
}
],
@@ -387,7 +423,10 @@
"type": "timeseries"
},
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"description": "Weekly cost per resolved issue",
"fieldConfig": {
"defaults": {
@@ -439,10 +478,13 @@
},
"targets": [
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"format": "time_series",
"rawQuery": true,
- "rawSql": "WITH _credits AS (SELECT CAST(date AS DATE) - (EXTRACT(ISODOW FROM CAST(date AS DATE)) - 1) * INTERVAL '1 day' AS week_start, SUM(credits_used) AS credits FROM _tool_q_dev_user_report WHERE $__timeFilter(date) GROUP BY CAST(date AS DATE) - (EXTRACT(ISODOW FROM CAST(date AS DATE)) - 1) * INTERVAL '1 day'), _issues AS (SELECT CAST(resolution_date AS DATE) - (EXTRACT(ISODOW FROM CAST(resolution_date AS DATE)) - 1) * INTERVAL '1 day' AS week_start, COUNT(*) AS resolved F [...]
+ "rawSql": "WITH _credits AS (SELECT CAST(date AS DATE) - (EXTRACT(ISODOW FROM CAST(date AS DATE)) - 1) * INTERVAL '1 day' AS week_start, SUM(credits_used) AS credits FROM _tool_kiro_user_report WHERE $__timeFilter(date) GROUP BY CAST(date AS DATE) - (EXTRACT(ISODOW FROM CAST(date AS DATE)) - 1) * INTERVAL '1 day'), _issues AS (SELECT CAST(resolution_date AS DATE) - (EXTRACT(ISODOW FROM CAST(resolution_date AS DATE)) - 1) * INTERVAL '1 day' AS week_start, COUNT(*) AS resolved FR [...]
"refId": "A"
}
],
@@ -450,7 +492,10 @@
"type": "timeseries"
},
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"description": "Is cost efficiency improving over time?",
"fieldConfig": {
"defaults": {
@@ -502,10 +547,13 @@
},
"targets": [
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"format": "time_series",
"rawQuery": true,
- "rawSql": "SELECT CAST(date AS DATE) - (EXTRACT(ISODOW FROM CAST(date AS DATE)) - 1) * INTERVAL '1 day' AS time, SUM(credits_used) AS \"Credits\", SUM(total_messages) AS \"Messages\", SUM(chat_conversations) AS \"Conversations\" FROM _tool_q_dev_user_report WHERE $__timeFilter(date) GROUP BY CAST(date AS DATE) - (EXTRACT(ISODOW FROM CAST(date AS DATE)) - 1) * INTERVAL '1 day' ORDER BY time NULLS FIRST",
+ "rawSql": "SELECT CAST(date AS DATE) - (EXTRACT(ISODOW FROM CAST(date AS DATE)) - 1) * INTERVAL '1 day' AS time, SUM(credits_used) AS \"Credits\", SUM(total_messages) AS \"Messages\", SUM(chat_conversations) AS \"Conversations\" FROM _tool_kiro_user_report WHERE $__timeFilter(date) GROUP BY CAST(date AS DATE) - (EXTRACT(ISODOW FROM CAST(date AS DATE)) - 1) * INTERVAL '1 day' ORDER BY time NULLS FIRST",
"refId": "A"
}
],
@@ -517,7 +565,6 @@
"refresh": "5m",
"schemaVersion": 41,
"tags": [
- "q_dev",
"kiro",
"cost",
"efficiency"
@@ -534,4 +581,4 @@
"title": "AI Cost-Efficiency",
"uid": "ai_cost_efficiency-pg",
"version": 1
-}
\ No newline at end of file
+}
diff --git a/grafana/dashboards/postgresql/developer-productivity-hours.json b/grafana/dashboards/postgresql/developer-productivity-hours.json
index ba9848d1c..05fb09212 100644
--- a/grafana/dashboards/postgresql/developer-productivity-hours.json
+++ b/grafana/dashboards/postgresql/developer-productivity-hours.json
@@ -19,7 +19,10 @@
"links": [],
"panels": [
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"description": "Chat and completion events by hour of day",
"fieldConfig": {
"defaults": {
@@ -63,10 +66,13 @@
},
"targets": [
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"format": "table",
"rawQuery": true,
- "rawSql": "SELECT LPAD(CAST(hr AS TEXT), 2, '0') AS \"Hour\", SUM(chat) AS \"Chat Events\", SUM(comp) AS \"Completion Events\" FROM (SELECT EXTRACT(HOUR FROM timestamp) AS hr, COUNT(*) AS chat, 0 AS comp FROM _tool_q_dev_chat_log WHERE $__timeFilter(timestamp) GROUP BY EXTRACT(HOUR FROM timestamp) UNION ALL SELECT EXTRACT(HOUR FROM timestamp) AS hr, 0 AS chat, COUNT(*) AS comp FROM _tool_q_dev_completion_log WHERE $__timeFilter(timestamp) GROUP BY EXTRACT(HOUR FROM timestamp)) [...]
+ "rawSql": "SELECT LPAD(CAST(hr AS TEXT), 2, '0') AS \"Hour\", SUM(chat) AS \"Chat Events\", SUM(comp) AS \"Completion Events\" FROM (SELECT EXTRACT(HOUR FROM timestamp) AS hr, COUNT(*) AS chat, 0 AS comp FROM _tool_kiro_chat_log WHERE $__timeFilter(timestamp) GROUP BY EXTRACT(HOUR FROM timestamp) UNION ALL SELECT EXTRACT(HOUR FROM timestamp) AS hr, 0 AS chat, COUNT(*) AS comp FROM _tool_kiro_completion_log WHERE $__timeFilter(timestamp) GROUP BY EXTRACT(HOUR FROM timestamp)) AS [...]
"refId": "A"
}
],
@@ -74,7 +80,10 @@
"type": "barchart"
},
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"description": "Average prompt complexity and response richness by hour",
"fieldConfig": {
"defaults": {
@@ -122,10 +131,13 @@
},
"targets": [
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"format": "table",
"rawQuery": true,
- "rawSql": "SELECT LPAD(CAST(EXTRACT(HOUR FROM timestamp) AS TEXT), 2, '0') AS \"Hour\", ROUND(AVG(prompt_length)) AS \"Avg Prompt Length\", ROUND(AVG(response_length)) AS \"Avg Response Length\" FROM _tool_q_dev_chat_log WHERE $__timeFilter(timestamp) GROUP BY EXTRACT(HOUR FROM timestamp) ORDER BY EXTRACT(HOUR FROM timestamp) NULLS FIRST",
+ "rawSql": "SELECT LPAD(CAST(EXTRACT(HOUR FROM timestamp) AS TEXT), 2, '0') AS \"Hour\", ROUND(AVG(prompt_length)) AS \"Avg Prompt Length\", ROUND(AVG(response_length)) AS \"Avg Response Length\" FROM _tool_kiro_chat_log WHERE $__timeFilter(timestamp) GROUP BY EXTRACT(HOUR FROM timestamp) ORDER BY EXTRACT(HOUR FROM timestamp) NULLS FIRST",
"refId": "A"
}
],
@@ -133,7 +145,10 @@
"type": "barchart"
},
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"description": "Steering and spec mode usage concentration by hour",
"fieldConfig": {
"defaults": {
@@ -177,10 +192,13 @@
},
"targets": [
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"format": "table",
"rawQuery": true,
- "rawSql": "SELECT LPAD(CAST(EXTRACT(HOUR FROM timestamp) AS TEXT), 2, '0') AS \"Hour\", SUM(CASE WHEN has_steering = TRUE THEN 1 ELSE 0 END) AS \"Steering\", SUM(CASE WHEN is_spec_mode = TRUE THEN 1 ELSE 0 END) AS \"Spec Mode\", SUM(CASE WHEN has_steering = FALSE AND is_spec_mode = FALSE THEN 1 ELSE 0 END) AS \"Plain Chat\" FROM _tool_q_dev_chat_log WHERE $__timeFilter(timestamp) GROUP BY EXTRACT(HOUR FROM timestamp) ORDER BY EXTRACT(HOUR FROM timestamp) NULLS FIRST",
+ "rawSql": "SELECT LPAD(CAST(EXTRACT(HOUR FROM timestamp) AS TEXT), 2, '0') AS \"Hour\", SUM(CASE WHEN has_steering = TRUE THEN 1 ELSE 0 END) AS \"Steering\", SUM(CASE WHEN is_spec_mode = TRUE THEN 1 ELSE 0 END) AS \"Spec Mode\", SUM(CASE WHEN has_steering = FALSE AND is_spec_mode = FALSE THEN 1 ELSE 0 END) AS \"Plain Chat\" FROM _tool_kiro_chat_log WHERE $__timeFilter(timestamp) GROUP BY EXTRACT(HOUR FROM timestamp) ORDER BY EXTRACT(HOUR FROM timestamp) NULLS FIRST",
"refId": "A"
}
],
@@ -188,7 +206,10 @@
"type": "barchart"
},
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"description": "Day-of-week activity pattern",
"fieldConfig": {
"defaults": {
@@ -232,10 +253,13 @@
},
"targets": [
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"format": "table",
"rawQuery": true,
- "rawSql": "SELECT CASE EXTRACT(ISODOW FROM CAST(timestamp AS DATE)) WHEN 1 THEN 'Sun' WHEN 2 THEN 'Mon' WHEN 3 THEN 'Tue' WHEN 4 THEN 'Wed' WHEN 5 THEN 'Thu' WHEN 6 THEN 'Fri' WHEN 7 THEN 'Sat' END AS \"Day\", SUM(chat) AS \"Chat Events\", SUM(comp) AS \"Completions\" FROM (SELECT timestamp, COUNT(*) AS chat, 0 AS comp FROM _tool_q_dev_chat_log WHERE $__timeFilter(timestamp) GROUP BY timestamp UNION ALL SELECT timestamp, 0, COUNT(*) FROM _tool_q_dev_completion_log WHERE $__time [...]
+ "rawSql": "SELECT CASE EXTRACT(ISODOW FROM CAST(timestamp AS DATE)) WHEN 1 THEN 'Sun' WHEN 2 THEN 'Mon' WHEN 3 THEN 'Tue' WHEN 4 THEN 'Wed' WHEN 5 THEN 'Thu' WHEN 6 THEN 'Fri' WHEN 7 THEN 'Sat' END AS \"Day\", SUM(chat) AS \"Chat Events\", SUM(comp) AS \"Completions\" FROM (SELECT timestamp, COUNT(*) AS chat, 0 AS comp FROM _tool_kiro_chat_log WHERE $__timeFilter(timestamp) GROUP BY timestamp UNION ALL SELECT timestamp, 0, COUNT(*) FROM _tool_kiro_completion_log WHERE $__timeFi [...]
"refId": "A"
}
],
@@ -247,7 +271,6 @@
"refresh": "5m",
"schemaVersion": 41,
"tags": [
- "q_dev",
"kiro",
"productivity",
"hours"
@@ -264,4 +287,4 @@
"title": "Developer AI Productivity Hours",
"uid": "kiro_productivity_hours-pg",
"version": 1
-}
\ No newline at end of file
+}
diff --git a/grafana/dashboards/postgresql/kiro-credits-dora.json b/grafana/dashboards/postgresql/kiro-credits-dora.json
index 551529fd0..6f6ff79fc 100644
--- a/grafana/dashboards/postgresql/kiro-credits-dora.json
+++ b/grafana/dashboards/postgresql/kiro-credits-dora.json
@@ -37,7 +37,7 @@
"targetBlank": true,
"title": "Kiro Usage Dashboard",
"type": "link",
- "url": "/d/qdev_user_report"
+ "url": "/d/kiro_user_report"
}
],
"panels": [
@@ -79,7 +79,10 @@
"type": "row"
},
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"description": "Pearson correlation coefficient between weekly Kiro credits and PR cycle time",
"fieldConfig": {
"defaults": {
@@ -141,11 +144,14 @@
},
"targets": [
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"editorMode": "code",
"format": "table",
"rawQuery": true,
- "rawSql": "WITH _kiro_weekly AS (SELECT CAST(date AS DATE) - (EXTRACT(ISODOW FROM CAST(date AS DATE)) - 1) * INTERVAL '1 day' AS week_start, SUM(credits_used) AS weekly_credits FROM _tool_q_dev_user_report WHERE $__timeFilter(date) GROUP BY CAST(date AS DATE) - (EXTRACT(ISODOW FROM CAST(date AS DATE)) - 1) * INTERVAL '1 day'), _pr_weekly AS (SELECT CAST(pr_merged_date AS DATE) - (EXTRACT(ISODOW FROM CAST(pr_merged_date AS DATE)) - 1) * INTERVAL '1 day' AS week_start, CAST(AVG(p [...]
+ "rawSql": "WITH _kiro_weekly AS (SELECT CAST(date AS DATE) - (EXTRACT(ISODOW FROM CAST(date AS DATE)) - 1) * INTERVAL '1 day' AS week_start, SUM(credits_used) AS weekly_credits FROM _tool_kiro_user_report WHERE $__timeFilter(date) GROUP BY CAST(date AS DATE) - (EXTRACT(ISODOW FROM CAST(date AS DATE)) - 1) * INTERVAL '1 day'), _pr_weekly AS (SELECT CAST(pr_merged_date AS DATE) - (EXTRACT(ISODOW FROM CAST(pr_merged_date AS DATE)) - 1) * INTERVAL '1 day' AS week_start, CAST(AVG(pr [...]
"refId": "A"
}
],
@@ -153,7 +159,10 @@
"type": "stat"
},
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"description": "Total Kiro credits consumed in period",
"fieldConfig": {
"defaults": {
@@ -194,10 +203,13 @@
},
"targets": [
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"format": "table",
"rawQuery": true,
- "rawSql": "SELECT SUM(credits_used) AS \"Credits Used\" FROM _tool_q_dev_user_report WHERE $__timeFilter(date)",
+ "rawSql": "SELECT SUM(credits_used) AS \"Credits Used\" FROM _tool_kiro_user_report WHERE $__timeFilter(date)",
"refId": "A"
}
],
@@ -205,7 +217,10 @@
"type": "stat"
},
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"description": "Median PR cycle time in hours",
"fieldConfig": {
"defaults": {
@@ -247,7 +262,10 @@
},
"targets": [
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"format": "table",
"rawQuery": true,
"rawSql": "WITH _ranked AS (SELECT CAST(pr_cycle_time AS NUMERIC) / NULLIF(60.0, 0) AS ct, PERCENT_RANK() OVER (ORDER BY pr_cycle_time NULLS FIRST) AS prank FROM project_pr_metrics WHERE NOT pr_merged_date IS NULL AND NOT pr_cycle_time IS NULL AND $__timeFilter(pr_merged_date)) SELECT ROUND(MAX(ct), 1) AS \"Median Cycle Time\" FROM _ranked WHERE prank <= 0.5",
@@ -258,7 +276,10 @@
"type": "stat"
},
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"description": "Cycle time comparison: weeks with above-median vs below-median AI credits usage",
"fieldConfig": {
"defaults": {
@@ -298,10 +319,13 @@
},
"targets": [
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"format": "table",
"rawQuery": true,
- "rawSql": "WITH _kiro_weekly AS (SELECT CAST(date AS DATE) - (EXTRACT(ISODOW FROM CAST(date AS DATE)) - 1) * INTERVAL '1 day' AS week_start, SUM(credits_used) AS weekly_credits FROM _tool_q_dev_user_report WHERE $__timeFilter(date) GROUP BY CAST(date AS DATE) - (EXTRACT(ISODOW FROM CAST(date AS DATE)) - 1) * INTERVAL '1 day'), _pr_weekly AS (SELECT CAST(pr_merged_date AS DATE) - (EXTRACT(ISODOW FROM CAST(pr_merged_date AS DATE)) - 1) * INTERVAL '1 day' AS week_start, CAST(AVG(p [...]
+ "rawSql": "WITH _kiro_weekly AS (SELECT CAST(date AS DATE) - (EXTRACT(ISODOW FROM CAST(date AS DATE)) - 1) * INTERVAL '1 day' AS week_start, SUM(credits_used) AS weekly_credits FROM _tool_kiro_user_report WHERE $__timeFilter(date) GROUP BY CAST(date AS DATE) - (EXTRACT(ISODOW FROM CAST(date AS DATE)) - 1) * INTERVAL '1 day'), _pr_weekly AS (SELECT CAST(pr_merged_date AS DATE) - (EXTRACT(ISODOW FROM CAST(pr_merged_date AS DATE)) - 1) * INTERVAL '1 day' AS week_start, CAST(AVG(pr [...]
"refId": "A"
}
],
@@ -322,7 +346,10 @@
"type": "row"
},
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"description": "Weekly Kiro credits consumed",
"fieldConfig": {
"defaults": {
@@ -374,10 +401,13 @@
},
"targets": [
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"format": "time_series",
"rawQuery": true,
- "rawSql": "SELECT CAST(date AS DATE) - (EXTRACT(ISODOW FROM CAST(date AS DATE)) - 1) * INTERVAL '1 day' AS time, SUM(credits_used) AS \"Credits Used\", COUNT(DISTINCT user_id) AS \"Active Users\" FROM _tool_q_dev_user_report WHERE $__timeFilter(date) GROUP BY CAST(date AS DATE) - (EXTRACT(ISODOW FROM CAST(date AS DATE)) - 1) * INTERVAL '1 day' ORDER BY time NULLS FIRST",
+ "rawSql": "SELECT CAST(date AS DATE) - (EXTRACT(ISODOW FROM CAST(date AS DATE)) - 1) * INTERVAL '1 day' AS time, SUM(credits_used) AS \"Credits Used\", COUNT(DISTINCT user_id) AS \"Active Users\" FROM _tool_kiro_user_report WHERE $__timeFilter(date) GROUP BY CAST(date AS DATE) - (EXTRACT(ISODOW FROM CAST(date AS DATE)) - 1) * INTERVAL '1 day' ORDER BY time NULLS FIRST",
"refId": "A"
}
],
@@ -385,7 +415,10 @@
"type": "timeseries"
},
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"description": "Weekly average PR cycle time in hours",
"fieldConfig": {
"defaults": {
@@ -437,7 +470,10 @@
},
"targets": [
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"format": "time_series",
"rawQuery": true,
"rawSql": "SELECT CAST(pr_merged_date AS DATE) - (EXTRACT(ISODOW FROM CAST(pr_merged_date AS DATE)) - 1) * INTERVAL '1 day' AS time, ROUND(CAST(CAST(AVG(pr_cycle_time) AS NUMERIC) / NULLIF(60.0, 0) AS DECIMAL), 1) AS \"Avg Cycle Time (hrs)\", COUNT(*) AS \"PRs Merged\" FROM project_pr_metrics WHERE NOT pr_merged_date IS NULL AND NOT pr_cycle_time IS NULL AND $__timeFilter(pr_merged_date) GROUP BY CAST(pr_merged_date AS DATE) - (EXTRACT(ISODOW FROM CAST(pr_merged_date AS DATE)) [...]
@@ -461,7 +497,10 @@
"type": "row"
},
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"description": "Pearson correlation between weekly credits and deployment count",
"fieldConfig": {
"defaults": {
@@ -512,10 +551,13 @@
},
"targets": [
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"format": "table",
"rawQuery": true,
- "rawSql": "WITH _kiro_weekly AS (SELECT CAST(date AS DATE) - (EXTRACT(ISODOW FROM CAST(date AS DATE)) - 1) * INTERVAL '1 day' AS week_start, SUM(credits_used) AS weekly_credits FROM _tool_q_dev_user_report WHERE $__timeFilter(date) GROUP BY CAST(date AS DATE) - (EXTRACT(ISODOW FROM CAST(date AS DATE)) - 1) * INTERVAL '1 day'), _deploy_weekly AS (SELECT CAST(cdc.finished_date AS DATE) - (EXTRACT(ISODOW FROM CAST(cdc.finished_date AS DATE)) - 1) * INTERVAL '1 day' AS week_start, [...]
+ "rawSql": "WITH _kiro_weekly AS (SELECT CAST(date AS DATE) - (EXTRACT(ISODOW FROM CAST(date AS DATE)) - 1) * INTERVAL '1 day' AS week_start, SUM(credits_used) AS weekly_credits FROM _tool_kiro_user_report WHERE $__timeFilter(date) GROUP BY CAST(date AS DATE) - (EXTRACT(ISODOW FROM CAST(date AS DATE)) - 1) * INTERVAL '1 day'), _deploy_weekly AS (SELECT CAST(cdc.finished_date AS DATE) - (EXTRACT(ISODOW FROM CAST(cdc.finished_date AS DATE)) - 1) * INTERVAL '1 day' AS week_start, C [...]
"refId": "A"
}
],
@@ -523,7 +565,10 @@
"type": "stat"
},
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"description": "Weekly credits overlaid with deployment count",
"fieldConfig": {
"defaults": {
@@ -575,10 +620,13 @@
},
"targets": [
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"format": "time_series",
"rawQuery": true,
- "rawSql": "SELECT time, SUM(credits) AS \"Credits Used\", SUM(deploys) AS \"Deployments\" FROM (SELECT CAST(date AS DATE) - (EXTRACT(ISODOW FROM CAST(date AS DATE)) - 1) * INTERVAL '1 day' AS time, SUM(credits_used) AS credits, 0 AS deploys FROM _tool_q_dev_user_report WHERE $__timeFilter(date) GROUP BY CAST(date AS DATE) - (EXTRACT(ISODOW FROM CAST(date AS DATE)) - 1) * INTERVAL '1 day' UNION ALL SELECT CAST(cdc.finished_date AS DATE) - (EXTRACT(ISODOW FROM CAST(cdc.finished_d [...]
+ "rawSql": "SELECT time, SUM(credits) AS \"Credits Used\", SUM(deploys) AS \"Deployments\" FROM (SELECT CAST(date AS DATE) - (EXTRACT(ISODOW FROM CAST(date AS DATE)) - 1) * INTERVAL '1 day' AS time, SUM(credits_used) AS credits, 0 AS deploys FROM _tool_kiro_user_report WHERE $__timeFilter(date) GROUP BY CAST(date AS DATE) - (EXTRACT(ISODOW FROM CAST(date AS DATE)) - 1) * INTERVAL '1 day' UNION ALL SELECT CAST(cdc.finished_date AS DATE) - (EXTRACT(ISODOW FROM CAST(cdc.finished_da [...]
"refId": "A"
}
],
@@ -599,7 +647,10 @@
"type": "row"
},
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"description": "Change failure rate: % of deployments that caused incidents",
"fieldConfig": {
"defaults": {
@@ -651,10 +702,13 @@
},
"targets": [
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"format": "time_series",
"rawQuery": true,
- "rawSql": "SELECT time, SUM(credits) AS \"Credits Used\", SUM(cfr) AS \"Change Failure Rate\" FROM (SELECT CAST(date AS DATE) - (EXTRACT(ISODOW FROM CAST(date AS DATE)) - 1) * INTERVAL '1 day' AS time, SUM(credits_used) AS credits, 0 AS cfr FROM _tool_q_dev_user_report WHERE $__timeFilter(date) GROUP BY CAST(date AS DATE) - (EXTRACT(ISODOW FROM CAST(date AS DATE)) - 1) * INTERVAL '1 day' UNION ALL SELECT CAST(d.deployment_finished_date AS DATE) - (EXTRACT(ISODOW FROM CAST(d.dep [...]
+ "rawSql": "SELECT time, SUM(credits) AS \"Credits Used\", SUM(cfr) AS \"Change Failure Rate\" FROM (SELECT CAST(date AS DATE) - (EXTRACT(ISODOW FROM CAST(date AS DATE)) - 1) * INTERVAL '1 day' AS time, SUM(credits_used) AS credits, 0 AS cfr FROM _tool_kiro_user_report WHERE $__timeFilter(date) GROUP BY CAST(date AS DATE) - (EXTRACT(ISODOW FROM CAST(date AS DATE)) - 1) * INTERVAL '1 day' UNION ALL SELECT CAST(d.deployment_finished_date AS DATE) - (EXTRACT(ISODOW FROM CAST(d.depl [...]
"refId": "A"
}
],
@@ -666,9 +720,8 @@
"refresh": "5m",
"schemaVersion": 41,
"tags": [
- "q_dev",
- "dora",
"kiro",
+ "dora",
"correlation"
],
"templating": {
@@ -683,7 +736,10 @@
"$__all"
]
},
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"definition": "SELECT DISTINCT name FROM projects",
"hide": 0,
"includeAll": true,
@@ -706,4 +762,4 @@
"title": "Kiro Credits + DORA Correlation",
"uid": "kiro_credits_dora-pg",
"version": 1
-}
\ No newline at end of file
+}
diff --git a/grafana/dashboards/postgresql/language-ai-heatmap.json b/grafana/dashboards/postgresql/language-ai-heatmap.json
index 63aa23d65..75b45818b 100644
--- a/grafana/dashboards/postgresql/language-ai-heatmap.json
+++ b/grafana/dashboards/postgresql/language-ai-heatmap.json
@@ -19,7 +19,10 @@
"links": [],
"panels": [
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"description": "Completion requests, avg context size, and completion rate per language",
"fieldConfig": {
"defaults": {
@@ -63,10 +66,13 @@
},
"targets": [
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"format": "table",
"rawQuery": true,
- "rawSql": "SELECT CASE WHEN file_extension = '' THEN '(unknown)' ELSE file_extension END AS \"Language\", COUNT(*) AS \"Requests\", ROUND(CAST(AVG(completions_count) AS DECIMAL), 2) AS \"Avg Completions\", ROUND(AVG(left_context_length)) AS \"Avg Left Context\", ROUND(AVG(right_context_length)) AS \"Avg Right Context\", ROUND(AVG(left_context_length + right_context_length)) AS \"Avg Total Context\", COUNT(DISTINCT user_id) AS \"Users\" FROM _tool_q_dev_completion_log WHERE $__t [...]
+ "rawSql": "SELECT CASE WHEN file_extension = '' THEN '(unknown)' ELSE file_extension END AS \"Language\", COUNT(*) AS \"Requests\", ROUND(CAST(AVG(completions_count) AS DECIMAL), 2) AS \"Avg Completions\", ROUND(AVG(left_context_length)) AS \"Avg Left Context\", ROUND(AVG(right_context_length)) AS \"Avg Right Context\", ROUND(AVG(left_context_length + right_context_length)) AS \"Avg Total Context\", COUNT(DISTINCT user_id) AS \"Users\" FROM _tool_kiro_completion_log WHERE $__ti [...]
"refId": "A"
}
],
@@ -74,7 +80,10 @@
"type": "table"
},
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"description": "Daily completion requests by language",
"fieldConfig": {
"defaults": {
@@ -118,10 +127,13 @@
},
"targets": [
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"format": "time_series",
"rawQuery": true,
- "rawSql": "SELECT CAST(timestamp AS DATE) AS time, CASE WHEN file_extension = '' THEN '(unknown)' ELSE file_extension END AS metric, COUNT(*) AS value FROM _tool_q_dev_completion_log WHERE $__timeFilter(timestamp) GROUP BY CAST(timestamp AS DATE), \"file_extension\" ORDER BY time NULLS FIRST",
+ "rawSql": "SELECT CAST(timestamp AS DATE) AS time, CASE WHEN file_extension = '' THEN '(unknown)' ELSE file_extension END AS metric, COUNT(*) AS value FROM _tool_kiro_completion_log WHERE $__timeFilter(timestamp) GROUP BY CAST(timestamp AS DATE), \"file_extension\" ORDER BY time NULLS FIRST",
"refId": "A"
}
],
@@ -129,8 +141,11 @@
"type": "timeseries"
},
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
- "description": "Which file types are most active during chat sessions",
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
+ "description": "Chat logs do not contain active file types. This uses completion-log file extensions and returned lines.",
"fieldConfig": {
"defaults": {
"color": {
@@ -183,18 +198,24 @@
},
"targets": [
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"format": "table",
"rawQuery": true,
- "rawSql": "SELECT CASE WHEN active_file_extension = '' OR active_file_extension IS NULL THEN '(no file)' ELSE active_file_extension END AS \"File Type\", COUNT(*) AS \"Chat Events\" FROM _tool_q_dev_chat_log WHERE $__timeFilter(timestamp) GROUP BY \"active_file_extension\" ORDER BY COUNT(*) DESC NULLS LAST LIMIT 10",
+ "rawSql": "SELECT CASE WHEN file_extension = '' THEN '(unknown)' ELSE file_extension END AS \"File Type\", SUM(returned_line_count) AS \"Returned Lines\" FROM _tool_kiro_completion_log WHERE $__timeFilter(timestamp) GROUP BY file_extension ORDER BY SUM(returned_line_count) DESC",
"refId": "A"
}
],
- "title": "Active File Types During Chat",
+ "title": "Returned Lines by File Type",
"type": "piechart"
},
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"description": "Context size trends for top languages",
"fieldConfig": {
"defaults": {
@@ -241,10 +262,13 @@
},
"targets": [
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"format": "time_series",
"rawQuery": true,
- "rawSql": "SELECT CAST(timestamp AS DATE) AS time, file_extension AS metric, ROUND(AVG(left_context_length + right_context_length)) AS value FROM _tool_q_dev_completion_log WHERE $__timeFilter(timestamp) AND file_extension IN (SELECT file_extension FROM _tool_q_dev_completion_log GROUP BY \"file_extension\" ORDER BY COUNT(*) DESC NULLS LAST LIMIT 5) GROUP BY CAST(timestamp AS DATE), \"file_extension\" ORDER BY time NULLS FIRST",
+ "rawSql": "SELECT CAST(timestamp AS DATE) AS time, file_extension AS metric, ROUND(AVG(left_context_length + right_context_length)) AS value FROM _tool_kiro_completion_log WHERE $__timeFilter(timestamp) AND file_extension IN (SELECT file_extension FROM _tool_kiro_completion_log GROUP BY \"file_extension\" ORDER BY COUNT(*) DESC NULLS LAST LIMIT 5) GROUP BY CAST(timestamp AS DATE), \"file_extension\" ORDER BY time NULLS FIRST",
"refId": "A"
}
],
@@ -256,7 +280,6 @@
"refresh": "5m",
"schemaVersion": 41,
"tags": [
- "q_dev",
"kiro",
"language",
"completions"
@@ -273,4 +296,4 @@
"title": "Kiro Language AI Heatmap",
"uid": "kiro_language_heatmap-pg",
"version": 1
-}
\ No newline at end of file
+}
diff --git a/grafana/dashboards/postgresql/multi-ai-comparison.json b/grafana/dashboards/postgresql/multi-ai-comparison.json
index bca478812..3787072c1 100644
--- a/grafana/dashboards/postgresql/multi-ai-comparison.json
+++ b/grafana/dashboards/postgresql/multi-ai-comparison.json
@@ -26,7 +26,7 @@
"targetBlank": true,
"title": "Kiro Usage",
"type": "link",
- "url": "/d/qdev_user_report"
+ "url": "/d/kiro_user_report"
},
{
"asDropdown": false,
@@ -59,7 +59,7 @@
"showLineNumbers": false,
"showMiniMap": false
},
- "content": "## Multi-AI Tool Comparison: Copilot vs Kiro\nCompare GitHub Copilot and Kiro (Amazon Q Developer) adoption and usage side by side.\n\n**Note:** Copilot metrics come from `_tool_copilot_enterprise_daily_metrics` (enterprise-level aggregates). Kiro metrics come from `_tool_q_dev_user_report` and `_tool_q_dev_user_data`. Select the Copilot connection and scope using the dropdowns above.",
+ "content": "## Multi-AI Tool Comparison: Copilot vs Kiro\nCompare GitHub Copilot and Kiro adoption and activity side by side.\n\n**Semantic boundary:** Copilot exports code-generation and acceptance events. Kiro exports usage reports and completion responses, but no acceptance event. Returned Kiro lines and Copilot LOC added are displayed with explicit labels and must not be treated as equivalent productivity measures.",
"mode": "markdown"
},
"title": "About",
@@ -79,7 +79,10 @@
"type": "row"
},
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"description": "Weekly active users for both tools",
"fieldConfig": {
"defaults": {
@@ -131,14 +134,20 @@
},
"targets": [
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"format": "time_series",
"rawQuery": true,
- "rawSql": "SELECT CAST(date AS DATE) - (EXTRACT(ISODOW FROM CAST(date AS DATE)) - 1) * INTERVAL '1 day' AS time, COUNT(DISTINCT user_id) AS \"Kiro Active Users\" FROM _tool_q_dev_user_report WHERE $__timeFilter(date) GROUP BY CAST(date AS DATE) - (EXTRACT(ISODOW FROM CAST(date AS DATE)) - 1) * INTERVAL '1 day' ORDER BY time NULLS FIRST",
+ "rawSql": "SELECT CAST(date AS DATE) - (EXTRACT(ISODOW FROM CAST(date AS DATE)) - 1) * INTERVAL '1 day' AS time, COUNT(DISTINCT user_id) AS \"Kiro Active Users\" FROM _tool_kiro_user_report WHERE $__timeFilter(date) GROUP BY CAST(date AS DATE) - (EXTRACT(ISODOW FROM CAST(date AS DATE)) - 1) * INTERVAL '1 day' ORDER BY time NULLS FIRST",
"refId": "A"
},
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"format": "time_series",
"rawQuery": true,
"rawSql": "SELECT CAST(day AS DATE) - (EXTRACT(ISODOW FROM CAST(day AS DATE)) - 1) * INTERVAL '1 day' AS time, MAX(daily_active_users) AS \"Copilot Active Users\" FROM _tool_copilot_enterprise_daily_metrics WHERE ('${copilot_connection_id}' = '' OR connection_id::text = '${copilot_connection_id}') AND scope_id = '${copilot_scope_id}' AND $__timeFilter(day) GROUP BY CAST(day AS DATE) - (EXTRACT(ISODOW FROM CAST(day AS DATE)) - 1) * INTERVAL '1 day' ORDER BY time NULLS FIRST",
@@ -158,12 +167,15 @@
},
"id": 10,
"panels": [],
- "title": "Code Generation",
+ "title": "Assistant Activity",
"type": "row"
},
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
- "description": "Weekly code generation and acceptance events",
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
+ "description": "Kiro completion requests and requests returning suggestions. Returned does not mean accepted.",
"fieldConfig": {
"defaults": {
"color": {
@@ -214,18 +226,24 @@
},
"targets": [
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"format": "time_series",
"rawQuery": true,
- "rawSql": "SELECT CAST(date AS DATE) - (EXTRACT(ISODOW FROM CAST(date AS DATE)) - 1) * INTERVAL '1 day' AS time, SUM(inline_suggestions_count) AS \"Kiro: Suggestions\", SUM(inline_acceptance_count) AS \"Kiro: Accepted\" FROM _tool_q_dev_user_data WHERE $__timeFilter(date) GROUP BY CAST(date AS DATE) - (EXTRACT(ISODOW FROM CAST(date AS DATE)) - 1) * INTERVAL '1 day' ORDER BY time NULLS FIRST",
+ "rawSql": "SELECT CAST(timestamp AS DATE) - (EXTRACT(ISODOW FROM CAST(timestamp AS DATE)) - 1) * INTERVAL '1 day' AS time, COUNT(*) AS \"Kiro: Completion Requests\", SUM(CASE WHEN completions_count > 0 THEN 1 ELSE 0 END) AS \"Kiro: Requests with Results\" FROM _tool_kiro_completion_log WHERE $__timeFilter(timestamp) GROUP BY CAST(timestamp AS DATE) - (EXTRACT(ISODOW FROM CAST(timestamp AS DATE)) - 1) * INTERVAL '1 day' ORDER BY time",
"refId": "A"
}
],
- "title": "Kiro: Code Suggestions & Acceptance",
+ "title": "Kiro Completion Requests & Results",
"type": "timeseries"
},
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"description": "Weekly Copilot code generation and acceptance events",
"fieldConfig": {
"defaults": {
@@ -277,7 +295,10 @@
},
"targets": [
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"format": "time_series",
"rawQuery": true,
"rawSql": "SELECT CAST(day AS DATE) - (EXTRACT(ISODOW FROM CAST(day AS DATE)) - 1) * INTERVAL '1 day' AS time, SUM(code_generation_activity_count) AS \"Copilot: Suggestions\", SUM(code_acceptance_activity_count) AS \"Copilot: Accepted\" FROM _tool_copilot_enterprise_daily_metrics WHERE ('${copilot_connection_id}' = '' OR connection_id::text = '${copilot_connection_id}') AND scope_id = '${copilot_scope_id}' AND $__timeFilter(day) GROUP BY CAST(day AS DATE) - (EXTRACT(ISODOW FROM [...]
@@ -297,12 +318,15 @@
},
"id": 20,
"panels": [],
- "title": "Lines of Code & Acceptance Rate",
+ "title": "Returned Lines & Acceptance Availability",
"type": "row"
},
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
- "description": "Weekly AI-generated lines of code accepted",
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
+ "description": "Different semantics: Kiro counts lines returned to the IDE; Copilot counts LOC added. Do not interpret as an acceptance comparison.",
"fieldConfig": {
"defaults": {
"color": {
@@ -353,19 +377,25 @@
},
"targets": [
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"format": "time_series",
"rawQuery": true,
- "rawSql": "SELECT time, SUM(kiro_loc) AS \"Kiro LOC Accepted\", SUM(copilot_loc) AS \"Copilot LOC Added\" FROM (SELECT CAST(date AS DATE) - (EXTRACT(ISODOW FROM CAST(date AS DATE)) - 1) * INTERVAL '1 day' AS time, SUM(inline_ai_code_lines + chat_ai_code_lines) AS kiro_loc, 0 AS copilot_loc FROM _tool_q_dev_user_data WHERE $__timeFilter(date) GROUP BY CAST(date AS DATE) - (EXTRACT(ISODOW FROM CAST(date AS DATE)) - 1) * INTERVAL '1 day' UNION ALL SELECT CAST(day AS DATE) - (EXTRA [...]
+ "rawSql": "SELECT time, SUM(kiro_lines) AS \"Kiro Returned Lines\", SUM(copilot_loc) AS \"Copilot LOC Added\" FROM (SELECT CAST(timestamp AS DATE) - (EXTRACT(ISODOW FROM CAST(timestamp AS DATE)) - 1) * INTERVAL '1 day' AS time, SUM(returned_line_count) AS kiro_lines, 0 AS copilot_loc FROM _tool_kiro_completion_log WHERE $__timeFilter(timestamp) GROUP BY CAST(timestamp AS DATE) - (EXTRACT(ISODOW FROM CAST(timestamp AS DATE)) - 1) * INTERVAL '1 day' UNION ALL SELECT CAST(day AS D [...]
"refId": "A"
}
],
- "title": "LOC Accepted: Kiro vs Copilot",
+ "title": "Kiro Returned Lines vs Copilot LOC Added",
"type": "timeseries"
},
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
- "description": "Overall acceptance rates for both tools",
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
+ "description": "Kiro exports no suggestion-acceptance event, so its value is NULL. Copilot acceptance remains available.",
"fieldConfig": {
"defaults": {
"color": {
@@ -404,14 +434,17 @@
},
"targets": [
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"format": "table",
"rawQuery": true,
- "rawSql": "SELECT 'Kiro' AS \"Tool\", ROUND(CAST(SUM(inline_acceptance_count) * 100.0 AS NUMERIC) / NULLIF(NULLIF(SUM(inline_suggestions_count), 0), 0), 1) AS \"Acceptance Rate\" FROM _tool_q_dev_user_data WHERE $__timeFilter(date) UNION ALL SELECT 'Copilot' AS \"Tool\", ROUND(CAST(SUM(code_acceptance_activity_count) * 100.0 AS NUMERIC) / NULLIF(NULLIF(SUM(code_generation_activity_count), 0), 0), 1) FROM _tool_copilot_enterprise_daily_metrics WHERE ('${copilot_connection_id}' = [...]
+ "rawSql": "SELECT 'Kiro (not exported)' AS \"Tool\", CAST(NULL AS NUMERIC) AS \"Acceptance Rate\" UNION ALL SELECT 'Copilot' AS \"Tool\", ROUND(CAST(SUM(code_acceptance_activity_count) * 100.0 AS NUMERIC) / NULLIF(SUM(code_generation_activity_count), 0), 1) AS \"Acceptance Rate\" FROM _tool_copilot_enterprise_daily_metrics WHERE ('${copilot_connection_id}' = '' OR connection_id::text = '${copilot_connection_id}') AND scope_id = '${copilot_scope_id}' AND $__timeFilter(day)",
"refId": "A"
}
],
- "title": "Acceptance Rate Comparison",
+ "title": "Acceptance Rate Availability",
"type": "bargauge"
}
],
@@ -419,16 +452,18 @@
"refresh": "5m",
"schemaVersion": 41,
"tags": [
- "q_dev",
- "copilot",
"kiro",
+ "copilot",
"comparison"
],
"templating": {
"list": [
{
"current": {},
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"definition": "SELECT DISTINCT connection_id FROM _tool_copilot_scopes ORDER BY connection_id DESC NULLS LAST",
"hide": 0,
"label": "Copilot Connection",
@@ -440,7 +475,10 @@
},
{
"current": {},
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"definition": "SELECT DISTINCT id FROM _tool_copilot_scopes WHERE connection_id = CAST('${copilot_connection_id}' AS BIGINT)",
"hide": 0,
"label": "Copilot Scope",
@@ -461,4 +499,4 @@
"title": "Multi-AI Tool Comparison",
"uid": "multi_ai_comparison-pg",
"version": 1
-}
\ No newline at end of file
+}
diff --git a/grafana/dashboards/postgresql/steering-adoption-tracker.json b/grafana/dashboards/postgresql/steering-adoption-tracker.json
index f332a3144..314032784 100644
--- a/grafana/dashboards/postgresql/steering-adoption-tracker.json
+++ b/grafana/dashboards/postgresql/steering-adoption-tracker.json
@@ -19,7 +19,10 @@
"links": [],
"panels": [
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"fieldConfig": {
"defaults": {
"color": {
@@ -59,10 +62,13 @@
},
"targets": [
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"format": "table",
"rawQuery": true,
- "rawSql": "SELECT ROUND(CAST(CAST(COUNT(DISTINCT CASE WHEN has_steering = TRUE THEN user_id END) * 100.0 AS NUMERIC) / NULLIF(NULLIF(COUNT(DISTINCT user_id), 0), 0) AS DECIMAL), 0) AS \"value\" FROM _tool_q_dev_chat_log WHERE $__timeFilter(timestamp)",
+ "rawSql": "SELECT ROUND(CAST(CAST(COUNT(DISTINCT CASE WHEN has_steering = TRUE THEN user_id END) * 100.0 AS NUMERIC) / NULLIF(NULLIF(COUNT(DISTINCT user_id), 0), 0) AS DECIMAL), 0) AS \"value\" FROM _tool_kiro_chat_log WHERE $__timeFilter(timestamp)",
"refId": "A"
}
],
@@ -70,7 +76,10 @@
"type": "stat"
},
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"fieldConfig": {
"defaults": {
"color": {
@@ -110,10 +119,13 @@
},
"targets": [
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"format": "table",
"rawQuery": true,
- "rawSql": "SELECT ROUND(CAST(CAST(COUNT(DISTINCT CASE WHEN is_spec_mode = TRUE THEN user_id END) * 100.0 AS NUMERIC) / NULLIF(NULLIF(COUNT(DISTINCT user_id), 0), 0) AS DECIMAL), 0) AS \"value\" FROM _tool_q_dev_chat_log WHERE $__timeFilter(timestamp)",
+ "rawSql": "SELECT ROUND(CAST(CAST(COUNT(DISTINCT CASE WHEN is_spec_mode = TRUE THEN user_id END) * 100.0 AS NUMERIC) / NULLIF(NULLIF(COUNT(DISTINCT user_id), 0), 0) AS DECIMAL), 0) AS \"value\" FROM _tool_kiro_chat_log WHERE $__timeFilter(timestamp)",
"refId": "A"
}
],
@@ -121,7 +133,10 @@
"type": "stat"
},
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"fieldConfig": {
"defaults": {
"color": {
@@ -161,10 +176,13 @@
},
"targets": [
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"format": "table",
"rawQuery": true,
- "rawSql": "SELECT ROUND(CAST(CAST(SUM(CASE WHEN has_steering = TRUE THEN 1 ELSE 0 END) * 100.0 AS NUMERIC) / NULLIF(COUNT(*), 0) AS DECIMAL), 1) AS \"value\" FROM _tool_q_dev_chat_log WHERE $__timeFilter(timestamp)",
+ "rawSql": "SELECT ROUND(CAST(CAST(SUM(CASE WHEN has_steering = TRUE THEN 1 ELSE 0 END) * 100.0 AS NUMERIC) / NULLIF(COUNT(*), 0) AS DECIMAL), 1) AS \"value\" FROM _tool_kiro_chat_log WHERE $__timeFilter(timestamp)",
"refId": "A"
}
],
@@ -172,7 +190,10 @@
"type": "stat"
},
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"description": "Weekly trend of steering and spec mode adoption rate",
"fieldConfig": {
"defaults": {
@@ -220,10 +241,13 @@
},
"targets": [
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"format": "time_series",
"rawQuery": true,
- "rawSql": "SELECT CAST(timestamp AS DATE) - (EXTRACT(ISODOW FROM CAST(timestamp AS DATE)) - 1) * INTERVAL '1 day' AS time, CAST(SUM(CASE WHEN has_steering = TRUE THEN 1 ELSE 0 END) AS NUMERIC) / NULLIF(COUNT(*), 0) AS \"Steering Rate\", CAST(SUM(CASE WHEN is_spec_mode = TRUE THEN 1 ELSE 0 END) AS NUMERIC) / NULLIF(COUNT(*), 0) AS \"Spec Mode Rate\" FROM _tool_q_dev_chat_log WHERE $__timeFilter(timestamp) GROUP BY CAST(timestamp AS DATE) - (EXTRACT(ISODOW FROM CAST(timestamp AS [...]
+ "rawSql": "SELECT CAST(timestamp AS DATE) - (EXTRACT(ISODOW FROM CAST(timestamp AS DATE)) - 1) * INTERVAL '1 day' AS time, CAST(SUM(CASE WHEN has_steering = TRUE THEN 1 ELSE 0 END) AS NUMERIC) / NULLIF(COUNT(*), 0) AS \"Steering Rate\", CAST(SUM(CASE WHEN is_spec_mode = TRUE THEN 1 ELSE 0 END) AS NUMERIC) / NULLIF(COUNT(*), 0) AS \"Spec Mode Rate\" FROM _tool_kiro_chat_log WHERE $__timeFilter(timestamp) GROUP BY CAST(timestamp AS DATE) - (EXTRACT(ISODOW FROM CAST(timestamp AS D [...]
"refId": "A"
}
],
@@ -231,7 +255,10 @@
"type": "timeseries"
},
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"description": "Compare prompt and response quality between steering and non-steering sessions",
"fieldConfig": {
"defaults": {
@@ -269,10 +296,13 @@
},
"targets": [
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"format": "table",
"rawQuery": true,
- "rawSql": "SELECT 'With Steering' AS \"Mode\", ROUND(AVG(prompt_length)) AS \"Avg Prompt\", ROUND(AVG(response_length)) AS \"Avg Response\" FROM _tool_q_dev_chat_log WHERE has_steering = TRUE AND $__timeFilter(timestamp) UNION ALL SELECT 'Without Steering', ROUND(AVG(prompt_length)), ROUND(AVG(response_length)) FROM _tool_q_dev_chat_log WHERE has_steering = FALSE AND $__timeFilter(timestamp)",
+ "rawSql": "SELECT 'With Steering' AS \"Mode\", ROUND(AVG(prompt_length)) AS \"Avg Prompt\", ROUND(AVG(response_length)) AS \"Avg Response\" FROM _tool_kiro_chat_log WHERE has_steering = TRUE AND $__timeFilter(timestamp) UNION ALL SELECT 'Without Steering', ROUND(AVG(prompt_length)), ROUND(AVG(response_length)) FROM _tool_kiro_chat_log WHERE has_steering = FALSE AND $__timeFilter(timestamp)",
"refId": "A"
}
],
@@ -280,8 +310,11 @@
"type": "bargauge"
},
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
- "description": "Per-user steering and spec mode usage",
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
+ "description": "Per-user steering and spec-mode use, with names resolved from usage reports.",
"fieldConfig": {
"defaults": {
"color": {
@@ -318,10 +351,13 @@
},
"targets": [
{
- "datasource": {"type": "grafana-postgresql-datasource", "uid": "devlake-postgres-api"},
+ "datasource": {
+ "type": "grafana-postgresql-datasource",
+ "uid": "devlake-postgres-api"
+ },
"format": "table",
"rawQuery": true,
- "rawSql": "SELECT COALESCE(MAX(display_name), user_id) AS \"User\", COUNT(*) AS \"Total Chats\", SUM(CASE WHEN has_steering = TRUE THEN 1 ELSE 0 END) AS \"Steering\", SUM(CASE WHEN is_spec_mode = TRUE THEN 1 ELSE 0 END) AS \"Spec Mode\", ROUND(CAST(CAST(SUM(CASE WHEN has_steering = TRUE THEN 1 ELSE 0 END) * 100.0 AS NUMERIC) / NULLIF(COUNT(*), 0) AS DECIMAL), 1) AS \"Steering %\" FROM _tool_q_dev_chat_log WHERE $__timeFilter(timestamp) GROUP BY \"user_id\" ORDER BY COUNT(*) DES [...]
+ "rawSql": "WITH names AS (SELECT user_id, MAX(display_name) AS display_name FROM _tool_kiro_user_report WHERE $__timeFilter(date) GROUP BY user_id) SELECT COALESCE(n.display_name, c.user_id) AS \"User\", COUNT(*) AS \"Total Chats\", SUM(CASE WHEN has_steering = TRUE THEN 1 ELSE 0 END) AS \"Steering\", SUM(CASE WHEN is_spec_mode = TRUE THEN 1 ELSE 0 END) AS \"Spec Mode\", ROUND(CAST(SUM(CASE WHEN has_steering = TRUE THEN 1 ELSE 0 END) AS NUMERIC) * 100.0 / NULLIF(COUNT(*), 0), 1 [...]
"refId": "A"
}
],
@@ -333,7 +369,6 @@
"refresh": "5m",
"schemaVersion": 41,
"tags": [
- "q_dev",
"kiro",
"steering",
"adoption"
@@ -350,4 +385,4 @@
"title": "Kiro Steering & Spec Mode Adoption",
"uid": "kiro_steering_adoption-pg",
"version": 1
-}
\ No newline at end of file
+}