Skip to content

Commit acf133b

Browse files
committed
feat(q-dev): add per-user model usage table and models column
Add "Per-User Model Usage" table (panel 11) showing each user's request count and avg prompt/response length per model_id. Also add "Models Used" column to the Per-User Activity table.
1 parent 392ed3c commit acf133b

1 file changed

Lines changed: 63 additions & 1 deletion

File tree

grafana/dashboards/qdev_logging.json

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -541,7 +541,7 @@
541541
"editorMode": "code",
542542
"format": "table",
543543
"rawQuery": true,
544-
"rawSql": "SELECT\n COALESCE(u.display_name, u.user_id) as 'User',\n u.user_id as 'User ID',\n u.chat_events as 'Chat Events',\n u.conversations as 'Conversations',\n ROUND(u.chat_events / NULLIF(u.conversations, 0), 1) as 'Avg Turns',\n COALESCE(c.completion_events, 0) as 'Completion Events',\n COALESCE(c.files_count, 0) as 'Distinct Files',\n ROUND(u.avg_prompt_len) as 'Avg Prompt Len',\n ROUND(u.avg_response_len) as 'Avg Response Len',\n u.steering_count as 'Steering Uses',\n u.spec_count as 'Spec Mode Uses',\n u.first_seen as 'First Seen',\n GREATEST(u.last_seen, COALESCE(c.last_seen, u.last_seen)) as 'Last Seen'\nFROM (\n SELECT\n user_id,\n MAX(display_name) as display_name,\n COUNT(*) as chat_events,\n COUNT(DISTINCT CASE WHEN conversation_id != '' THEN conversation_id END) as conversations,\n AVG(prompt_length) as avg_prompt_len,\n AVG(response_length) as avg_response_len,\n SUM(CASE WHEN has_steering = 1 THEN 1 ELSE 0 END) as steering_count,\n SUM(CASE WHEN is_spec_mode = 1 THEN 1 ELSE 0 END) as spec_count,\n MIN(timestamp) as first_seen,\n MAX(timestamp) as last_seen\n FROM lake._tool_q_dev_chat_log\n WHERE $__timeFilter(timestamp)\n GROUP BY user_id\n) u\nLEFT JOIN (\n SELECT\n user_id,\n COUNT(*) as completion_events,\n COUNT(DISTINCT file_name) as files_count,\n MAX(timestamp) as last_seen\n FROM lake._tool_q_dev_completion_log\n WHERE $__timeFilter(timestamp)\n GROUP BY user_id\n) c ON u.user_id = c.user_id\nORDER BY u.user_id",
544+
"rawSql": "SELECT\n COALESCE(u.display_name, u.user_id) as 'User',\n u.user_id as 'User ID',\n u.chat_events as 'Chat Events',\n u.conversations as 'Conversations',\n ROUND(u.chat_events / NULLIF(u.conversations, 0), 1) as 'Avg Turns',\n COALESCE(c.completion_events, 0) as 'Completion Events',\n COALESCE(c.files_count, 0) as 'Distinct Files',\n ROUND(u.avg_prompt_len) as 'Avg Prompt Len',\n ROUND(u.avg_response_len) as 'Avg Response Len',\n u.steering_count as 'Steering Uses',\n u.spec_count as 'Spec Mode Uses',\n u.models_used as 'Models Used',\n u.first_seen as 'First Seen',\n GREATEST(u.last_seen, COALESCE(c.last_seen, u.last_seen)) as 'Last Seen'\nFROM (\n SELECT\n user_id,\n MAX(display_name) as display_name,\n COUNT(*) as chat_events,\n COUNT(DISTINCT CASE WHEN conversation_id != '' THEN conversation_id END) as conversations,\n AVG(prompt_length) as avg_prompt_len,\n AVG(response_length) as avg_response_len,\n GROUP_CONCAT(DISTINCT CASE WHEN model_id != '' AND model_id IS NOT NULL THEN model_id END ORDER BY model_id SEPARATOR ', ') as models_used,\n SUM(CASE WHEN has_steering = 1 THEN 1 ELSE 0 END) as steering_count,\n SUM(CASE WHEN is_spec_mode = 1 THEN 1 ELSE 0 END) as spec_count,\n MIN(timestamp) as first_seen,\n MAX(timestamp) as last_seen\n FROM lake._tool_q_dev_chat_log\n WHERE $__timeFilter(timestamp)\n GROUP BY user_id\n) u\nLEFT JOIN (\n SELECT\n user_id,\n COUNT(*) as completion_events,\n COUNT(DISTINCT file_name) as files_count,\n MAX(timestamp) as last_seen\n FROM lake._tool_q_dev_completion_log\n WHERE $__timeFilter(timestamp)\n GROUP BY user_id\n) c ON u.user_id = c.user_id\nORDER BY u.user_id",
545545
"refId": "A"
546546
}
547547
],
@@ -775,6 +775,68 @@
775775
],
776776
"title": "Prompt & Response Length Trends",
777777
"type": "timeseries"
778+
},
779+
{
780+
"datasource": "mysql",
781+
"description": "Per-user breakdown of model usage in chat events",
782+
"fieldConfig": {
783+
"defaults": {
784+
"color": {
785+
"mode": "thresholds"
786+
},
787+
"custom": {
788+
"align": "auto",
789+
"cellOptions": {
790+
"type": "auto"
791+
},
792+
"filterable": true,
793+
"inspect": false
794+
},
795+
"mappings": [],
796+
"thresholds": {
797+
"mode": "absolute",
798+
"steps": [
799+
{
800+
"color": "green"
801+
}
802+
]
803+
}
804+
},
805+
"overrides": []
806+
},
807+
"gridPos": {
808+
"h": 8,
809+
"w": 24,
810+
"x": 0,
811+
"y": 64
812+
},
813+
"id": 11,
814+
"options": {
815+
"cellHeight": "sm",
816+
"footer": {
817+
"countRows": false,
818+
"fields": "",
819+
"reducer": [
820+
"sum"
821+
],
822+
"show": false
823+
},
824+
"showHeader": true,
825+
"sortBy": []
826+
},
827+
"pluginVersion": "11.6.2",
828+
"targets": [
829+
{
830+
"datasource": "mysql",
831+
"editorMode": "code",
832+
"format": "table",
833+
"rawQuery": true,
834+
"rawSql": "SELECT\n COALESCE(MAX(display_name), user_id) as 'User',\n CASE WHEN model_id = '' OR model_id IS NULL THEN '(unknown)' ELSE model_id END as 'Model',\n COUNT(*) as 'Requests',\n ROUND(AVG(prompt_length)) as 'Avg Prompt Len',\n ROUND(AVG(response_length)) as 'Avg Response Len'\nFROM lake._tool_q_dev_chat_log\nWHERE $__timeFilter(timestamp)\nGROUP BY user_id, model_id\nORDER BY user_id, COUNT(*) DESC",
835+
"refId": "A"
836+
}
837+
],
838+
"title": "Per-User Model Usage",
839+
"type": "table"
778840
}
779841
],
780842
"preload": false,

0 commit comments

Comments
 (0)