GrimoireLab 是 CHAOSS 社区开发的软件研发分析平台,用于从各类代码仓库、Issue 追踪系统、邮件列表等数据源中提取数据,进行指标计算和可视化分析。
GrimoireLab 是一个开源的软件研发分析工具集,由 Bitergia 公司发起并贡献给 CHAOSS(Community Health Analytics Open Source Software)社区。它提供了一套完整的流水线,从数据采集、存储、富化到可视化,帮助组织和开源社区理解其软件项目的健康状况、贡献者活跃度、开发流程效率等关键指标。
| 能力 | 说明 |
|---|---|
| 多源数据采集 | 支持 30+ 种数据源,包括 Git、GitHub、GitLab、Jira、Slack、邮件列表等 |
| 统一身份管理 | 通过 SortingHat 合并同一人在不同平台的多个身份 |
| 指标计算与富化 | 基于 CHAOSS 指标模型计算社区健康度指标 |
| 可视化仪表盘 | 提供 OpenSearch Dashboards 预置面板 |
| 自动化流水线 | 通过 Mordred 实现全自动数据采集与更新 |
GrimoireLab 采用模块化设计,各组件职责清晰,可独立使用也可组合成完整平台。
┌─────────────────────────────────────────────────────────────┐
│ 数据源 (Data Sources) │
│ Git │ GitHub │ GitLab │ Jira │ Slack │ Gerrit │ Mailing List │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 数据采集层 (Collection) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Perceval │ │ Graal │ │KingArthur│ │ Raw │ │
│ │ (数据抓取)│ │(代码分析)│ │(批量调度)│ │ Indexes │ │
│ └──────────┘ └──────────┘ └──────────┘ └────┬─────┘ │
└──────────────────────────────────────────────────┼─────────┘
│
┌────────────────────┘
▼
┌─────────────────────────────────────────────────────────────┐
│ 数据富化层 (Enrichment) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │GrimoireELK │ │ SortingHat │ │ Cereslib │ │
│ │(指标计算) │ │(身份管理) │ │(数据处理) │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ Enriched │ │
│ │ Indexes │ │
│ └─────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 可视化层 (Visualization) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Sigils │ │ Kidash │ │ Manuscripts │ │
│ │ (仪表盘面板) │ │(面板管理) │ │ (报告生成) │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────┐ │
│ │ OpenSearch/Kibana │ │
│ │ Dashboards │ │
│ └─────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 编排与管理层 (Orchestration) │
│ ┌─────────────┐ │
│ │ Mordred │ │
│ │ (自动化调度) │ │
│ └─────────────┘ │
└─────────────────────────────────────────────────────────────┘
Perceval 是 GrimoireLab 的数据采集核心,负责从各类软件工程工具中抓取原始数据。它采用统一的输出格式,将不同数据源的数据标准化为 JSON 格式。
支持的数据源(30+ 种):
| 类别 | 数据源 |
|---|---|
| 版本控制 | Git、GitHub、GitLab、Gerrit |
| Issue 追踪 | Jira、Bugzilla、Redmine、GitHub Issues、GitLab Issues |
| 协作沟通 | Slack、Mattermost、Rocket.Chat、Gitter、Telegram |
| 邮件列表 | MBox、Pipermail、HyperKitty、Groups.io、NNTP |
| 问答社区 | StackExchange、Askbot、Discourse、MediaWiki |
| CI/CD | Jenkins、GitHub Actions(间接) |
| 其他 | Confluence、Meetup、RSS、Twitter、DockerHub |
Perceval 输出格式:
每个采集到的 item 包含以下通用字段:
{
"backend": "git",
"backend_version": "0.12.0",
"perceval_version": "0.12.24",
"timestamp": 1609459200,
"origin": "https://github.com/chaoss/grimoirelab.git",
"uuid": "abc123...",
"updated_on": 1609459200,
"category": "commit",
"tag": "grimoirelab",
"data": {
// 原始数据,格式取决于数据源
}
}
基本使用示例:
# 采集 Git 仓库提交记录
perceval git https://github.com/chaoss/grimoirelab.git
# 采集 GitHub Issues(需要 Token)
perceval github --api-token ghp_xxx chaoss grimoirelab --category issue
# 采集 Slack 消息
perceval slack <api-token> <channel-id>
# 按时间范围采集
perceval git https://github.com/chaoss/grimoirelab.git --from-date 2024-01-01
GrimoireELK 是连接 Perceval 和 OpenSearch 的桥梁,负责:
数据流转:
Perceval ──► Raw Index ──► Enrichment ──► Enriched Index ──► Dashboard
富化后的关键字段:
| 字段 | 说明 |
|---|---|
author_uuid |
作者唯一标识(来自 SortingHat) |
author_org_name |
作者所属组织 |
author_bot |
是否为机器人账号 |
grimoire_creation_date |
上游创建时间(用于时间序列) |
metadata__enriched_on |
富化时间戳 |
SortingHat 解决了一个核心问题:同一人在不同平台有多个身份。
例如,一个开发者可能:
john@company.comjohn-devJohn DoejdoeSortingHat 将这些身份合并为一个 individual,并支持:
SortingHat 数据模型:
Individual (个人)
├── uuid: 唯一标识
├── profile: 默认显示信息
└── identities[]: 多个平台身份
├── email
├── username
├── source (github, git, slack...)
└── uuid
└── enrollments[]: 组织归属历史
├── organization
├── start_date
└── end_date
Sigils 提供预置的 OpenSearch Dashboards 面板,涵盖:
Mordred 是 GrimoireLab 的"大脑",通过配置文件自动调度整个流水线:
# 典型 Mordred 配置 (setup.cfg)
[general]
short_name = MyProject
update = true
sleep = 3600 # 每小时更新一次
[projects]
projects_file = projects.json
[es_collection]
url = http://localhost:9200
[es_enrichment]
url = http://localhost:9200
[sortinghat]
host = localhost
user = root
password = xxx
database = sortinghat_db
[panels]
kibiter_time_from = now-1y
kibiter_default_index = git
最快捷的部署方式,适合快速体验和小规模使用。
环境要求:
部署步骤:
# 1. 克隆仓库
git clone https://github.com/chaoss/grimoirelab
cd grimoirelab/docker-compose
# 2. 配置项目(编辑 projects.json)
cat > projects.json << 'EOF'
{
"MyProject": {
"git": [
"https://github.com/chaoss/grimoirelab.git"
],
"github": [
"https://github.com/chaoss/grimoirelab"
]
}
}
EOF
# 3. 启动服务
docker-compose up -d
# 4. 访问仪表盘
# OpenSearch Dashboards: http://localhost:8000
# SortingHat 身份管理: http://localhost:8000/identities/
服务组成:
| 容器 | 功能 | 端口 |
|---|---|---|
mordred |
数据采集与富化调度 | - |
opensearch |
数据存储与搜索 | 9200 |
opensearch-dashboards |
可视化界面 | 8000 |
sortinghat |
身份管理服务 | - |
sortinghat-worker |
身份处理队列 | - |
适合只需要基本功能的场景:
docker run --net=host \
-v $(pwd)/projects.json:/home/grimoire/conf/projects.json \
-v $(pwd)/setup.cfg:/home/grimoire/conf/setup.cfg \
-t grimoirelab/grimoirelab
适合深度定制和开发场景。
# 1. 克隆主仓库
git clone https://github.com/chaoss/grimoirelab
cd grimoirelab
# 2. 获取所有子模块(各组件源码)
git submodule update --init --remote
# 3. 进入各组件目录安装
# 例如安装 Perceval:
cd grimoirelab-perceval
pip install -e .
# 安装 GrimoireELK:
cd ../grimoirelab-elk
pip install -e .
在 Hugo 的内部部署中,GrimoireLab 的本地代码库(由 Perceval 抓取后存储)位于:
/home/grimoire/.perceval/repositories/
这是 Perceval 默认的本地缓存目录,存放从远程仓库克隆的 Git 仓库副本。该路径在 Perceval 的配置中可通过 --git-path 参数自定义。
/home/grimoire/
├── .perceval/
│ └── repositories/ # Git 仓库本地缓存
│ ├── github_chaoss_grimoirelab.git/
│ └── github_chaoss_perceval.git/
├── conf/
│ ├── projects.json # 项目配置
│ └── setup.cfg # Mordred 主配置
├── logs/ # 运行日志
└── data/ # 导出数据
# 查看 Mordred 运行状态
docker logs -f grimoirelab_mordred_1
# 手动触发数据采集
perceval git https://github.com/chaoss/grimoirelab.git \
--json-line \
> grimoirelab-commits.json
# 检查 OpenSearch 索引
curl http://localhost:9200/_cat/indices?v
# 查看 SortingHat 数据库
mysql -u root -p sortinghat_db -e "SELECT * FROM individuals LIMIT 10;"
# 导出仪表盘面板
kidash --export panels.json --url http://localhost:9200
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 1. 配置项目 │───►│ 2. 采集数据 │───►│ 3. 身份管理 │───►│ 4. 数据富化 │
│ projects.json│ │ Perceval │ │ SortingHat │ │GrimoireELK │
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
│
▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 7. 持续优化 │◄───│ 6. 生成报告 │◄───│ 5. 可视化 │◄───│ 4. 数据富化 │
│ 调整指标/面板│ │ Manuscripts │ │ Dashboards │ │ Enrichment │
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
Step 1: 配置项目
{
"MyProject": {
"git": [
"https://github.com/company/project-backend.git",
"https://github.com/company/project-frontend.git"
],
"github": [
"https://github.com/company/project-backend",
"https://github.com/company/project-frontend"
],
"jira": [
"https://jira.company.com"
],
"slack": [
"T12345678 C87654321"
]
}
}
Step 2: 数据采集
# 手动采集示例
perceval git https://github.com/company/project-backend.git \
--from-date 2024-01-01 \
--to-date 2024-12-31 \
--output backend-raw.json
# 批量采集(通过 Mordred 自动调度)
Step 3: 身份管理
# 导入身份到 SortingHat
sortinghat load --identities identities.json
# 合并身份(将多个邮箱关联到同一人)
sortinghat merge --uuid abc123 def456
# 添加组织归属
sortinghat enroll --uuid abc123 --organization "Company A" \
--from 2023-01-01 --to 2024-12-31
Step 4-5: 富化与可视化
由 Mordred 自动完成,或手动执行:
# 富化 Git 数据
p2o.py --enrich --index git_raw --index-enrich git \
-e http://localhost:9200 --no_inc --debug \
git https://github.com/company/project-backend.git
# 导入预置面板
kidash --import panels/git.json --url http://localhost:9200
GrimoireLab 实现了 CHAOSS 指标模型 中的大部分指标,分为四个维度:
| 指标 | GrimoireLab 实现 | 说明 |
|---|---|---|
| 贡献者数量 | git_authors, github_issue_authors |
按时间窗口统计 |
| 提交频率 | git_commits |
每日/每周/每月提交数 |
| 累积代码变更 | git_lines_added, git_lines_removed |
代码增删行数 |
| 指标 | GrimoireLab 实现 | 说明 |
|---|---|---|
| 贡献者地域分布 | 基于邮箱域名推断 | 识别组织归属 |
| 新人 onboarding 时间 | 首次提交到首次合并的时长 | 社区友好度 |
| 事件参与者多样性 | Meetup/活动数据源 | 线下活动覆盖 |
| 指标 | GrimoireLab 实现 | 说明 |
|---|---|---|
| Issue 响应时间 | time_to_first_attention |
首次响应时长 |
| PR 合并时间 | time_to_merge |
从提交到合并 |
| 代码评审参与度 | github_pull_requests + review 数据 |
评审者数量 |
| 发布频率 | 基于 Git tag 或 release 数据 | 版本发布节奏 |
| 指标 | GrimoireLab 实现 | 说明 |
|---|---|---|
| 代码审查覆盖率 | 有/无评审的 PR 比例 | 质量门禁 |
| 依赖项更新频率 | 需结合依赖扫描工具 | 技术债务 |
| 许可证合规 | Graal + Colic 分析 | 许可证冲突检测 |
如需支持 Perceval 未内置的数据源,可开发自定义 Backend:
# 自定义 Backend 示例结构
from perceval.backend import Backend, BackendCommand
class MyCustomBackend(Backend):
"""自定义数据源采集器"""
version = '0.1.0'
def fetch(self, category=CATEGORY_ITEM, from_date=None, to_date=None):
"""实现数据采集逻辑"""
# 1. 连接数据源 API
# 2. 分页获取数据
# 3. 标准化为 Perceval Item 格式
pass
@classmethod
def has_resuming(cls):
return True
@classmethod
def has_archiving(cls):
return True
# GrimoireELK 自定义 Enricher
from grimoire_elk.enriched.enrich import Enrich
class MyEnricher(Enrich):
"""自定义数据富化器"""
def get_field_author(self):
return "data.author"
def get_rich_item(self, item):
"""定义富化后的字段结构"""
eitem = super().get_rich_item(item)
# 添加自定义字段
eitem['custom_metric'] = self.calculate_custom_metric(item)
eitem['team'] = self.map_author_to_team(item['data']['author'])
return eitem
使用 Kidash 导出/导入面板:
# 导出现有面板
kidash --export my-panel.json --url http://localhost:9200
# 修改面板 JSON(添加可视化组件)
# ...
# 导入新面板
kidash --import my-panel.json --url http://localhost:9200
| 数据规模 | 建议配置 | 优化策略 |
|---|---|---|
| < 10 个仓库 | 单节点 Docker Compose | 默认配置 |
| 10-100 个仓库 | 独立 OpenSearch 集群 | 分片数 = 节点数 |
| > 100 个仓库 | 多节点 + 分布式采集 | KingArthur 批量调度 |
# opensearch.yml 关键配置
cluster.name: grimoirelab
node.name: node-1
# 内存锁定(防止交换)
bootstrap.memory_lock: true
# 分片配置
index.number_of_shards: 3
index.number_of_replicas: 1
# 缓存优化
indices.fielddata.cache.size: 30%
indices.query.bool.max_clause_count: 8192
# 增量采集(只抓取新数据)
perceval git https://github.com/xxx/xxx.git --from-date $(date -d '1 day ago' +%Y-%m-%d)
# 并行采集多个仓库
# 使用 KingArthur 或自定义脚本实现
Q: OpenSearch 启动失败,提示内存不足
# 增加 vm.max_map_count
sudo sysctl -w vm.max_map_count=262144
# 永久生效:编辑 /etc/sysctl.conf
echo "vm.max_map_count=262144" | sudo tee -a /etc/sysctl.conf
Q: Perceval 采集 GitHub 数据时遇到 API 限流
# 使用 Token 认证(提高限流额度)
perceval github --api-token ghp_xxx owner repo
# 或使用 GitHub App 认证(更高额度)
Q: SortingHat 身份合并后仪表盘数据未更新
# 需要重新富化数据以应用新的身份关联
# Mordred 会自动处理,手动触发:
p2o.py --enrich --index git_raw --index-enrich git -e http://localhost:9200 \
--refresh-identities git <repo-url>
Q: 仪表盘显示"No results found"
curl localhost:9200/_cat/indicesprojects.json 配置与数据源 URL 匹配| 组件 | 仓库 | 说明 |
|---|---|---|
| Perceval | grimoirelab-perceval | 数据采集 |
| GrimoireELK | grimoirelab-elk | 数据富化 |
| SortingHat | grimoirelab-sortinghat | 身份管理 |
| Sigils | grimoirelab-sigils | 仪表盘面板 |
| Mordred | grimoirelab-mordred | 自动化编排 |
| Graal | grimoirelab-graal | 代码分析 |
| KingArthur | grimoirelab-kingarthur | 批量调度 |
Dueñas S, Cosentino V, Gonzalez-Barahona JM, et al. 2021.
GrimoireLab: A toolset for software development analytics.
PeerJ Computer Science 7:e601.
https://doi.org/10.7717/peerj-cs.601
GrimoireLab 是开源社区和企业进行软件研发分析的强大工具集。其核心优势在于:
对于 Hugo 的内部部署,关键配置点包括:
/home/grimoire/.perceval/repositories/projects.json 配置需要分析的项目和数据源