构建扫描与分析
源:Gradle Build Scans | Develocity
Build Scan 是 Gradle 提供的交互式构建报告,详细记录构建过程的每个细节,帮助诊断问题和优化性能。
Build Scan 概念
什么是 Build Scan
Build Scan 是一份上传到 Gradle 服务器的详细构建报告,包含:
构建元数据:
- 构建时间和结果
- Gradle 版本和环境
- 插件版本
任务信息:
- 任务执行时间
- 任务依赖关系
- 任务输入输出
性能数据:
- 配置阶段耗时
- 执行阶段耗时
- 依赖解析耗时
依赖信息:
- 依赖树
- 依赖冲突
- 依赖下载
生成 Build Scan
命令行生成
bash
./gradlew build --scan流程:
- 构建完成后提示
Publishing build scan...
https://gradle.com/s/abc123xyz- 首次使用需要接受协议
Do you accept the Gradle Cloud Services license agreement (https://gradle.com/terms-of-service)? [yes, no]
yes- 打开链接查看报告
自动启用
gradle.properties:
properties
# 始终生成 Build Scan
org.gradle.caching=truesettings.gradle.kts:
kotlin
plugins {
id("com.gradle.enterprise") version "3.16"
}
gradleEnterprise {
buildScan {
termsOfServiceUrl = "https://gradle.com/terms-of-service"
termsOfServiceAgree = "yes"
// 自动发布
publishAlways()
}
}Build Scan 内容
Performance 性能
Timeline 时间线:
- 配置阶段
- 依赖解析
- 任务执行
- 输出上传
Task Execution 任务执行:
- 任务列表(按耗时排序)
- 任务状态(执行/缓存/UP-TO-DATE)
- 任务输入输出
Build Cache 构建缓存:
- 缓存命中率
- 缓存保存/加载
- 节省的时间
Configuration 配置:
- 脚本编译时间
- 插件配置时间
- 项目配置时间
Dependencies 依赖
Dependency Tree 依赖树:
- 完整依赖图
- 传递依赖
- 依赖版本
Dependency Resolution 依赖解析:
- 解析时间
- 仓库访问
- 依赖冲突
Downloaded Dependencies 下载:
- 下载的库
- 下载大小
- 下载时间
Infrastructure 基础设施
Environment 环境:
- Gradle 版本
- JVM 版本
- 操作系统
- CPU 和内存
Build Configuration 构建配置:
- gradle.properties
- 环境变量
- JVM 参数
Plugins 插件:
- 应用的插件
- 插件版本
- 插件耗时
使用场景
场景1:诊断慢构建
步骤:
- 生成 Build Scan
bash
./gradlew build --scan查看 Performance → Task Execution
识别最慢的任务
:app:compileDebugKotlin - 12.5s
:app:kaptDebugKotlin - 8.3s
:app:processDebugResources - 3.2s- 优化慢任务
- compileDebugKotlin:考虑模块化
- kaptDebugKotlin:迁移到 KSP
- processDebugResources:减少资源
场景2:分析依赖冲突
步骤:
查看 Dependencies → Dependency Resolution
查找冲突
com.squareup.okhttp3:okhttp
├── 4.12.0 (requested: 4.9.0)
└── 4.12.0 (requested: 4.12.0)查看冲突原因
修复冲突
场景3:缓存效率分析
步骤:
查看 Performance → Build Cache
检查指标
Cacheable tasks: 150
From cache: 120 (80%)
Not from cache: 30 (20%)
Time saved: 45.3s- 优化缓存命中率
对比构建
对比功能
对比两次构建:
- 保存第一次构建的 URL
- 运行第二次构建
- 在 Build Scan 中选择 "Compare with another build"
- 输入第一次构建的 URL
对比内容:
- 构建时间差异
- 任务执行差异
- 缓存命中差异
- 依赖变化
性能趋势
跟踪性能:
Build 1: 45.3s
Build 2: 38.2s (↓ 15.7%)
Build 3: 36.9s (↓ 3.4%)
Build 4: 37.5s (↑ 1.6%)团队协作
分享 Build Scan
生成可分享链接:
bash
./gradlew build --scan分享给团队:
- 复制 URL
- 发送给同事
- 讨论问题
自定义标签
添加标签:
kotlin
gradleEnterprise {
buildScan {
tag("CI")
tag("feature-branch")
value("Git Branch", "feature/login")
value("Git Commit", "abc123")
}
}按标签筛选:
- 查看所有 CI 构建
- 查看特定分支构建
- 分析趋势
隐私和安全
数据上传
上传内容:
- 构建元数据(公开)
- 任务信息(公开)
- 环境信息(公开)
- 源代码(不上传)
隐私设置:
kotlin
gradleEnterprise {
buildScan {
// 仅在 CI 上传
publishOnDemand()
// 或条件发布
if (System.getenv("CI") == "true") {
publishAlways()
}
}
}私有 Build Scan 服务器
Gradle Enterprise(企业版):
kotlin
gradleEnterprise {
server = "https://gradle-enterprise.company.com"
buildScan {
publishAlways()
}
}优势:
- 数据不离开内网
- 更多功能
- 团队协作
实战案例
案例1:CI 性能监控
GitHub Actions:
yaml
name: Build with Scan
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Gradle
uses: gradle/gradle-build-action@v2
with:
gradle-home-cache-cleanup: true
- name: Build with Scan
run: ./gradlew build --scan
env:
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }}案例2:性能回归检测
脚本:
bash
#!/bin/bash
# 基线构建
./gradlew build --scan > baseline.txt
BASELINE_URL=$(grep "https://gradle.com/s/" baseline.txt | awk '{print $1}')
# 当前构建
./gradlew build --scan > current.txt
CURRENT_URL=$(grep "https://gradle.com/s/" current.txt | awk '{print $1}')
echo "Baseline: $BASELINE_URL"
echo "Current: $CURRENT_URL"
echo "Compare: ${CURRENT_URL}/compare/${BASELINE_URL##*/}"案例3:依赖审计
步骤:
- 生成 Build Scan
- 导出依赖列表
- 检查安全漏洞
- 生成报告
Build Scan vs 其他工具
对比
| 特性 | Build Scan | Profile 报告 | Build Analyzer |
|---|---|---|---|
| 详细程度 | ⭐⭐⭐ | ⭐⭐ | ⭐⭐ |
| 交互性 | ⭐⭐⭐ | ⭐ | ⭐⭐⭐ |
| 分享能力 | ⭐⭐⭐ | ⭐ | ❌ |
| 依赖分析 | ⭐⭐⭐ | ⭐ | ⭐ |
| 趋势分析 | ⭐⭐⭐ | ❌ | ❌ |
组合使用
推荐组合:
- Build Scan:全面诊断
- Profile 报告:快速查看
- Build Analyzer:IDE 集成
- Gradle Profiler:基准测试
最佳实践
CI 自动生成:
kotlin
if (System.getenv("CI") == "true") {
gradleEnterprise.buildScan.publishAlways()
}添加有用标签:
kotlin
buildScan {
tag(System.getenv("BRANCH_NAME") ?: "local")
value("Git Commit", gitCommit)
value("PR Number", prNumber)
}定期审查:
- 每周查看构建趋势
- 识别性能退化
- 及时优化
团队分享:
- 分享慢构建链接
- 讨论优化方案
- 记录最佳实践
隐私保护:
- 评估数据敏感性
- 考虑私有部署
- 配置上传策略