
技术速递|Copilot Usage Advanced Dashboard 教程
作者:Xuefeng Yin排版:Alan Wang形成单一的数据面板展示,从不同的维度展现 Copilot 在多个 Organzations 和 Teams 中的使用情况。特性概括如下:对数据进行持久化存储到 Elasticsearch 中,并基于 Grafana 进行数据可视化,。因此,可以自由选择期望进行数据可视化的时间段,如过去一整年、或者特定的月份。所有存储的数据都包含了 Organiz
作者:Xuefeng Yin
排版:Alan Wang
Copilot Usage Advanced Dashboard 是为了充分利用 GitHub Copilot API 中的几乎所有数据,用到的 API 有:
形成单一的数据面板展示,从不同的维度展现 Copilot 在多个 Organzations 和 Teams 中的使用情况。特性概括如下:
-
对数据进行持久化存储到 Elasticsearch 中,并基于 Grafana 进行数据可视化,而不仅仅是展示过去的28天数据。因此,可以自由选择期望进行数据可视化的时间段,如过去一整年、或者特定的月份。
-
所有存储的数据都包含了 Organization 和 Team 字段,方便通过变量过滤器进行数据筛选。
-
对每一份数据生成唯一 hash key,每次获取最新数据时,会更新已经存储的数据。
-
可根据实际需求,对 Grafana 的 dashboards 中的 visualizations 进行调整、删除。
-
可以基于 Grafana 的内置告警功能,设定 alert 规则,对一些不合适的使用行为进行告警,比如对长期不活跃的用户发送告警信息。
-
可以方便的与第三方系统集成,不论是从 Elasticsearch 中抽取数据到别的数据可视化平台进行数据可视化,或者在 Copilot Usage Advanced Dashboard 中添加别的数据源进行联合数据可视化。
Online Demo Environment✨
设计了2款 dashboards,二者可以在 Grafana 中同时存在。
Copilot Usage Advanced Dashboard
Copilot Metrics Viewer 兼容 dashboard
如果你很熟悉 copilot-metrics-viewer 项目,那么请体验这个 dashboard,并在后续的安装中使用此 dashboard。
-
地址:http://20.89.179.123:3000/d/be7hpbvvhst8gc/copilot-usage-advanced-dashboard
-
用户名:
demouser
-
密码:
demouser
Copilot Usage Advanced Dashboard Original
新设计 dashboard
-
地址:http://20.89.179.123:3000/d/a98455d6-b401-4a53-80ad-7af9f97be6f4/copilot-usage-advanced-dashboard-original
-
用户名:
demouser
-
密码:
demouser
条件变量
支持四种过滤条件,分别是:
-
Organzation
-
Team
-
Language
-
Editor
变量的选择会动态关联到数据
特性
Copilot Usage Advanced Dashboard
1 Organization
先基于 List teams of an onganization 获取 Organization 下的所有 teams,然后基于 Get a summary of Copilot usage for a team,对 Organization 下所有的 teams 的数据求和并计算,得到完整的 Organization 层面数据。
-
Acceptance Rate Average =
sum(total_acceptances_count) / sum(total_suggestions_count)
-
Cumulative Number of Acceptence (Count) =
sum(total_acceptances_count)
-
Cumulative Number of Suggestions (Count) =
sum(total_suggestions_count)
-
Cumulative Number of Lines of Code Accepted =
sum(total_lines_accepted)
-
Acceptance Rate (%) =
total_acceptances_count / total_suggestions_count
-
Total Active Users = total_active_users
-
Total Suggestions & Acceptances Count =
total_suggestions_count
&total_acceptances_count
-
Total Lines Suggested & Accepted =
total_lines_suggested
&total_lines_accepted
2 Teams
基于Get a summary of Copilot usage for a team中的 breakdown 数据进行分析,对数据按照 Teams 进行数据聚合,得到不同的 Teams 的数据对比。
-
Number of Teams =
unique_count(team_slug)
-
Top Teams by Accepted Prompts =
sum(acceptances_count).groupby(team_slug)
-
Top Teams by Acceptance Rate =
sum(acceptances_count).groupby(team_slug) / sum(suggestions_count).groupby(team_slug)
-
Teams Breakdown =
sum(*).groupby(team_slug)
3 Languages
基于Get a summary of Copilot usage for a team中的breakdown数据进行分析,对数据按照Languages进行数据聚合,得到不同的Languages的数据对比。
-
Number of Languages=
unique_count(language)
-
Top Languages by Accepted Prompts =
sum(acceptances_count).groupby(language)
-
Top Languages by Acceptance Rate =
sum(acceptances_count).groupby(language) / sum(suggestions_count).groupby(language)
-
Languages Breakdown =
sum(*).groupby(language)
4 Editors
基于 Get a summary of Copilot usage for a team 中的 breakdown 数据进行分析,对数据按照 Editors 进行数据聚合,得到不同的 Editors 的数据对比。
-
Number of Editors =
unique_count(editor)
-
Top Editors by Accepted Prompts =
sum(acceptances_count).groupby(editor)
-
Top Editors by Acceptance Rate =
sum(acceptances_count).groupby(editor) / sum(suggestions_count).groupby(editor)
-
Editors Breakdown =
sum(*).groupby(editor)
5 Copilot Chat
基于 Get a summary of Copilot usage for a team 的数据进行分析,得到 Copilot Chat 的使用情况。
-
Acceptance Rate Average =
sum(total_chat_acceptances) / sum(total_chat_turns)
-
Cumulative Number of Acceptances =
sum(total_chat_acceptances)
-
Cumulative Number of Turns =
sum(total_chat_turns)
-
Total Acceptances | Total Turns Count =
total_chat_acceptances
|total_chat_turns
-
Total Active Copilot Chat Users =
total_active_chat_users
6 Seat Analysis
基于 Get Copilot seat information and settings for an organization 以及 List all Copilot seat assignments for an organization 的数据分析,把席位分配情况和使用情况进行统一呈现。
-
Copilot Plan Type =
count(seats).groupby(plan_type)
-
Total =
seat_breakdown.total
-
Active in this Cycle =
seat_breakdown.active_this_cycle
-
Assigned But Never Used =
last_activity_at.isnan()
-
Inactive in this Cycle =
seat_breakdown.inactive_this_cycle
-
Ranking of Inactive Users ( ≥ 2 days ) =
today - last_activity_at
-
All assigned seats =
*
7 Breakdown Heatmap
基于 Get a summary of Copilot usage for a team 中的breakdown 数据进行分析,从 Languages 和 Editors 二个维度进行数据分析。可以清晰的看到什么样的 Languages 和 Editors 的组合可以实现最好的 Copilot 使用效果。
-
Active Users Count (Group by Language) =
active_users.groupby(language)
-
Accept Rate by Count (%) =
sum(acceptances_count).groupby(language) / sum(suggestions_count).groupby(language)
-
Accept Rate by Lines (%) =
sum(lines_accepted).groupby(language) / sum(lines_suggested).groupby(language)
-
Active Users Count (Group by Editor) = a
ctive_users.groupby(editor)
-
Accept Rate by Count (%) =
sum(acceptances_count).groupby(editor) / sum(suggestions_count).groupby(editor)
-
Accept Rate by Lines (%) =
sum(lines_accepted).groupby(editor) / sum(lines_suggested).groupby(editor)
Copilot Usage Advanced Dashboard Original
1 Copilot Seat Info & Top Languages
-
您可以查看席位分布情况、企业版还是商务版?以及总体激活趋势。对于不使用 Copilot 的用户,将根据不活动时间长短进行排名,并列出从未激活的用户。
-
根据使用情况对语言和团队进行排名
2 Copilot Usage Total Insight
您可以根据计数、行数和聊天量分析推荐总数和采用率趋势。
3 Copilot Usage Breakdown Insight
你可以分析 Copilot 在不同语言,不同编辑器组合下的效果。
特别说明
本文所描述一切内容都是基于 all-in-one 架构。在生产环境中,可以根据实际需求,拆分成分布式架构。
原理
技术栈
依赖的技术栈:
-
VM
-
Docker
-
Elasticsearch
-
Grafana
-
Python3
部署
所有操作在 VM 中执行
先决条件
一切都在本地并且免费(VM 除外)
唯一需要的是:
-
一个 VM
-
内存:建议 16G
-
操作系统:Ubuntu 22.04(推荐,其他操作系统除了安装 Docker 外没有区别)
-
端口:需要释放
3000
端口供 Grafana 使用,22
端口可以自行确定。
-
其他一切都基于现有的东西,或者基于开源软件,无需额外费用,例如:
-
启用了 Copilot 的 GitHub Organzations(我相信,您已经拥有它)
-
Docker(社区版本就足够了)
-
Elasticsearch(社区版本就足够了)
-
Grafana(社区版本就足够了,不需要 Grafana 云帐户)
-
从此项目构建的 CPUAD-Updater(MIT 许可证)
Docker
安装方式参考 Install Docker Engine,对于 Ubuntu 22.04,可以使用如下命令:
apt install docker.io
验证
docker version
得到如下内容,表示 ok
Client:
Version: 24.0.7
API version: 1.43
Go version: go1.21.1
Git commit: 24.0.7-0ubuntu2~22.04.1
Built: Wed Mar 13 20:23:54 2024
OS/Arch: linux/amd64
Context: default
Server:
Engine:
Version: 24.0.7
API version: 1.43 (minimum version 1.12)
Go version: go1.21.1
Git commit: 24.0.7-0ubuntu2~22.04.1
Built: Wed Mar 13 20:23:54 2024
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.7.12
GitCommit:
runc:
Version: 1.1.12-0ubuntu2~22.04.1
GitCommit:
docker-init:
Version: 0.19.0
GitCommit:
下载源码
所有工作内容都放在 /srv
目录中,点击下载 zip 压缩包,解压后重命名文件夹名称为 copilot-usage-advanced-dashboard
,或者直接 git clone
cd /srv
git clone https://github.com/satomic/copilot-usage-advanced-dashboard.git
cd copilot-usage-advanced-dashboard
验证
ls -ltr
得到如下内容,表示 ok
total 64
-rw-r--r-- 1 root root 100 Dec 16 11:22 fetch.sh
-rw-r--r-- 1 root root 56 Dec 16 11:22 docker_build.sh
-rw-r--r-- 1 root root 1063 Dec 16 11:22 LICENSE
-rw-r--r-- 1 root root 1031 Dec 16 11:22 Dockerfile
-rw-r--r-- 1 root root 193 Dec 16 11:22 push.sh
drwxr-xr-x 2 root root 4096 Dec 16 11:22 mapping
-rw-r--r-- 1 root root 22 Dec 16 11:32 requirements.txt
-rw-r--r-- 1 root root 996 Dec 16 13:44 log_utils.py
drwxr-xr-x 2 root root 4096 Dec 17 00:18 grafana
-rw-r--r-- 1 root root 2571 Dec 17 00:18 gen_grafana_model.py
-rw-r--r-- 1 root root 22500 Dec 17 01:40 main.py
Elasticsearch
安装
如果你已经有了 ES,那么可以跳过本步骤,直接到下一步。
ES 不会暴露到 VM 的外部,因此不用开启xpack.security.enabled
- 为 Elasticsearch 创建数据持久化目录和配置文件目录:
mkdir -p /srv/elasticsearch/data /srv/elasticsearch/confi
- 并授予所有用户读写权限。
chmod -R a+rw /srv/elasticsearch
- 在
/srv/elasticsearch/config/
目录下创建elasticsearch.yml
配置文件:
cat >> /srv/elasticsearch/config/elasticsearch.yml << EOF
network.host: 0.0.0.0
node.name: single-node
cluster.name: es-docker-cluster
path.data: /usr/share/elasticsearch/data
path.logs: /usr/share/elasticsearch/logs
discovery.type: single-node
bootstrap.memory_lock: true
EOF
- 使用以下命令启动 Elasticsearch,并绑定数据目录和配置文件:
docker run -itd --restart always --name es \
-p 9200:9200 \
-e "xpack.security.enabled=false" \
-e "ES_JAVA_OPTS=-Xms4g -Xmx4g" \
-v /srv/elasticsearch/data:/usr/share/elasticsearch/data \
-v /srv/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml:ro \
docker.elastic.co/elasticsearch/elasticsearch:8.17.0
- 访问测试
curl http://localhost:9200
得到如下内容,表示 ok
{
"name": "single-node",
"cluster_name": "es-docker-cluster",
"cluster_uuid": "oO3mfjYWTZ6VZFSClDiSLA",
"version": {
"number": "8.17.0",
"build_flavor": "default",
"build_type": "docker",
"build_hash": "2b6a7fed44faa321997703718f07ee0420804b41",
"build_date": "2024-12-11T12:08:05.663969764Z",
"build_snapshot": false,
"lucene_version": "9.12.0",
"minimum_wire_compatibility_version": "7.17.0",
"minimum_index_compatibility_version": "7.0.0"
},
"tagline": "You Know, for Search"
}
创建 index
- 确认当前在正确的路径中
cd /srv/copilot-usage-advanced-dashboard
- 执行脚本,创建 index
bash create_es_indexes.sh
得到如下内容,表示 ok
{"acknowledged":true,"shards_acknowledged":true,"index":"copilot_usage_total"}
{"acknowledged":true,"shards_acknowledged":true,"index":"copilot_usage_breakdown"}
{"acknowledged":true,"shards_acknowledged":true,"index":"copilot_usage_breakdown_chat"}
{"acknowledged":true,"shards_acknowledged":true,"index":"copilot_seat_info_settings"}
{"acknowledged":true,"shards_acknowledged":true,"index":"copilot_seat_assignments"}
- 检查
curl -X GET http://localhost:9200/_cat/indices?v
得到如下内容,表示 ok
health status index uuid pri rep docs.count docs.deleted store.size pri.store.size dataset.size
yellow open copilot_usage_total XrOEfAngTS60VsuUz3Lbrw 1 1 0 0 227b 227b 227b
yellow open copilot_seat_info_settings WtOBdBNUQRqua7wi7VANeQ 1 1 0 0 227b 227b 227b
yellow open copilot_
seat
_assignments lK5t4SwASZizPQ_
W4NX4KQ 1 1 0 0 227b 227b 227b
yellow open copilot_usage_breakdown xE6tkg5GQEOP-EP8pwAkYg 1 1 0 0 227b 227b 227b
yellow open copilot_usage_breakdown_chat 6R_1cdlIQQOCv4BoHPqXCw 1 1 0 0 227b 227b 227b
Grafana
安装
如果你已经有了 Grafana,那么可以跳过本步骤,直接到下一步。
- 创建数据路径
mkdir -p /srv/grafana/data
chmod -R a+rw /srv/grafana/data
- 启动
docker run -itd --restart always --name=grafana \
--net=host \
-p 3000:3000 \
-v /srv/grafana/data:/var/lib/grafana \
-e "GF_LOG_LEVEL=debug" \
grafana/grafana:11.4.0
- 访问 Grafana
-
访问地址:
http://<PUBLIC_IP_OF_YOUR_VM>:3000
-
默认用户名密码为
admin
/admin
,请修改密码
创建 Admin Token
- 管理员访问 Administration → Users and access → Service accounts
- 输入 Display name,Role 选择
Admin
,点击 Create
- 点击 Add service account token
- 点击 Generate token
- Copy to clipboard and close
- 现在,你获得了你的 Grafana Token “
<your_grafana_token>
”,请保存后它,并设置为VM中的环境变量,接下来步骤会用到。
export GRAFANA_TOKEN="<your_grafana_token>"
通过 API 添加 Data sources
- 确认当前在正确的路径中
cd /srv/copilot-usage-advanced-dashboard
- 执行脚本,添加 data sources
bash add_grafana_data_sources.sh
- 访问 Grafana UI,确认添加成功
生成 Dashboard Json Model
- 确认当前在正确的路径中
cd /srv/copilot-usage-advanced-dashboard
- 执行脚本,生成 Grafana json 模型,如下2个命令,执行其中的一条就可以
# 生成 Copilot Usage Advanced Dashboard
python3 gen_grafana_model.py --template=grafana/dashboard-template.json
# Copilot Usage Advanced Dashboard Original
python3 gen_grafana_model.py --template=grafana/dashboard-template-original.jso
得到输出
Model saved to grafana/dashboard-model-2024-12-17.json, please import it to Grafana
导入产生的 Json 创建 Dashboard
- 下载产生的文件到本地
scp root@<PUBLIC_IP_OF_YOUR_VM>:/srv/copilot-usage-advanced-dashboard/grafana/dashboard-model-*.json .
dashboard-model-2024-12-17.json 100% 157KB 243.8KB/s 00:00
dashboard-model-data_sources_name_uid_mapping-2024-12-17.json 100% 210 1.1KB/s 00:00
- 复制产生的 json 文件,导入到 Grafana
选择文件导入,或者直接粘贴内容
- Import
- 恭喜你,此时获得了完整的 Dashboard,但是应该还没有数据。接下来,运行核心程序。
cpuad-updater
是 Copilot Usage Advanced Dashboard Updater 的首字符简写
选项1:✨Docker 方式运行(推荐)
参数说明
-
GITHUB_PAT
:-
你的账户需要具有 Organzations 的 Owner 权限。
-
Create a personal access token (classic)在
manage_billing:copilot, read:enterprise, read:org
作用域。 -
如果遇到了 PAT 权限问题,在组织的 Settings-Personal access tokens 中 Allow access via fine-grained personal access tokens。
-
请替换
<YOUR_GITHUB_PAT>
为实际值。
-
-
ORGANIZATION_SLUGS
:希望被监控的所有Organzation的Slug,可以是一个,也可以是以,(英文符号)分割的多个。如果你使用的是 Copilot Standalone,那么此处请使用你的 Standalone Slug,并且以standalone:
作为前缀,例如standalone:YOUR_STANDALONE_SLUG
。请替换<YOUR_ORGANIZATION_SLUGS>
为实际值。例如,如下类型的值都是支持的: -
myOrg1
-
myOrg1,myOrg2
-
standalone:myStandaloneSlug
-
myOrg1,standalone:myStandaloneSlug
-
LOG_PATH
:日志存储位置,不建议修改。如果修改需要同步修改-v
数据卷映射。 -
EXECUTION_INTERVAL
:更新间隔,默认为每1
小时更新一次程序。
docker run -itd \
--net=host \
--restart=always \
--name cpuad \
-e GITHUB_PAT="<YOUR_GITHUB_PAT>" \
-e ORGANIZATION_SLUGS="<YOUR_ORGANIZATION_SLUGS>" \
-e LOG_PATH="logs" \
-e EXECUTION_INTERVAL=1 \
-e ELASTICSEARCH_URL="http://localhost:9200" \
-v /srv/cpuad-updater-logs:/app/logs \
satomic/cpuad-updater
选项2:源码运行
- 确认当前在正确的路径中
cd /srv/copilot-usage-advanced-dashboard
- 安装依赖
python3 -m pip install -r requirements.txt
- 设置环境变量。如果你使用的是 Copilot Standalone,那么此处请使用你的 Standalone Slug,并且以
standalone:
作为前缀,例如standalone:YOUR_STANDALONE_SLUG
。
export GITHUB_PAT="<YOUR_GITHUB_PAT>"
export ORGANIZATION_SLUGS="<YOUR_ORGANIZATION_SLUGS>"
- 执行
python3 main.py
- 输出日志
2024-12-17 05:32:22,292 - [INFO] - Data saved to logs/2024-12-17/nekoaru_level3-team1_copilot_usage_2024-12-17.json
2024-12-17 05:32:22,292 - [INFO] - Fetched Copilot usage for team: level3-team1
2024-12-17 05:32:22,293 - [INFO] - Data saved to logs/2024-12-17/nekoaru_all_teams_copilot_usage_2024-12-17.json
2024-12-17 05:32:22,293 - [INFO] - Processing Copilot usage data for organization: nekoaru
2024-12-17 05:32:22,293 - [INFO] - Processing Copilot usage data for team: level1-team1
2024-12-17 05:32:22,293 - [WARNING] - No Copilot usage data found for team: level1-team1
2024-12-17 05:32:22,293 - [INFO] - Processing Copilot usage data for team: level2-team1
2024-12-17 05:32:22,293 - [WARNING] - No Copilot usage data found for team: level2-team1
2024-12-17 05:32:22,293 - [INFO] - Processing Copilot usage data for team: level2-team2
2024-12-17 05:32:22,293 - [WARNING] - No Copilot usage data found for team: level2-team2
2024-12-17 05:32:22,293 - [INFO] - Processing Copilot usage data for team: level3-team1
2024-12-17 05:32:22,293 - [WARNING] - No Copilot usage data found for team: level3-team1
2024-12-17 05:32:22,293 - [INFO] - Sleeping for 6 hours before next execution...
2024-12-17 05:32:22,293 - [INFO] - Heartbeat: still running...
恭喜完成🎉
当前 VM 中的应用运行状态
此时此刻,在 VM 中,你应该能看到3个容器处于运行中(如果你都是基于 docker 从0开始部署的话),如下:
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1edffd12a522 satomic/cpuad-updater:20241221 "python3 main.py" 23 hours ago Up 10 hours cpuad
b19e467d48f1 grafana/grafana:11.4.0 "/run.sh" 25 hours ago Up 10 hours grafana
ee35b2a340f1 docker.elastic.co/elasticsearch/elasticsearch:8.17.0 "/bin/tini -- /usr/l…" 3 days ago Up 10 hours 0.0.0.0:9200->9200/tcp, :::9200->9200/tcp, 9300/tcp es
查看 Dashboard
此时,回到 Grafana 页面,刷新,此时,应该可以看到数据了。
或者
acceptances_count
更多推荐
所有评论(0)