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/incubator-devlake.git


The following commit(s) were added to refs/heads/main by this push:
     new 07bc58370 feat: Collect Pull Request Reviewer Status (#8668)
07bc58370 is described below

commit 07bc5837045ae2e9c9e74f49a6ac4020cbb8d454
Author: Warren Chen <[email protected]>
AuthorDate: Wed Dec 31 10:00:56 2025 +0800

    feat: Collect Pull Request Reviewer Status (#8668)
    
    * feat: Collect Pull Request Reviewer Status
    
    * feat: Collect Pull Request Reviewer Status
---
 backend/plugins/bitbucket/impl/impl.go             |    2 +
 .../20251226_add_pr_reviewer_table.go              |   64 +
 .../bitbucket/models/migrationscripts/register.go  |    1 +
 backend/plugins/bitbucket/models/pr_reviewer.go    |   41 +
 backend/plugins/bitbucket/tasks/pr_collector.go    |    2 +
 backend/plugins/bitbucket/tasks/pr_extractor.go    |   41 +-
 .../bitbucket/tasks/pr_reviewer_convertor.go       |   80 +
 grafana/dashboards/qdev_user_data.json             | 1588 ++++++++++----------
 8 files changed, 1023 insertions(+), 796 deletions(-)

diff --git a/backend/plugins/bitbucket/impl/impl.go 
b/backend/plugins/bitbucket/impl/impl.go
index 3fd1ec6f8..9586294ec 100644
--- a/backend/plugins/bitbucket/impl/impl.go
+++ b/backend/plugins/bitbucket/impl/impl.go
@@ -80,6 +80,7 @@ func (p Bitbucket) GetTablesInfo() []dal.Tabler {
                &models.BitbucketDeployment{},
                &models.BitbucketPipelineStep{},
                &models.BitbucketPrCommit{},
+               &models.BitbucketPrReviewer{},
                &models.BitbucketScopeConfig{},
        }
 }
@@ -125,6 +126,7 @@ func (p Bitbucket) SubTaskMetas() []plugin.SubTaskMeta {
                tasks.ConvertRepoMeta,
                tasks.ConvertAccountsMeta,
                tasks.ConvertPullRequestsMeta,
+               tasks.ConvertPrReviewersMeta,
                tasks.ConvertPrCommentsMeta,
                tasks.ConvertPrCommitsMeta,
                tasks.ConvertCommitsMeta,
diff --git 
a/backend/plugins/bitbucket/models/migrationscripts/20251226_add_pr_reviewer_table.go
 
b/backend/plugins/bitbucket/models/migrationscripts/20251226_add_pr_reviewer_table.go
new file mode 100644
index 000000000..c5da61075
--- /dev/null
+++ 
b/backend/plugins/bitbucket/models/migrationscripts/20251226_add_pr_reviewer_table.go
@@ -0,0 +1,64 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package migrationscripts
+
+import (
+       "time"
+
+       "github.com/apache/incubator-devlake/core/context"
+       "github.com/apache/incubator-devlake/core/errors"
+       
"github.com/apache/incubator-devlake/core/models/migrationscripts/archived"
+       "github.com/apache/incubator-devlake/core/plugin"
+)
+
+var _ plugin.MigrationScript = (*addPrReviewerTable)(nil)
+
+type prReviewer20251226 struct {
+       ConnectionId   uint64 `gorm:"primaryKey"`
+       RepoId         string `gorm:"primaryKey;type:varchar(255)"`
+       PullRequestId  int    `gorm:"primaryKey"`
+       AccountId      string `gorm:"primaryKey;type:varchar(255)"`
+       DisplayName    string `gorm:"type:varchar(255)"`
+       Role           string `gorm:"type:varchar(100)"`
+       State          string `gorm:"type:varchar(100)"`
+       Approved       bool
+       ParticipatedOn *time.Time
+       archived.NoPKModel
+}
+
+func (prReviewer20251226) TableName() string {
+       return "_tool_bitbucket_pr_reviewers"
+}
+
+type addPrReviewerTable struct{}
+
+func (*addPrReviewerTable) Up(basicRes context.BasicRes) errors.Error {
+       db := basicRes.GetDal()
+       if err := db.AutoMigrate(&prReviewer20251226{}); err != nil {
+               return err
+       }
+       return nil
+}
+
+func (*addPrReviewerTable) Version() uint64 {
+       return 20251226100000
+}
+
+func (*addPrReviewerTable) Name() string {
+       return "add _tool_bitbucket_pr_reviewers table"
+}
diff --git a/backend/plugins/bitbucket/models/migrationscripts/register.go 
b/backend/plugins/bitbucket/models/migrationscripts/register.go
index c47f7db4f..e8a31d2c1 100644
--- a/backend/plugins/bitbucket/models/migrationscripts/register.go
+++ b/backend/plugins/bitbucket/models/migrationscripts/register.go
@@ -43,5 +43,6 @@ func All() []plugin.MigrationScript {
                new(addMergedByToPr),
                new(changeIssueComponentType),
                new(addApiTokenAuth),
+               new(addPrReviewerTable),
        }
 }
diff --git a/backend/plugins/bitbucket/models/pr_reviewer.go 
b/backend/plugins/bitbucket/models/pr_reviewer.go
new file mode 100644
index 000000000..43df52739
--- /dev/null
+++ b/backend/plugins/bitbucket/models/pr_reviewer.go
@@ -0,0 +1,41 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package models
+
+import (
+       "time"
+
+       "github.com/apache/incubator-devlake/core/models/common"
+)
+
+type BitbucketPrReviewer struct {
+       ConnectionId   uint64 `gorm:"primaryKey"`
+       RepoId         string `gorm:"primaryKey;type:varchar(255)"`
+       PullRequestId  int    `gorm:"primaryKey"`
+       AccountId      string `gorm:"primaryKey;type:varchar(255)"`
+       DisplayName    string `gorm:"type:varchar(255)"`
+       Role           string `gorm:"type:varchar(100)"` // PARTICIPANT, 
REVIEWER
+       State          string `gorm:"type:varchar(100)"` // approved, 
changes_requested, null
+       Approved       bool
+       ParticipatedOn *time.Time
+       common.NoPKModel
+}
+
+func (BitbucketPrReviewer) TableName() string {
+       return "_tool_bitbucket_pr_reviewers"
+}
diff --git a/backend/plugins/bitbucket/tasks/pr_collector.go 
b/backend/plugins/bitbucket/tasks/pr_collector.go
index efa6890e1..4db0dd08f 100644
--- a/backend/plugins/bitbucket/tasks/pr_collector.go
+++ b/backend/plugins/bitbucket/tasks/pr_collector.go
@@ -53,6 +53,8 @@ func CollectApiPullRequests(taskCtx plugin.SubTaskContext) 
errors.Error {
                                
`values.merge_commit.hash,values.merge_commit.date,values.links.html,values.author,values.created_on,values.updated_on,`+
                                
`values.destination.branch.name,values.destination.commit.hash,values.destination.repository.full_name,`+
                                
`values.source.branch.name,values.source.commit.hash,values.source.repository.full_name,`+
+                               
`values.participants.user.account_id,values.participants.user.display_name,`+
+                               
`values.participants.role,values.participants.state,values.participants.approved,values.participants.participated_on,`+
                                `page,pagelen,size`,
                        collectorWithState),
                GetTotalPages:  GetTotalPagesFromResponse,
diff --git a/backend/plugins/bitbucket/tasks/pr_extractor.go 
b/backend/plugins/bitbucket/tasks/pr_extractor.go
index 9cca3a0ce..5edb75e28 100644
--- a/backend/plugins/bitbucket/tasks/pr_extractor.go
+++ b/backend/plugins/bitbucket/tasks/pr_extractor.go
@@ -77,8 +77,15 @@ type BitbucketApiPullRequest struct {
                } `json:"commit"`
                Repo *models.BitbucketApiRepo `json:"repository"`
        } `json:"source"`
-       //Reviewers    []BitbucketAccountResponse `json:"reviewers"`
-       //Participants []BitbucketAccountResponse `json:"participants"`
+       Participants []BitbucketParticipant `json:"participants"`
+}
+
+type BitbucketParticipant struct {
+       User           *BitbucketAccountResponse `json:"user"`
+       Role           string                    `json:"role"`
+       State          *string                   `json:"state"`
+       Approved       bool                      `json:"approved"`
+       ParticipatedOn *common.Iso8601Time       `json:"participated_on"`
 }
 
 func ExtractApiPullRequests(taskCtx plugin.SubTaskContext) errors.Error {
@@ -117,6 +124,36 @@ func ExtractApiPullRequests(taskCtx plugin.SubTaskContext) 
errors.Error {
                        }
                        results = append(results, bitbucketPr)
 
+                       // Extract participants/reviewers
+                       for _, participant := range rawL.Participants {
+                               if participant.User == nil {
+                                       continue
+                               }
+                               reviewer := &models.BitbucketPrReviewer{
+                                       ConnectionId:  
data.Options.ConnectionId,
+                                       RepoId:        data.Options.FullName,
+                                       PullRequestId: rawL.BitbucketId,
+                                       AccountId:     
participant.User.AccountId,
+                                       DisplayName:   
participant.User.DisplayName,
+                                       Role:          participant.Role,
+                                       Approved:      participant.Approved,
+                               }
+                               if participant.State != nil {
+                                       reviewer.State = *participant.State
+                               }
+                               if participant.ParticipatedOn != nil {
+                                       reviewer.ParticipatedOn = 
participant.ParticipatedOn.ToNullableTime()
+                               }
+                               results = append(results, reviewer)
+
+                               // Also save the user account
+                               bitbucketUser, err := 
convertAccount(participant.User, data.Options.ConnectionId)
+                               if err != nil {
+                                       return nil, err
+                               }
+                               results = append(results, bitbucketUser)
+                       }
+
                        return results, nil
                },
        })
diff --git a/backend/plugins/bitbucket/tasks/pr_reviewer_convertor.go 
b/backend/plugins/bitbucket/tasks/pr_reviewer_convertor.go
new file mode 100644
index 000000000..c6de00e92
--- /dev/null
+++ b/backend/plugins/bitbucket/tasks/pr_reviewer_convertor.go
@@ -0,0 +1,80 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package tasks
+
+import (
+       "reflect"
+
+       "github.com/apache/incubator-devlake/core/dal"
+       "github.com/apache/incubator-devlake/core/errors"
+       "github.com/apache/incubator-devlake/core/models/domainlayer/code"
+       "github.com/apache/incubator-devlake/core/models/domainlayer/didgen"
+       plugin "github.com/apache/incubator-devlake/core/plugin"
+       "github.com/apache/incubator-devlake/helpers/pluginhelper/api"
+       "github.com/apache/incubator-devlake/plugins/bitbucket/models"
+)
+
+var ConvertPrReviewersMeta = plugin.SubTaskMeta{
+       Name:             "Convert PR Reviewers",
+       EntryPoint:       ConvertPrReviewers,
+       EnabledByDefault: true,
+       Required:         false,
+       Description:      "Convert tool layer PR reviewers to domain layer",
+       DomainTypes:      []string{plugin.DOMAIN_TYPE_CODE_REVIEW},
+}
+
+func ConvertPrReviewers(taskCtx plugin.SubTaskContext) errors.Error {
+       rawDataSubTaskArgs, data := CreateRawDataSubTaskArgs(taskCtx, 
RAW_PULL_REQUEST_TABLE)
+       db := taskCtx.GetDal()
+       repoId := data.Options.FullName
+
+       cursor, err := db.Cursor(
+               dal.From(&models.BitbucketPrReviewer{}),
+               dal.Where("repo_id = ? and connection_id = ?", repoId, 
data.Options.ConnectionId),
+       )
+       if err != nil {
+               return err
+       }
+       defer cursor.Close()
+
+       prIdGen := didgen.NewDomainIdGenerator(&models.BitbucketPullRequest{})
+       accountIdGen := didgen.NewDomainIdGenerator(&models.BitbucketAccount{})
+
+       converter, err := api.NewDataConverter(api.DataConverterArgs{
+               InputRowType:       
reflect.TypeOf(models.BitbucketPrReviewer{}),
+               Input:              cursor,
+               RawDataSubTaskArgs: *rawDataSubTaskArgs,
+               Convert: func(inputRow interface{}) ([]interface{}, 
errors.Error) {
+                       reviewer := inputRow.(*models.BitbucketPrReviewer)
+                       domainReviewer := &code.PullRequestReviewer{
+                               PullRequestId: 
prIdGen.Generate(data.Options.ConnectionId, reviewer.RepoId, 
reviewer.PullRequestId),
+                               ReviewerId:    
accountIdGen.Generate(data.Options.ConnectionId, reviewer.AccountId),
+                               Name:          reviewer.DisplayName,
+                               UserName:      reviewer.DisplayName,
+                       }
+                       return []interface{}{
+                               domainReviewer,
+                       }, nil
+               },
+       })
+       if err != nil {
+               return err
+       }
+
+       return converter.Execute()
+}
diff --git a/grafana/dashboards/qdev_user_data.json 
b/grafana/dashboards/qdev_user_data.json
index 8ce8d11b3..ff55b9ff8 100644
--- a/grafana/dashboards/qdev_user_data.json
+++ b/grafana/dashboards/qdev_user_data.json
@@ -1,795 +1,795 @@
-{
-  "annotations": {
-    "list": [
-      {
-        "builtIn": 1,
-        "datasource": "-- Grafana --",
-        "enable": true,
-        "hide": true,
-        "iconColor": "rgba(0, 211, 255, 1)",
-        "name": "Annotations & Alerts",
-        "type": "dashboard"
-      }
-    ]
-  },
-  "editable": true,
-  "fiscalYearStartMonth": 0,
-  "graphTooltip": 0,
-  "id": 100,
-  "links": [],
-  "panels": [
-    {
-      "datasource": "mysql",
-      "description": "Overview of key user metrics",
-      "fieldConfig": {
-        "defaults": {
-          "color": {
-            "mode": "thresholds"
-          },
-          "mappings": [],
-          "thresholds": {
-            "mode": "absolute",
-            "steps": [
-              {
-                "color": "green"
-              }
-            ]
-          }
-        },
-        "overrides": []
-      },
-      "gridPos": {
-        "h": 8,
-        "w": 24,
-        "x": 0,
-        "y": 0
-      },
-      "id": 10,
-      "options": {
-        "colorMode": "value",
-        "graphMode": "area",
-        "justifyMode": "auto",
-        "orientation": "auto",
-        "percentChangeColorMode": "standard",
-        "reduceOptions": {
-          "calcs": [
-            "sum"
-          ],
-          "fields": "",
-          "values": false
-        },
-        "showPercentChange": false,
-        "text": {},
-        "textMode": "auto",
-        "wideLayout": true
-      },
-      "pluginVersion": "11.6.2",
-      "targets": [
-        {
-          "datasource": "mysql",
-          "editorMode": "code",
-          "format": "table",
-          "group": [],
-          "metricColumn": "none",
-          "rawQuery": true,
-          "rawSql": "SELECT\n  COUNT(DISTINCT user_id) as 'Active Users',\n  
SUM(chat_ai_code_lines) as 'Accepted Lines (Chat)',\n  
SUM(inline_ai_code_lines) as 'Accepted Lines (Inline Suggestion)',\n  
SUM(inline_acceptance_count) / NULLIF(SUM(inline_suggestions_count), 0) as 
'Acceptance Rate (Inline Suggestion)',\n  SUM(code_review_findings_count) as 
'Findings (Code Review)',\n  SUM(code_fix_accepted_lines) as 'Accepted Lines 
(Code Fix)',\n  SUM(code_fix_acceptance_event_count) / NULLIF [...]
-          "refId": "A",
-          "select": [
-            [
-              {
-                "params": [
-                  "value"
-                ],
-                "type": "column"
-              }
-            ]
-          ],
-          "sql": {
-            "columns": [
-              {
-                "parameters": [],
-                "type": "function"
-              }
-            ],
-            "groupBy": [
-              {
-                "property": {
-                  "type": "string"
-                },
-                "type": "groupBy"
-              }
-            ],
-            "limit": 50
-          },
-          "timeColumn": "time",
-          "where": [
-            {
-              "name": "$__timeFilter",
-              "params": [],
-              "type": "macro"
-            }
-          ]
-        }
-      ],
-      "title": "Overall Usage Statistics",
-      "type": "stat"
-    },
-    {
-      "datasource": "mysql",
-      "description": "Daily AI code line changes across all users",
-      "fieldConfig": {
-        "defaults": {
-          "color": {
-            "mode": "palette-classic"
-          },
-          "custom": {
-            "axisBorderShow": false,
-            "axisCenteredZero": false,
-            "axisColorMode": "text",
-            "axisLabel": "",
-            "axisPlacement": "auto",
-            "barAlignment": 0,
-            "barWidthFactor": 0.6,
-            "drawStyle": "line",
-            "fillOpacity": 10,
-            "gradientMode": "none",
-            "hideFrom": {
-              "legend": false,
-              "tooltip": false,
-              "viz": false
-            },
-            "insertNulls": false,
-            "lineInterpolation": "smooth",
-            "lineWidth": 2,
-            "pointSize": 5,
-            "scaleDistribution": {
-              "type": "linear"
-            },
-            "showPoints": "never",
-            "spanNulls": true,
-            "stacking": {
-              "group": "A",
-              "mode": "none"
-            },
-            "thresholdsStyle": {
-              "mode": "off"
-            }
-          },
-          "mappings": [],
-          "thresholds": {
-            "mode": "absolute",
-            "steps": [
-              {
-                "color": "green"
-              }
-            ]
-          },
-          "unit": "short"
-        },
-        "overrides": []
-      },
-      "gridPos": {
-        "h": 8,
-        "w": 24,
-        "x": 0,
-        "y": 8
-      },
-      "id": 3,
-      "options": {
-        "legend": {
-          "calcs": [
-            "mean",
-            "max",
-            "sum"
-          ],
-          "displayMode": "table",
-          "placement": "right",
-          "showLegend": true
-        },
-        "tooltip": {
-          "hideZeros": false,
-          "mode": "multi",
-          "sort": "none"
-        }
-      },
-      "pluginVersion": "11.6.2",
-      "targets": [
-        {
-          "datasource": "mysql",
-          "editorMode": "code",
-          "format": "time_series",
-          "group": [],
-          "metricColumn": "none",
-          "rawQuery": true,
-          "rawSql": "SELECT\n  date as time,\n  SUM(chat_ai_code_lines) as 
'Chat Accepted Lines',\n  SUM(code_fix_accepted_lines) as 'Code Fix Accepted 
Lines',\n  SUM(code_fix_generated_lines) as 'Code Fix Generated Lines',\n  
SUM(transformation_lines_ingested) as 'Java Transform Ingested Lines',\n  
SUM(transformation_lines_generated) as 'Java Transform Generated Lines',\n  
SUM(inline_ai_code_lines) as 'Inline Suggestion Accepted Lines',\n  
SUM(inline_chat_accepted_line_additions) as 'In [...]
-          "refId": "A",
-          "select": [
-            [
-              {
-                "params": [
-                  "value"
-                ],
-                "type": "column"
-              }
-            ]
-          ],
-          "sql": {
-            "columns": [
-              {
-                "parameters": [],
-                "type": "function"
-              }
-            ],
-            "groupBy": [
-              {
-                "property": {
-                  "type": "string"
-                },
-                "type": "groupBy"
-              }
-            ],
-            "limit": 50
-          },
-          "timeColumn": "time",
-          "where": [
-            {
-              "name": "$__timeFilter",
-              "params": [],
-              "type": "macro"
-            }
-          ]
-        }
-      ],
-      "title": "Daily AI Code Line Changes",
-      "type": "timeseries"
-    },
-    {
-      "datasource": "mysql",
-      "description": "Daily AI interaction trends across all users",
-      "fieldConfig": {
-        "defaults": {
-          "color": {
-            "mode": "palette-classic"
-          },
-          "custom": {
-            "axisBorderShow": false,
-            "axisCenteredZero": false,
-            "axisColorMode": "text",
-            "axisLabel": "",
-            "axisPlacement": "auto",
-            "barAlignment": 0,
-            "barWidthFactor": 0.6,
-            "drawStyle": "line",
-            "fillOpacity": 10,
-            "gradientMode": "none",
-            "hideFrom": {
-              "legend": false,
-              "tooltip": false,
-              "viz": false
-            },
-            "insertNulls": false,
-            "lineInterpolation": "smooth",
-            "lineWidth": 2,
-            "pointSize": 5,
-            "scaleDistribution": {
-              "type": "linear"
-            },
-            "showPoints": "never",
-            "spanNulls": true,
-            "stacking": {
-              "group": "A",
-              "mode": "none"
-            },
-            "thresholdsStyle": {
-              "mode": "off"
-            }
-          },
-          "mappings": [],
-          "thresholds": {
-            "mode": "absolute",
-            "steps": [
-              {
-                "color": "green"
-              }
-            ]
-          },
-          "unit": "short"
-        },
-        "overrides": []
-      },
-      "gridPos": {
-        "h": 8,
-        "w": 24,
-        "x": 0,
-        "y": 16
-      },
-      "id": 9,
-      "options": {
-        "legend": {
-          "calcs": [
-            "mean",
-            "max",
-            "sum"
-          ],
-          "displayMode": "table",
-          "placement": "right",
-          "showLegend": true
-        },
-        "tooltip": {
-          "hideZeros": false,
-          "mode": "multi",
-          "sort": "none"
-        }
-      },
-      "pluginVersion": "11.6.2",
-      "targets": [
-        {
-          "datasource": "mysql",
-          "editorMode": "code",
-          "format": "time_series",
-          "group": [],
-          "metricColumn": "none",
-          "rawQuery": true,
-          "rawSql": "SELECT\n  date as time,\n  SUM(chat_messages_sent) as 
'Chat Messages Sent',\n  SUM(code_fix_acceptance_event_count) as 'Code Fix 
Accepted Event Count',\n  SUM(code_fix_generation_event_count) as 'Code Fix 
Generated Event Count',\n  SUM(transformation_event_count) as 'Java Transform 
Event Count',\n  SUM(inline_acceptance_count) as 'Inline Suggestion Accepted 
Suggestions',\n  SUM(inline_suggestions_count) as 'Inline Suggestion Count',\n  
SUM(inline_chat_total_event_cou [...]
-          "refId": "A",
-          "select": [
-            [
-              {
-                "params": [
-                  "value"
-                ],
-                "type": "column"
-              }
-            ]
-          ],
-          "sql": {
-            "columns": [
-              {
-                "parameters": [],
-                "type": "function"
-              }
-            ],
-            "groupBy": [
-              {
-                "property": {
-                  "type": "string"
-                },
-                "type": "groupBy"
-              }
-            ],
-            "limit": 50
-          },
-          "timeColumn": "time",
-          "where": [
-            {
-              "name": "$__timeFilter",
-              "params": [],
-              "type": "macro"
-            }
-          ]
-        }
-      ],
-      "title": "Daily AI Interactions",
-      "type": "timeseries"
-    },
-    {
-      "datasource": "mysql",
-      "description": "Code review metrics over time",
-      "fieldConfig": {
-        "defaults": {
-          "color": {
-            "mode": "palette-classic"
-          },
-          "custom": {
-            "axisBorderShow": false,
-            "axisCenteredZero": false,
-            "axisColorMode": "text",
-            "axisLabel": "",
-            "axisPlacement": "auto",
-            "barAlignment": 0,
-            "barWidthFactor": 0.6,
-            "drawStyle": "line",
-            "fillOpacity": 10,
-            "gradientMode": "none",
-            "hideFrom": {
-              "legend": false,
-              "tooltip": false,
-              "viz": false
-            },
-            "insertNulls": false,
-            "lineInterpolation": "smooth",
-            "lineWidth": 2,
-            "pointSize": 5,
-            "scaleDistribution": {
-              "type": "linear"
-            },
-            "showPoints": "never",
-            "spanNulls": true,
-            "stacking": {
-              "group": "A",
-              "mode": "none"
-            },
-            "thresholdsStyle": {
-              "mode": "off"
-            }
-          },
-          "mappings": [],
-          "thresholds": {
-            "mode": "absolute",
-            "steps": [
-              {
-                "color": "green"
-              }
-            ]
-          },
-          "unit": "short"
-        },
-        "overrides": []
-      },
-      "gridPos": {
-        "h": 8,
-        "w": 12,
-        "x": 0,
-        "y": 24
-      },
-      "id": 4,
-      "options": {
-        "legend": {
-          "calcs": [
-            "mean",
-            "max",
-            "sum"
-          ],
-          "displayMode": "table",
-          "placement": "bottom",
-          "showLegend": true
-        },
-        "tooltip": {
-          "hideZeros": false,
-          "mode": "multi",
-          "sort": "none"
-        }
-      },
-      "pluginVersion": "11.6.2",
-      "targets": [
-        {
-          "datasource": "mysql",
-          "format": "time_series",
-          "group": [],
-          "metricColumn": "none",
-          "rawQuery": true,
-          "rawSql": "SELECT\n  date as time,\n  
SUM(code_fix_acceptance_event_count) as 'Code Fix Accepted Event Count',\n  
SUM(code_fix_generation_event_count) as 'Code Fix Generated Event Count',\n  
SUM(code_review_findings_count) as 'Total Findings'\nFROM 
lake._tool_q_dev_user_data\nWHERE $__timeFilter(date)\nGROUP BY date\nORDER BY 
date",
-          "refId": "A",
-          "select": [
-            [
-              {
-                "params": [
-                  "value"
-                ],
-                "type": "column"
-              }
-            ]
-          ],
-          "sql": {
-            "columns": [
-              {
-                "parameters": [],
-                "type": "function"
-              }
-            ],
-            "groupBy": [
-              {
-                "property": {
-                  "type": "string"
-                },
-                "type": "groupBy"
-              }
-            ],
-            "limit": 50
-          },
-          "timeColumn": "time",
-          "where": [
-            {
-              "name": "$__timeFilter",
-              "params": [],
-              "type": "macro"
-            }
-          ]
-        }
-      ],
-      "title": "Code Review Metrics",
-      "type": "timeseries"
-    },
-    {
-      "datasource": "mysql",
-      "description": "Daily acceptance rate of AI suggestions",
-      "fieldConfig": {
-        "defaults": {
-          "color": {
-            "mode": "palette-classic"
-          },
-          "custom": {
-            "axisBorderShow": false,
-            "axisCenteredZero": false,
-            "axisColorMode": "text",
-            "axisLabel": "",
-            "axisPlacement": "auto",
-            "barAlignment": 0,
-            "barWidthFactor": 0.6,
-            "drawStyle": "line",
-            "fillOpacity": 10,
-            "gradientMode": "none",
-            "hideFrom": {
-              "legend": false,
-              "tooltip": false,
-              "viz": false
-            },
-            "insertNulls": false,
-            "lineInterpolation": "smooth",
-            "lineWidth": 2,
-            "pointSize": 5,
-            "scaleDistribution": {
-              "type": "linear"
-            },
-            "showPoints": "never",
-            "spanNulls": true,
-            "stacking": {
-              "group": "A",
-              "mode": "none"
-            },
-            "thresholdsStyle": {
-              "mode": "off"
-            }
-          },
-          "mappings": [],
-          "thresholds": {
-            "mode": "absolute",
-            "steps": [
-              {
-                "color": "green"
-              }
-            ]
-          },
-          "unit": "percentunit"
-        },
-        "overrides": []
-      },
-      "gridPos": {
-        "h": 8,
-        "w": 12,
-        "x": 12,
-        "y": 24
-      },
-      "id": 5,
-      "options": {
-        "legend": {
-          "calcs": [
-            "mean",
-            "max",
-            "min"
-          ],
-          "displayMode": "table",
-          "placement": "bottom",
-          "showLegend": true
-        },
-        "tooltip": {
-          "hideZeros": false,
-          "mode": "multi",
-          "sort": "none"
-        }
-      },
-      "pluginVersion": "11.6.2",
-      "targets": [
-        {
-          "datasource": "mysql",
-          "editorMode": "code",
-          "format": "time_series",
-          "group": [],
-          "metricColumn": "none",
-          "rawQuery": true,
-          "rawSql": "SELECT\n  date as time,\n  
SUM(code_fix_acceptance_event_count) / 
NULLIF(SUM(code_fix_generation_event_count), 0) as 'Code Fix',\n  
SUM(inline_acceptance_count) / NULLIF(SUM(inline_suggestions_count), 0) as 
'Inline Suggestions',\n  SUM(inline_chat_acceptance_event_count) / 
NULLIF(SUM(inline_chat_total_event_count), 0) as 'Inline Chat'\nFROM 
lake._tool_q_dev_user_data\nWHERE $__timeFilter(date)\nGROUP BY date\nORDER BY 
date",
-          "refId": "A",
-          "select": [
-            [
-              {
-                "params": [
-                  "value"
-                ],
-                "type": "column"
-              }
-            ]
-          ],
-          "sql": {
-            "columns": [
-              {
-                "parameters": [],
-                "type": "function"
-              }
-            ],
-            "groupBy": [
-              {
-                "property": {
-                  "type": "string"
-                },
-                "type": "groupBy"
-              }
-            ],
-            "limit": 50
-          },
-          "timeColumn": "time",
-          "where": [
-            {
-              "name": "$__timeFilter",
-              "params": [],
-              "type": "macro"
-            }
-          ]
-        }
-      ],
-      "title": "Daily AI Suggestion Acceptance Rate",
-      "type": "timeseries"
-    },
-    {
-      "datasource": "mysql",
-      "description": "User AI interaction metrics",
-      "fieldConfig": {
-        "defaults": {
-          "color": {
-            "mode": "thresholds"
-          },
-          "custom": {
-            "align": "auto",
-            "cellOptions": {
-              "type": "auto"
-            },
-            "filterable": true,
-            "inspect": false
-          },
-          "mappings": [],
-          "thresholds": {
-            "mode": "absolute",
-            "steps": [
-              {
-                "color": "green"
-              }
-            ]
-          }
-        },
-        "overrides": [
-          {
-            "matcher": {
-              "id": "byName",
-              "options": "Acceptance Rate"
-            },
-            "properties": [
-              {
-                "id": "unit",
-                "value": "percentunit"
-              },
-              {
-                "id": "custom.cellOptions",
-                "value": {
-                  "mode": "gradient",
-                  "type": "gauge"
-                }
-              }
-            ]
-          },
-          {
-            "matcher": {
-              "id": "byName",
-              "options": "Inline Chat Accepted Events"
-            },
-            "properties": [
-              {
-                "id": "custom.width",
-                "value": 239
-              }
-            ]
-          },
-          {
-            "matcher": {
-              "id": "byName",
-              "options": "Acceptance Rate (Inline Suggestion)"
-            },
-            "properties": [
-              {
-                "id": "custom.width",
-                "value": 172
-              }
-            ]
-          }
-        ]
-      },
-      "gridPos": {
-        "h": 8,
-        "w": 24,
-        "x": 0,
-        "y": 32
-      },
-      "id": 6,
-      "options": {
-        "cellHeight": "sm",
-        "footer": {
-          "countRows": false,
-          "fields": "",
-          "reducer": [
-            "sum"
-          ],
-          "show": false
-        },
-        "showHeader": true,
-        "sortBy": []
-      },
-      "pluginVersion": "11.6.2",
-      "targets": [
-        {
-          "datasource": "mysql",
-          "editorMode": "code",
-          "format": "table",
-          "group": [],
-          "metricColumn": "none",
-          "rawQuery": true,
-          "rawSql": "SELECT\n  COALESCE(display_name, user_id) as 'User',\n  
SUM(chat_ai_code_lines) as 'Accepted Lines (Chat)',\n  
SUM(transformation_lines_ingested) as 'Lines Ingested (Java Transform)',\n  
SUM(transformation_lines_generated) as 'Lines Generated (Java Transform)',\n  
SUM(transformation_event_count) as 'Event Count (Java Transform)',\n  
SUM(code_review_findings_count) as 'Findings (Code Review)',\n  
SUM(code_fix_accepted_lines) as 'Accepted Lines (Code Fix)',\n  SUM(code [...]
-          "refId": "A",
-          "select": [
-            [
-              {
-                "params": [
-                  "value"
-                ],
-                "type": "column"
-              }
-            ]
-          ],
-          "sql": {
-            "columns": [
-              {
-                "parameters": [],
-                "type": "function"
-              }
-            ],
-            "groupBy": [
-              {
-                "property": {
-                  "type": "string"
-                },
-                "type": "groupBy"
-              }
-            ],
-            "limit": 50
-          },
-          "timeColumn": "time",
-          "where": [
-            {
-              "name": "$__timeFilter",
-              "params": [],
-              "type": "macro"
-            }
-          ]
-        }
-      ],
-      "title": "User Interactions",
-      "type": "table"
-    }
-  ],
-  "preload": false,
-  "refresh": "5m",
-  "schemaVersion": 41,
-  "tags": [
-    "q_dev",
-    "user_data"
-  ],
-  "templating": {
-    "list": []
-  },
-  "time": {
-    "from": "now-30d",
-    "to": "now"
-  },
-  "timepicker": {},
-  "timezone": "utc",
-  "title": "Q Dev User Data Dashboard",
-  "uid": "qdev_user_data",
-  "version": 1
+{
+  "annotations": {
+    "list": [
+      {
+        "builtIn": 1,
+        "datasource": "-- Grafana --",
+        "enable": true,
+        "hide": true,
+        "iconColor": "rgba(0, 211, 255, 1)",
+        "name": "Annotations & Alerts",
+        "type": "dashboard"
+      }
+    ]
+  },
+  "editable": true,
+  "fiscalYearStartMonth": 0,
+  "graphTooltip": 0,
+  "id": 100,
+  "links": [],
+  "panels": [
+    {
+      "datasource": "mysql",
+      "description": "Overview of key user metrics",
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "thresholds"
+          },
+          "mappings": [],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green"
+              }
+            ]
+          }
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 8,
+        "w": 24,
+        "x": 0,
+        "y": 0
+      },
+      "id": 10,
+      "options": {
+        "colorMode": "value",
+        "graphMode": "area",
+        "justifyMode": "auto",
+        "orientation": "auto",
+        "percentChangeColorMode": "standard",
+        "reduceOptions": {
+          "calcs": [
+            "sum"
+          ],
+          "fields": "",
+          "values": false
+        },
+        "showPercentChange": false,
+        "text": {},
+        "textMode": "auto",
+        "wideLayout": true
+      },
+      "pluginVersion": "11.6.2",
+      "targets": [
+        {
+          "datasource": "mysql",
+          "editorMode": "code",
+          "format": "table",
+          "group": [],
+          "metricColumn": "none",
+          "rawQuery": true,
+          "rawSql": "SELECT\n  COUNT(DISTINCT user_id) as 'Active Users',\n  
SUM(chat_ai_code_lines) as 'Accepted Lines (Chat)',\n  
SUM(inline_ai_code_lines) as 'Accepted Lines (Inline Suggestion)',\n  
SUM(inline_acceptance_count) / NULLIF(SUM(inline_suggestions_count), 0) as 
'Acceptance Rate (Inline Suggestion)',\n  SUM(code_review_findings_count) as 
'Findings (Code Review)',\n  SUM(code_fix_accepted_lines) as 'Accepted Lines 
(Code Fix)',\n  SUM(code_fix_acceptance_event_count) / NULLIF [...]
+          "refId": "A",
+          "select": [
+            [
+              {
+                "params": [
+                  "value"
+                ],
+                "type": "column"
+              }
+            ]
+          ],
+          "sql": {
+            "columns": [
+              {
+                "parameters": [],
+                "type": "function"
+              }
+            ],
+            "groupBy": [
+              {
+                "property": {
+                  "type": "string"
+                },
+                "type": "groupBy"
+              }
+            ],
+            "limit": 50
+          },
+          "timeColumn": "time",
+          "where": [
+            {
+              "name": "$__timeFilter",
+              "params": [],
+              "type": "macro"
+            }
+          ]
+        }
+      ],
+      "title": "Overall Usage Statistics",
+      "type": "stat"
+    },
+    {
+      "datasource": "mysql",
+      "description": "Daily AI code line changes across all users",
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "palette-classic"
+          },
+          "custom": {
+            "axisBorderShow": false,
+            "axisCenteredZero": false,
+            "axisColorMode": "text",
+            "axisLabel": "",
+            "axisPlacement": "auto",
+            "barAlignment": 0,
+            "barWidthFactor": 0.6,
+            "drawStyle": "line",
+            "fillOpacity": 10,
+            "gradientMode": "none",
+            "hideFrom": {
+              "legend": false,
+              "tooltip": false,
+              "viz": false
+            },
+            "insertNulls": false,
+            "lineInterpolation": "smooth",
+            "lineWidth": 2,
+            "pointSize": 5,
+            "scaleDistribution": {
+              "type": "linear"
+            },
+            "showPoints": "never",
+            "spanNulls": true,
+            "stacking": {
+              "group": "A",
+              "mode": "none"
+            },
+            "thresholdsStyle": {
+              "mode": "off"
+            }
+          },
+          "mappings": [],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green"
+              }
+            ]
+          },
+          "unit": "short"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 8,
+        "w": 24,
+        "x": 0,
+        "y": 8
+      },
+      "id": 3,
+      "options": {
+        "legend": {
+          "calcs": [
+            "mean",
+            "max",
+            "sum"
+          ],
+          "displayMode": "table",
+          "placement": "right",
+          "showLegend": true
+        },
+        "tooltip": {
+          "hideZeros": false,
+          "mode": "multi",
+          "sort": "none"
+        }
+      },
+      "pluginVersion": "11.6.2",
+      "targets": [
+        {
+          "datasource": "mysql",
+          "editorMode": "code",
+          "format": "time_series",
+          "group": [],
+          "metricColumn": "none",
+          "rawQuery": true,
+          "rawSql": "SELECT\n  date as time,\n  SUM(chat_ai_code_lines) as 
'Chat Accepted Lines',\n  SUM(code_fix_accepted_lines) as 'Code Fix Accepted 
Lines',\n  SUM(code_fix_generated_lines) as 'Code Fix Generated Lines',\n  
SUM(transformation_lines_ingested) as 'Java Transform Ingested Lines',\n  
SUM(transformation_lines_generated) as 'Java Transform Generated Lines',\n  
SUM(inline_ai_code_lines) as 'Inline Suggestion Accepted Lines',\n  
SUM(inline_chat_accepted_line_additions) as 'In [...]
+          "refId": "A",
+          "select": [
+            [
+              {
+                "params": [
+                  "value"
+                ],
+                "type": "column"
+              }
+            ]
+          ],
+          "sql": {
+            "columns": [
+              {
+                "parameters": [],
+                "type": "function"
+              }
+            ],
+            "groupBy": [
+              {
+                "property": {
+                  "type": "string"
+                },
+                "type": "groupBy"
+              }
+            ],
+            "limit": 50
+          },
+          "timeColumn": "time",
+          "where": [
+            {
+              "name": "$__timeFilter",
+              "params": [],
+              "type": "macro"
+            }
+          ]
+        }
+      ],
+      "title": "Daily AI Code Line Changes",
+      "type": "timeseries"
+    },
+    {
+      "datasource": "mysql",
+      "description": "Daily AI interaction trends across all users",
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "palette-classic"
+          },
+          "custom": {
+            "axisBorderShow": false,
+            "axisCenteredZero": false,
+            "axisColorMode": "text",
+            "axisLabel": "",
+            "axisPlacement": "auto",
+            "barAlignment": 0,
+            "barWidthFactor": 0.6,
+            "drawStyle": "line",
+            "fillOpacity": 10,
+            "gradientMode": "none",
+            "hideFrom": {
+              "legend": false,
+              "tooltip": false,
+              "viz": false
+            },
+            "insertNulls": false,
+            "lineInterpolation": "smooth",
+            "lineWidth": 2,
+            "pointSize": 5,
+            "scaleDistribution": {
+              "type": "linear"
+            },
+            "showPoints": "never",
+            "spanNulls": true,
+            "stacking": {
+              "group": "A",
+              "mode": "none"
+            },
+            "thresholdsStyle": {
+              "mode": "off"
+            }
+          },
+          "mappings": [],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green"
+              }
+            ]
+          },
+          "unit": "short"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 8,
+        "w": 24,
+        "x": 0,
+        "y": 16
+      },
+      "id": 9,
+      "options": {
+        "legend": {
+          "calcs": [
+            "mean",
+            "max",
+            "sum"
+          ],
+          "displayMode": "table",
+          "placement": "right",
+          "showLegend": true
+        },
+        "tooltip": {
+          "hideZeros": false,
+          "mode": "multi",
+          "sort": "none"
+        }
+      },
+      "pluginVersion": "11.6.2",
+      "targets": [
+        {
+          "datasource": "mysql",
+          "editorMode": "code",
+          "format": "time_series",
+          "group": [],
+          "metricColumn": "none",
+          "rawQuery": true,
+          "rawSql": "SELECT\n  date as time,\n  SUM(chat_messages_sent) as 
'Chat Messages Sent',\n  SUM(code_fix_acceptance_event_count) as 'Code Fix 
Accepted Event Count',\n  SUM(code_fix_generation_event_count) as 'Code Fix 
Generated Event Count',\n  SUM(transformation_event_count) as 'Java Transform 
Event Count',\n  SUM(inline_acceptance_count) as 'Inline Suggestion Accepted 
Suggestions',\n  SUM(inline_suggestions_count) as 'Inline Suggestion Count',\n  
SUM(inline_chat_total_event_cou [...]
+          "refId": "A",
+          "select": [
+            [
+              {
+                "params": [
+                  "value"
+                ],
+                "type": "column"
+              }
+            ]
+          ],
+          "sql": {
+            "columns": [
+              {
+                "parameters": [],
+                "type": "function"
+              }
+            ],
+            "groupBy": [
+              {
+                "property": {
+                  "type": "string"
+                },
+                "type": "groupBy"
+              }
+            ],
+            "limit": 50
+          },
+          "timeColumn": "time",
+          "where": [
+            {
+              "name": "$__timeFilter",
+              "params": [],
+              "type": "macro"
+            }
+          ]
+        }
+      ],
+      "title": "Daily AI Interactions",
+      "type": "timeseries"
+    },
+    {
+      "datasource": "mysql",
+      "description": "Code review metrics over time",
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "palette-classic"
+          },
+          "custom": {
+            "axisBorderShow": false,
+            "axisCenteredZero": false,
+            "axisColorMode": "text",
+            "axisLabel": "",
+            "axisPlacement": "auto",
+            "barAlignment": 0,
+            "barWidthFactor": 0.6,
+            "drawStyle": "line",
+            "fillOpacity": 10,
+            "gradientMode": "none",
+            "hideFrom": {
+              "legend": false,
+              "tooltip": false,
+              "viz": false
+            },
+            "insertNulls": false,
+            "lineInterpolation": "smooth",
+            "lineWidth": 2,
+            "pointSize": 5,
+            "scaleDistribution": {
+              "type": "linear"
+            },
+            "showPoints": "never",
+            "spanNulls": true,
+            "stacking": {
+              "group": "A",
+              "mode": "none"
+            },
+            "thresholdsStyle": {
+              "mode": "off"
+            }
+          },
+          "mappings": [],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green"
+              }
+            ]
+          },
+          "unit": "short"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 8,
+        "w": 12,
+        "x": 0,
+        "y": 24
+      },
+      "id": 4,
+      "options": {
+        "legend": {
+          "calcs": [
+            "mean",
+            "max",
+            "sum"
+          ],
+          "displayMode": "table",
+          "placement": "bottom",
+          "showLegend": true
+        },
+        "tooltip": {
+          "hideZeros": false,
+          "mode": "multi",
+          "sort": "none"
+        }
+      },
+      "pluginVersion": "11.6.2",
+      "targets": [
+        {
+          "datasource": "mysql",
+          "format": "time_series",
+          "group": [],
+          "metricColumn": "none",
+          "rawQuery": true,
+          "rawSql": "SELECT\n  date as time,\n  
SUM(code_fix_acceptance_event_count) as 'Code Fix Accepted Event Count',\n  
SUM(code_fix_generation_event_count) as 'Code Fix Generated Event Count',\n  
SUM(code_review_findings_count) as 'Total Findings'\nFROM 
lake._tool_q_dev_user_data\nWHERE $__timeFilter(date)\nGROUP BY date\nORDER BY 
date",
+          "refId": "A",
+          "select": [
+            [
+              {
+                "params": [
+                  "value"
+                ],
+                "type": "column"
+              }
+            ]
+          ],
+          "sql": {
+            "columns": [
+              {
+                "parameters": [],
+                "type": "function"
+              }
+            ],
+            "groupBy": [
+              {
+                "property": {
+                  "type": "string"
+                },
+                "type": "groupBy"
+              }
+            ],
+            "limit": 50
+          },
+          "timeColumn": "time",
+          "where": [
+            {
+              "name": "$__timeFilter",
+              "params": [],
+              "type": "macro"
+            }
+          ]
+        }
+      ],
+      "title": "Code Review Metrics",
+      "type": "timeseries"
+    },
+    {
+      "datasource": "mysql",
+      "description": "Daily acceptance rate of AI suggestions",
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "palette-classic"
+          },
+          "custom": {
+            "axisBorderShow": false,
+            "axisCenteredZero": false,
+            "axisColorMode": "text",
+            "axisLabel": "",
+            "axisPlacement": "auto",
+            "barAlignment": 0,
+            "barWidthFactor": 0.6,
+            "drawStyle": "line",
+            "fillOpacity": 10,
+            "gradientMode": "none",
+            "hideFrom": {
+              "legend": false,
+              "tooltip": false,
+              "viz": false
+            },
+            "insertNulls": false,
+            "lineInterpolation": "smooth",
+            "lineWidth": 2,
+            "pointSize": 5,
+            "scaleDistribution": {
+              "type": "linear"
+            },
+            "showPoints": "never",
+            "spanNulls": true,
+            "stacking": {
+              "group": "A",
+              "mode": "none"
+            },
+            "thresholdsStyle": {
+              "mode": "off"
+            }
+          },
+          "mappings": [],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green"
+              }
+            ]
+          },
+          "unit": "percentunit"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 8,
+        "w": 12,
+        "x": 12,
+        "y": 24
+      },
+      "id": 5,
+      "options": {
+        "legend": {
+          "calcs": [
+            "mean",
+            "max",
+            "min"
+          ],
+          "displayMode": "table",
+          "placement": "bottom",
+          "showLegend": true
+        },
+        "tooltip": {
+          "hideZeros": false,
+          "mode": "multi",
+          "sort": "none"
+        }
+      },
+      "pluginVersion": "11.6.2",
+      "targets": [
+        {
+          "datasource": "mysql",
+          "editorMode": "code",
+          "format": "time_series",
+          "group": [],
+          "metricColumn": "none",
+          "rawQuery": true,
+          "rawSql": "SELECT\n  date as time,\n  
SUM(code_fix_acceptance_event_count) / 
NULLIF(SUM(code_fix_generation_event_count), 0) as 'Code Fix',\n  
SUM(inline_acceptance_count) / NULLIF(SUM(inline_suggestions_count), 0) as 
'Inline Suggestions',\n  SUM(inline_chat_acceptance_event_count) / 
NULLIF(SUM(inline_chat_total_event_count), 0) as 'Inline Chat'\nFROM 
lake._tool_q_dev_user_data\nWHERE $__timeFilter(date)\nGROUP BY date\nORDER BY 
date",
+          "refId": "A",
+          "select": [
+            [
+              {
+                "params": [
+                  "value"
+                ],
+                "type": "column"
+              }
+            ]
+          ],
+          "sql": {
+            "columns": [
+              {
+                "parameters": [],
+                "type": "function"
+              }
+            ],
+            "groupBy": [
+              {
+                "property": {
+                  "type": "string"
+                },
+                "type": "groupBy"
+              }
+            ],
+            "limit": 50
+          },
+          "timeColumn": "time",
+          "where": [
+            {
+              "name": "$__timeFilter",
+              "params": [],
+              "type": "macro"
+            }
+          ]
+        }
+      ],
+      "title": "Daily AI Suggestion Acceptance Rate",
+      "type": "timeseries"
+    },
+    {
+      "datasource": "mysql",
+      "description": "User AI interaction metrics",
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "thresholds"
+          },
+          "custom": {
+            "align": "auto",
+            "cellOptions": {
+              "type": "auto"
+            },
+            "filterable": true,
+            "inspect": false
+          },
+          "mappings": [],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green"
+              }
+            ]
+          }
+        },
+        "overrides": [
+          {
+            "matcher": {
+              "id": "byName",
+              "options": "Acceptance Rate"
+            },
+            "properties": [
+              {
+                "id": "unit",
+                "value": "percentunit"
+              },
+              {
+                "id": "custom.cellOptions",
+                "value": {
+                  "mode": "gradient",
+                  "type": "gauge"
+                }
+              }
+            ]
+          },
+          {
+            "matcher": {
+              "id": "byName",
+              "options": "Inline Chat Accepted Events"
+            },
+            "properties": [
+              {
+                "id": "custom.width",
+                "value": 239
+              }
+            ]
+          },
+          {
+            "matcher": {
+              "id": "byName",
+              "options": "Acceptance Rate (Inline Suggestion)"
+            },
+            "properties": [
+              {
+                "id": "custom.width",
+                "value": 172
+              }
+            ]
+          }
+        ]
+      },
+      "gridPos": {
+        "h": 8,
+        "w": 24,
+        "x": 0,
+        "y": 32
+      },
+      "id": 6,
+      "options": {
+        "cellHeight": "sm",
+        "footer": {
+          "countRows": false,
+          "fields": "",
+          "reducer": [
+            "sum"
+          ],
+          "show": false
+        },
+        "showHeader": true,
+        "sortBy": []
+      },
+      "pluginVersion": "11.6.2",
+      "targets": [
+        {
+          "datasource": "mysql",
+          "editorMode": "code",
+          "format": "table",
+          "group": [],
+          "metricColumn": "none",
+          "rawQuery": true,
+          "rawSql": "SELECT\n  COALESCE(display_name, user_id) as 'User',\n  
SUM(chat_ai_code_lines) as 'Accepted Lines (Chat)',\n  
SUM(transformation_lines_ingested) as 'Lines Ingested (Java Transform)',\n  
SUM(transformation_lines_generated) as 'Lines Generated (Java Transform)',\n  
SUM(transformation_event_count) as 'Event Count (Java Transform)',\n  
SUM(code_review_findings_count) as 'Findings (Code Review)',\n  
SUM(code_fix_accepted_lines) as 'Accepted Lines (Code Fix)',\n  SUM(code [...]
+          "refId": "A",
+          "select": [
+            [
+              {
+                "params": [
+                  "value"
+                ],
+                "type": "column"
+              }
+            ]
+          ],
+          "sql": {
+            "columns": [
+              {
+                "parameters": [],
+                "type": "function"
+              }
+            ],
+            "groupBy": [
+              {
+                "property": {
+                  "type": "string"
+                },
+                "type": "groupBy"
+              }
+            ],
+            "limit": 50
+          },
+          "timeColumn": "time",
+          "where": [
+            {
+              "name": "$__timeFilter",
+              "params": [],
+              "type": "macro"
+            }
+          ]
+        }
+      ],
+      "title": "User Interactions",
+      "type": "table"
+    }
+  ],
+  "preload": false,
+  "refresh": "5m",
+  "schemaVersion": 41,
+  "tags": [
+    "q_dev",
+    "user_data"
+  ],
+  "templating": {
+    "list": []
+  },
+  "time": {
+    "from": "now-30d",
+    "to": "now"
+  },
+  "timepicker": {},
+  "timezone": "utc",
+  "title": "Q Dev User Data Dashboard",
+  "uid": "qdev_user_data",
+  "version": 1
 }
\ No newline at end of file

Reply via email to