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 463b1629d feat(grafana): integrate Claude Code into Multi-AI 
Comparison dashboard (#9181)
463b1629d is described below

commit 463b1629d78af4da2543fc1aff5342c2988b204e
Author: Keerthan Poojary <[email protected]>
AuthorDate: Sun Oct 4 15:41:04 2026 +0530

    feat(grafana): integrate Claude Code into Multi-AI Comparison dashboard 
(#9181)
    
    - Add Claude Code: Tool Actions panel to fill 12-column grid gap in 
Assistant Activity row
    - Add Claude Code active users series to Weekly Active Users Comparison
    - Add Claude Code LOC added to Kiro/Copilot/Cursor/Claude LOC time series
    - Add Claude Code tool acceptance rate to Acceptance Rate Availability gauge
    - Add claude_code_connection_id and claude_code_scope_id template variables
    - Add navigation link to Claude Code Adoption dashboard
    - Update Semantic Boundary documentation
---
 grafana/dashboards/mysql/multi-ai-comparison.json  | 104 +++++++++++++++-
 .../dashboards/postgresql/multi-ai-comparison.json | 133 ++++++++++++++++++++-
 2 files changed, 225 insertions(+), 12 deletions(-)

diff --git a/grafana/dashboards/mysql/multi-ai-comparison.json 
b/grafana/dashboards/mysql/multi-ai-comparison.json
index a663eba9b..ce09e8fa7 100644
--- a/grafana/dashboards/mysql/multi-ai-comparison.json
+++ b/grafana/dashboards/mysql/multi-ai-comparison.json
@@ -49,6 +49,17 @@
       "title": "Cursor Usage",
       "type": "link",
       "url": "/d/cursor_usage"
+    },
+    {
+      "asDropdown": false,
+      "icon": "external link",
+      "includeVars": true,
+      "keepTime": true,
+      "tags": [],
+      "targetBlank": true,
+      "title": "Claude Code Adoption",
+      "type": "link",
+      "url": "/d/claude_code_adoption"
     }
   ],
   "panels": [
@@ -70,7 +81,7 @@
           "showLineNumbers": false,
           "showMiniMap": false
         },
-        "content": "## Multi-AI Tool Comparison: Copilot vs Kiro vs 
Cursor\nCompare GitHub Copilot, Kiro, and Cursor 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. Cursor metrics come from `_tool_cursor_daily_usage`. Returned Kiro 
lines, Copilot LOC added, and Cursor LOC added are displayed with explicit 
labels and must not be treated as equi [...]
+        "content": "## Multi-AI Tool Comparison: Copilot vs Kiro vs Cursor vs 
Claude Code\nCompare GitHub Copilot, Kiro, Cursor, and Claude Code adoption and 
activity side by side.\n\n**Semantic boundary:** Copilot and Cursor export IDE 
code-generation and tab completion events. Kiro exports completion logs. Claude 
Code is an agentic CLI tool; its activity tracks tool execution approvals 
(accepted vs rejected edit/write tool actions) and lines added. Returned Kiro 
lines, Copilot LOC adde [...]
         "mode": "markdown"
       },
       "title": "About",
@@ -170,6 +181,16 @@
           "rawQuery": true,
           "rawSql": "SELECT\n  DATE_SUB(DATE(usage_date), INTERVAL 
WEEKDAY(DATE(usage_date)) DAY) AS time,\n  COUNT(DISTINCT user_id) AS 'Cursor 
Active Users'\nFROM _tool_cursor_daily_usage\nWHERE connection_id = 
${cursor_connection_id}\n  AND scope_id = '${cursor_scope_id}'\n  AND is_active 
= 1\n  AND $__timeFilter(usage_date)\nGROUP BY DATE_SUB(DATE(usage_date), 
INTERVAL WEEKDAY(DATE(usage_date)) DAY)\nORDER BY time",
           "refId": "C"
+        },
+        {
+          "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 'Claude Code 
Active Users'\nFROM _tool_claude_code_user_activity\nWHERE connection_id = 
${claude_code_connection_id}\n  AND scope_id = '${claude_code_scope_id}'\n  AND 
$__timeFilter(date)\n  AND (\n    cc_session_count > 0\n    OR cc_commit_count 
> 0\n    OR cc_pull_request_count > 0\n    OR cc_lines_added > 0\n    OR 
cc_lines_removed > 0\n    OR edit_tool_accepted [...]
+          "refId": "D"
         }
       ],
       "title": "Weekly Active Users Comparison",
@@ -360,6 +381,46 @@
       "title": "Cursor: Tab Completions",
       "type": "timeseries"
     },
+    {
+      "datasource": {
+        "type": "mysql",
+        "uid": "devlake-mysql-api"
+      },
+      "description": "Weekly Claude Code tool modification actions: accepted 
vs rejected (edit, write, and notebook tools)",
+      "fieldConfig": {
+        "defaults": {
+          "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" 
}
+          },
+          "unit": "short"
+        },
+        "overrides": []
+      },
+      "gridPos": { "h": 8, "w": 12, "x": 12, "y": 21 },
+      "id": 14,
+      "options": {
+        "legend": { "calcs": ["mean", "sum"], "displayMode": "table", 
"placement": "right", "showLegend": true },
+        "tooltip": { "mode": "multi" }
+      },
+      "targets": [
+        {
+          "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(edit_tool_accepted + 
write_tool_accepted + multi_edit_tool_accepted + notebook_edit_tool_accepted) 
AS 'Claude: Accepted Actions',\n  SUM(edit_tool_rejected + write_tool_rejected 
+ multi_edit_tool_rejected + notebook_edit_tool_rejected) AS 'Claude: Rejected 
Actions'\nFROM _tool_claude_code_user_activity\nWHERE connection_id = 
${claude_code_connection_id}\n  AND scope_id = '${claude_code_s [...]
+          "refId": "A"
+        }
+      ],
+      "title": "Claude Code: Tool Actions",
+      "type": "timeseries"
+    },
     {
       "collapsed": false,
       "gridPos": {
@@ -435,11 +496,11 @@
           },
           "format": "time_series",
           "rawQuery": true,
-          "rawSql": "SELECT time, SUM(kiro_lines) AS 'Kiro Returned Lines', 
SUM(copilot_loc) AS 'Copilot LOC Added', SUM(cursor_loc) AS 'Cursor 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, 0 AS 
cursor_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), INT [...]
+          "rawSql": "SELECT time, SUM(kiro_lines) AS 'Kiro Returned Lines', 
SUM(copilot_loc) AS 'Copilot LOC Added', SUM(cursor_loc) AS 'Cursor LOC Added', 
SUM(claude_loc) AS 'Claude 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, 0 AS cursor_loc, 0 AS claude_loc FROM 
_tool_kiro_completion_log WHERE $__timeFilter(timestamp) GROUP BY 
DATE_SUB(DATE(timestamp), INTERVAL WEEKDAY(DATE(t [...]
           "refId": "A"
         }
       ],
-      "title": "Kiro Returned Lines vs Copilot LOC Added",
+      "title": "Kiro Returned Lines vs Copilot/Cursor/Claude LOC Added",
       "type": "timeseries"
     },
     {
@@ -492,7 +553,7 @@
           },
           "format": "table",
           "rawQuery": true,
-          "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) UNION ALL SELECT 'Cursor' AS Tool, ROUND(SUM(tabs_accepted) 
* 100.0 / [...]
+          "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) UNION ALL SELECT 'Cursor' AS Tool, ROUND(SUM(tabs_accepted) 
* 100.0 / [...]
           "refId": "A"
         }
       ],
@@ -507,6 +568,7 @@
     "kiro",
     "copilot",
     "cursor",
+    "claude",
     "comparison"
   ],
   "templating": {
@@ -564,6 +626,36 @@
         "query": "SELECT DISTINCT id FROM _tool_cursor_scopes WHERE 
connection_id = CAST('${cursor_connection_id}' AS UNSIGNED)",
         "refresh": 1,
         "type": "query"
+      },
+      {
+        "current": {},
+        "datasource": {
+          "type": "mysql",
+          "uid": "devlake-mysql-api"
+        },
+        "definition": "SELECT DISTINCT connection_id FROM 
_tool_claude_code_scopes ORDER BY connection_id DESC",
+        "hide": 0,
+        "label": "Claude Code Connection",
+        "name": "claude_code_connection_id",
+        "options": [],
+        "query": "SELECT DISTINCT connection_id FROM _tool_claude_code_scopes 
ORDER BY connection_id DESC",
+        "refresh": 1,
+        "type": "query"
+      },
+      {
+        "current": {},
+        "datasource": {
+          "type": "mysql",
+          "uid": "devlake-mysql-api"
+        },
+        "definition": "SELECT DISTINCT id FROM _tool_claude_code_scopes WHERE 
connection_id = CAST('${claude_code_connection_id}' AS UNSIGNED)",
+        "hide": 0,
+        "label": "Claude Code Scope",
+        "name": "claude_code_scope_id",
+        "options": [],
+        "query": "SELECT DISTINCT id FROM _tool_claude_code_scopes WHERE 
connection_id = CAST('${claude_code_connection_id}' AS UNSIGNED)",
+        "refresh": 1,
+        "type": "query"
       }
     ]
   },
@@ -573,7 +665,7 @@
   },
   "timepicker": {},
   "timezone": "utc",
-  "title": "Multi-AI Tool Comparison: Copilot vs Kiro vs Cursor",
+  "title": "Multi-AI Tool Comparison: Copilot vs Kiro vs Cursor vs Claude 
Code",
   "uid": "multi_ai_comparison",
-  "version": 2
+  "version": 3
 }
diff --git a/grafana/dashboards/postgresql/multi-ai-comparison.json 
b/grafana/dashboards/postgresql/multi-ai-comparison.json
index 03b1727ef..749875118 100644
--- a/grafana/dashboards/postgresql/multi-ai-comparison.json
+++ b/grafana/dashboards/postgresql/multi-ai-comparison.json
@@ -49,6 +49,17 @@
       "title": "Cursor Usage",
       "type": "link",
       "url": "/d/cursor_usage"
+    },
+    {
+      "asDropdown": false,
+      "icon": "external link",
+      "includeVars": true,
+      "keepTime": true,
+      "tags": [],
+      "targetBlank": true,
+      "title": "Claude Code Adoption",
+      "type": "link",
+      "url": "/d/claude_code_adoption"
     }
   ],
   "panels": [
@@ -70,7 +81,7 @@
           "showLineNumbers": false,
           "showMiniMap": false
         },
-        "content": "## Multi-AI Tool Comparison: Copilot vs Kiro vs 
Cursor\nCompare GitHub Copilot, Kiro, and Cursor 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. Cursor metrics come from `_tool_cursor_daily_usage`. Returned Kiro 
lines, Copilot LOC added, and Cursor LOC added are displayed with explicit 
labels and must not be treated as equi [...]
+        "content": "## Multi-AI Tool Comparison: Copilot vs Kiro vs Cursor vs 
Claude Code\nCompare GitHub Copilot, Kiro, Cursor, and Claude Code adoption and 
activity side by side.\n\n**Semantic boundary:** Copilot and Cursor export IDE 
code-generation and tab completion events. Kiro exports completion logs. Claude 
Code is an agentic CLI tool; its activity tracks tool execution approvals 
(accepted vs rejected edit/write tool actions) and lines added. Returned Kiro 
lines, Copilot LOC adde [...]
         "mode": "markdown"
       },
       "title": "About",
@@ -173,6 +184,16 @@
           "rawQuery": true,
           "rawSql": "SELECT CAST(usage_date AS DATE) - (EXTRACT(ISODOW FROM 
CAST(usage_date AS DATE)) - 1) * INTERVAL '1 day' AS time, COUNT(DISTINCT 
user_id) AS \"Cursor Active Users\" FROM _tool_cursor_daily_usage WHERE 
('${cursor_connection_id}' = '' OR connection_id::text = 
'${cursor_connection_id}') AND scope_id = '${cursor_scope_id}' AND is_active = 
TRUE AND $__timeFilter(usage_date) GROUP BY CAST(usage_date AS DATE) - 
(EXTRACT(ISODOW FROM CAST(usage_date AS DATE)) - 1) * INTERVAL  [...]
           "refId": "C"
+        },
+        {
+          "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 
\"Claude Code Active Users\" FROM _tool_claude_code_user_activity WHERE 
('${claude_code_connection_id}' = '' OR connection_id::text = 
'${claude_code_connection_id}') AND scope_id = '${claude_code_scope_id}' AND 
$__timeFilter(date) AND (cc_session_count > 0 OR cc_commit_count > 0 OR 
cc_pull_request_count > 0 OR cc_lines_added > 0 OR cc_lines [...]
+          "refId": "D"
         }
       ],
       "title": "Weekly Active Users Comparison",
@@ -398,6 +419,75 @@
       "title": "Cursor: Tab Completions",
       "type": "timeseries"
     },
+    {
+      "datasource": {
+        "type": "grafana-postgresql-datasource",
+        "uid": "devlake-postgres-api"
+      },
+      "description": "Weekly Claude Code tool modification actions: accepted 
vs rejected (edit, write, and notebook tools)",
+      "fieldConfig": {
+        "defaults": {
+          "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"
+            }
+          },
+          "unit": "short"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 8,
+        "w": 12,
+        "x": 12,
+        "y": 21
+      },
+      "id": 14,
+      "options": {
+        "legend": {
+          "calcs": [
+            "mean",
+            "sum"
+          ],
+          "displayMode": "table",
+          "placement": "right",
+          "showLegend": true
+        },
+        "tooltip": {
+          "mode": "multi"
+        }
+      },
+      "targets": [
+        {
+          "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(edit_tool_accepted + 
write_tool_accepted + multi_edit_tool_accepted + notebook_edit_tool_accepted) 
AS \"Claude: Accepted Actions\", SUM(edit_tool_rejected + write_tool_rejected + 
multi_edit_tool_rejected + notebook_edit_tool_rejected) AS \"Claude: Rejected 
Actions\" FROM _tool_claude_code_user_activity WHERE 
('${claude_code_connection_id}' = '' OR connection_id:: [...]
+          "refId": "A"
+        }
+      ],
+      "title": "Claude Code: Tool Actions",
+      "type": "timeseries"
+    },
     {
       "collapsed": false,
       "gridPos": {
@@ -473,11 +563,11 @@
           },
           "format": "time_series",
           "rawQuery": true,
-          "rawSql": "SELECT time, SUM(kiro_lines) AS \"Kiro Returned Lines\", 
SUM(copilot_loc) AS \"Copilot LOC Added\", SUM(cursor_loc) AS \"Cursor 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, 0 AS cursor_loc FROM 
_tool_kiro_completion_log WHERE $__timeFilter(timestamp) GROUP BY 
CAST(timestamp AS DATE) - (EXTRACT(ISODOW FROM CAST(timestamp AS DAT [...]
+          "rawSql": "SELECT time, SUM(kiro_lines) AS \"Kiro Returned Lines\", 
SUM(copilot_loc) AS \"Copilot LOC Added\", SUM(cursor_loc) AS \"Cursor LOC 
Added\", SUM(claude_loc) AS \"Claude 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, 0 AS 
cursor_loc, 0 AS claude_loc FROM _tool_kiro_completion_log WHERE 
$__timeFilter(timestamp) GROUP BY CAST(times [...]
           "refId": "A"
         }
       ],
-      "title": "Kiro Returned Lines vs Copilot LOC Added",
+      "title": "Kiro Returned Lines vs Copilot/Cursor/Claude LOC Added",
       "type": "timeseries"
     },
     {
@@ -530,7 +620,7 @@
           },
           "format": "table",
           "rawQuery": true,
-          "rawSql": "SELECT 'Kiro (not exported)' AS \"Tool\", CAST(NULL AS 
DECIMAL(10, 2)) AS \"Acceptance Rate\" 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) 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 $__tim 
[...]
+          "rawSql": "SELECT 'Kiro (not exported)' AS \"Tool\", CAST(NULL AS 
DECIMAL(10, 2)) AS \"Acceptance Rate\" 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) 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 $__tim 
[...]
           "refId": "A"
         }
       ],
@@ -545,6 +635,7 @@
     "kiro",
     "copilot",
     "cursor",
+    "claude",
     "comparison"
   ],
   "templating": {
@@ -608,6 +699,36 @@
         "query": "SELECT DISTINCT id FROM _tool_cursor_scopes WHERE 
connection_id = CAST('${cursor_connection_id}' AS BIGINT)",
         "refresh": 1,
         "type": "query"
+      },
+      {
+        "current": {},
+        "datasource": {
+          "type": "grafana-postgresql-datasource",
+          "uid": "devlake-postgres-api"
+        },
+        "definition": "SELECT DISTINCT connection_id FROM 
_tool_claude_code_scopes ORDER BY connection_id DESC NULLS LAST",
+        "hide": 0,
+        "label": "Claude Code Connection",
+        "name": "claude_code_connection_id",
+        "options": [],
+        "query": "SELECT DISTINCT connection_id FROM _tool_claude_code_scopes 
ORDER BY connection_id DESC NULLS LAST",
+        "refresh": 1,
+        "type": "query"
+      },
+      {
+        "current": {},
+        "datasource": {
+          "type": "grafana-postgresql-datasource",
+          "uid": "devlake-postgres-api"
+        },
+        "definition": "SELECT DISTINCT id FROM _tool_claude_code_scopes WHERE 
connection_id = CAST('${claude_code_connection_id}' AS BIGINT)",
+        "hide": 0,
+        "label": "Claude Code Scope",
+        "name": "claude_code_scope_id",
+        "options": [],
+        "query": "SELECT DISTINCT id FROM _tool_claude_code_scopes WHERE 
connection_id = CAST('${claude_code_connection_id}' AS BIGINT)",
+        "refresh": 1,
+        "type": "query"
       }
     ]
   },
@@ -617,7 +738,7 @@
   },
   "timepicker": {},
   "timezone": "utc",
-  "title": "Multi-AI Tool Comparison: Copilot vs Kiro vs Cursor",
+  "title": "Multi-AI Tool Comparison: Copilot vs Kiro vs Cursor vs Claude 
Code",
   "uid": "multi_ai_comparison-pg",
-  "version": 2
+  "version": 3
 }
\ No newline at end of file

Reply via email to