name: 分析回归 description: 基于OpenShift发布的回归管理指标对组件健康进行评分
分析回归
本技能提供功能,通过分析回归管理指标来分析和评分OpenShift发布的组件健康。它通过分析回归覆盖率、回归及时性和解决速度,评估组件管理测试回归的效果。
何时使用本技能
当您需要以下操作时使用本技能:
- 为特定OpenShift发布评分组件健康
- 识别在回归处理方面需要帮助的组件
- 跨发布跟踪回归和解决效率
- 生成组件质量记分卡
- 为利益相关者生成健康报告(文本或HTML)
重要提示:评分是主观的,并非对团队表现的批评。这旨在帮助识别需要帮助的地方,并跟踪我们改进回归响应率的进展。
先决条件
-
Python 3 安装
- 检查是否安装:
which python3 - 需要Python 3.6或更高版本
- 在大多数系统中已预安装
- 检查是否安装:
-
网络访问
- 脚本需要网络访问以连接到组件健康API和发布日期API
- 确保可以进行HTTPS请求
-
所需脚本
plugins/teams/skills/get-release-dates/get_release_dates.pyplugins/teams/skills/list-regressions/list_regressions.pyplugins/teams/skills/analyze-regressions/generate_html_report.py(用于HTML报告)plugins/teams/skills/analyze-regressions/report_template.html(用于HTML报告)
实施步骤
步骤 1:解析参数
从命令参数中提取发布版本和可选的组件过滤器:
- 发布格式:“X.Y”(例如,“4.17”,“4.21”)
- 组件(可选):要过滤的组件名称列表
参数解析示例:
/teams:analyze-regressions 4.17
/teams:analyze-regressions 4.21 --components Monitoring etcd
步骤 2:获取发布日期
运行get_release_dates.py脚本来确定发布的开发窗口:
python3 plugins/teams/skills/get-release-dates/get_release_dates.py \
--release 4.17
预期输出(标准输出上的JSON):
{
"release": "4.17",
"development_start": "2024-05-17T00:00:00Z",
"feature_freeze": "2024-08-26T00:00:00Z",
"code_freeze": "2024-09-30T00:00:00Z",
"ga": "2024-10-29T00:00:00Z"
}
处理步骤:
- 解析JSON输出
- 提取
development_start日期 - 转换为YYYY-MM-DD格式 - 提取
ga日期 - 转换为YYYY-MM-DD格式(对于开发中的发布可能为null) - 适当处理null日期:
development_start:通常始终存在;如果为null,省略--start参数ga:对于开发中的发布将为null;如果为null,省略--end参数
日期转换示例:
"2024-05-17T00:00:00Z" → "2024-05-17"
null → 不使用此参数
步骤 3:执行列出回归脚本
运行list_regressions.py脚本并带有适当的参数:
python3 plugins/teams/skills/list-regressions/list_regressions.py \
--release 4.17 \
--start 2024-05-17 \
--end 2024-10-29 \
--short
参数规则:
--release:始终必需(从步骤1)--components:可选,仅在用户指定时使用(从步骤1)--start:使用步骤2中的development_start日期(如果不为null)- 始终应用,无论是GA发布还是开发中的发布
- 排除开发开始前关闭的回归(与此发布无关)
--end:使用步骤2中的ga日期(仅当不为null时)- 仅对GA发布应用(当GA日期不为null时)
- 排除GA后打开的回归(发布后回归,通常未监控/处理)
- 不对开发中的发布应用(当GA日期为null时)
--short:始终包含此标志- 从响应中排除回归数据数组
- 仅包括汇总统计
- 防止大型数据集时的截断问题
GA发布示例(4.17):
python3 plugins/teams/skills/list-regressions/list_regressions.py \
--release 4.17 \
--start 2024-05-17 \
--end 2024-10-29 \
--short
开发中发布示例(4.21,GA为null):
python3 plugins/teams/skills/list-regressions/list_regressions.py \
--release 4.21 \
--start 2025-09-02 \
--short
带组件过滤器的示例:
python3 plugins/teams/skills/list-regressions/list_regressions.py \
--release 4.21 \
--components Monitoring etcd \
--start 2025-09-02 \
--short
步骤 4:解析输出结构
脚本输出JSON到标准输出,结构如下:
{
"summary": {
"total": 62,
"triaged": 59,
"triage_percentage": 95.2,
"filtered_suspected_infra_regressions": 8,
"time_to_triage_hrs_avg": 68,
"time_to_triage_hrs_max": 240,
"time_to_close_hrs_avg": 168,
"time_to_close_hrs_max": 480,
"open": {
"total": 2,
"triaged": 1,
"triage_percentage": 50.0,
"time_to_triage_hrs_avg": 48,
"time_to_triage_hrs_max": 48,
"open_hrs_avg": 120,
"open_hrs_max": 200
},
"closed": {
"total": 60,
"triaged": 58,
"triage_percentage": 96.7,
"time_to_triage_hrs_avg": 72,
"time_to_triage_hrs_max": 240,
"time_to_close_hrs_avg": 168,
"time_to_close_hrs_max": 480,
"time_triaged_closed_hrs_avg": 96,
"time_triaged_closed_hrs_max": 240
}
},
"components": {
"ComponentName": {
"summary": {
"total": 15,
"triaged": 13,
"triage_percentage": 86.7,
"filtered_suspected_infra_regressions": 0,
"time_to_triage_hrs_avg": 68,
"time_to_triage_hrs_max": 180,
"time_to_close_hrs_avg": 156,
"time_to_close_hrs_max": 360,
"open": {
"total": 1,
"triaged": 0,
"triage_percentage": 0.0,
"time_to_triage_hrs_avg": null,
"time_to_triage_hrs_max": null,
"open_hrs_avg": 72,
"open_hrs_max": 72
},
"closed": {
"total": 14,
"triaged": 13,
"triage_percentage": 92.9,
"time_to_triage_hrs_avg": 68,
"time_to_triage_hrs_max": 180,
"time_to_close_hrs_avg": 156,
"time_to_close_hrs_max": 360,
"time_triaged_closed_hrs_avg": 88,
"time_triaged_closed_hrs_max": 180
}
}
}
}
}
关键 - 使用汇总计数:
- **始终使用
summary.total、summary.open.total、summary.closed.total**进行计数 - **始终使用
components.*.summary.***进行每个组件的计数 - 不要尝试计算回归数组(它们已通过
--short标志排除) - 这确保了即使在大数据集时的准确性
要提取的关键指标:
从summary对象:
summary.total- 总回归数summary.triaged- 总处理的回归数summary.triage_percentage- 关键健康指标:处理百分比summary.filtered_suspected_infra_regressions- 过滤的基础设施回归计数summary.time_to_triage_hrs_avg- 关键健康指标:平均处理小时数summary.time_to_triage_hrs_max- 最大处理小时数summary.time_to_close_hrs_avg- 关键健康指标:平均关闭小时数summary.time_to_close_hrs_max- 最大关闭小时数summary.open.total- 开放回归计数summary.open.triaged- 开放处理计数summary.open.triage_percentage- 开放处理百分比summary.closed.total- 关闭回归计数summary.closed.triaged- 关闭处理计数summary.closed.triage_percentage- 关闭处理百分比
从components对象:
- 与汇总相同的字段,但每个组件
- 使用
components.*.summary.*获取所有每个组件的统计信息
步骤 5:计算健康评分
重要 - 关闭回归的处理:
- 不建议对关闭的回归进行追溯处理 - 工具不支持此操作
- 当识别需要关注的未处理回归时,仅考虑开放回归:
summary.open.total - summary.open.triaged - 关闭回归处理百分比仅用于历史分析,而非可操作项目
整体健康评分
基于三个关键指标计算评分:
1. 处理覆盖率 (summary.triage_percentage):
- 90-100%:优秀 ✅
- 70-89%:良好 ⚠️
- 50-69%:需要改进 ⚠️
- <50%:差 ❌
2. 处理及时性 (summary.time_to_triage_hrs_avg):
- <24小时:优秀 ✅
- 24-72小时:良好 ⚠️
- 72-168小时(1周):需要改进 ⚠️
-
168小时:差 ❌
3. 解决速度 (summary.time_to_close_hrs_avg):
- <168小时(1周):优秀 ✅
- 168-336小时(1-2周):良好 ⚠️
- 336-720小时(2-4周):需要改进 ⚠️
-
720小时(4周以上):差 ❌
每个组件的健康评分
对于components中的每个组件:
- 使用
components.*.summary.*字段计算相同的三个评分 - 按健康状况从好到坏对组件进行排名
- 突出需要关注的组件:
- 低处理覆盖率(<50%)
- 处理响应慢(>72小时平均)
- 解决时间慢(>336小时/2周平均)
- 高开放回归计数
- 高总回归计数
步骤 6:显示文本报告
呈现格式良好的文本报告:
整体健康评分部分
显示summary中的整体统计信息:
=== 发布4.17的整体健康评分 ===
开发窗口:2024-05-17 至 2024-10-29(GA发布)
总回归数:62
过滤的基础设施回归:8
已处理:59(95.2%)
开放:2(50.0% 已处理)
关闭:60(96.7% 已处理)
处理覆盖率:✅ 优秀(95.2%)
处理及时性:⚠️ 良好(68小时平均,240小时最大)
解决速度:✅ 优秀(168小时平均,480小时最大)
重要:如果GA日期为null(开发中发布),注明:
开发窗口:2025-09-02 起(开发中)
每个组件的健康记分卡
显示从components.*.summary排名的表格:
=== 组件健康记分卡 ===
| 组件 | 处理覆盖率 | 处理时间 | 解决时间 | 开放 | 评分 |
|-----------------|-----------------|-------------|-----------------|------|-------|
| kube-apiserver | 100.0% | 58小时 | 144小时 | 1 | ✅ |
| etcd | 95.0% | 84小时 | 192小时 | 0 | ✅ |
| Monitoring | 86.7% | 68小时 | 156小时 | 1 | ⚠️ |
需要关注的组件
突出有问题的特定组件:
=== 需要关注的组件 ===
Monitoring:
- 1个开放未处理的回归(需要处理)
- 处理覆盖率:86.7%(低于90%)
示例组件:
- 5个开放未处理的回归(需要处理)
- 处理响应慢:120小时平均
- 高开放计数:5个开放回归
关键:当列出需要行动的处理时:
- 仅列出开放未处理的回归 - 这些是可操作的
- 不建议对关闭的回归进行处理 - 工具不支持追溯处理
- 计算可操作未处理计数为:
components.*.summary.open.total - components.*.summary.open.triaged
步骤 7:提供HTML报告生成
在显示文本报告后,询问用户是否要生成交互式HTML报告:
您想让我生成交互式HTML报告吗?(是/否)
如果用户肯定响应:
步骤 7a:为HTML报告准备数据
HTML报告需要特定结构的数据。转换JSON数据:
# 为HTML模板准备组件数据
component_data = []
for component_name, component_obj in components.items():
summary = component_obj['summary']
component_data.append({
'name': component_name,
'total': summary['total'],
'open': summary['open']['total'],
'closed': summary['closed']['total'],
'triaged': summary['triaged'],
'triage_percentage': summary['triage_percentage'],
'time_to_triage_hrs_avg': summary.get('time_to_triage_hrs_avg'),
'time_to_close_hrs_avg': summary.get('time_to_close_hrs_avg'),
'health_grade': calculate_health_grade(summary) # 计算组合评分
})
步骤 7b:生成HTML报告
使用generate_html_report.py脚本(或内联Python代码):
python3 plugins/teams/skills/analyze-regressions/generate_html_report.py \
--release 4.17 \
--data regression_data.json \
--output .work/teams-4.17/report.html
或使用带模板的内联Python:
import json
from datetime import datetime
# 加载模板
with open('plugins/teams/skills/analyze-regressions/report_template.html', 'r') as f:
template = f.read()
# 替换占位符
template = template.replace('{{RELEASE}}', '4.17')
template = template.replace('{{GENERATED_DATE}}', datetime.now().isoformat())
template = template.replace('{{SUMMARY_DATA}}', json.dumps(summary))
template = template.replace('{{COMPONENT_DATA}}', json.dumps(component_data))
# 写入输出
output_path = '.work/teams-4.17/report.html'
os.makedirs(os.path.dirname(output_path), exist_ok=True)
with open(output_path, 'w') as f:
f.write(template)
步骤 7c:打开报告
在用户默认浏览器中打开HTML报告:
macOS:
open .work/teams-4.17/report.html
Linux:
xdg-open .work/teams-4.17/report.html
Windows:
start .work/teams-4.17/report.html
向用户显示文件路径:
HTML报告已生成:.work/teams-4.17/report.html
正在打开默认浏览器...
错误处理
常见错误
-
网络错误
- 症状:
URLError或连接超时 - 解决方案:检查网络连接和防火墙规则
- 重试:两个脚本都有30秒超时
- 症状:
-
无效发布格式
- 症状:空结果或错误响应
- 解决方案:验证发布格式(例如,“4.17”,而非"v4.17"或"4.17.0")
-
发布日期未找到
- 症状:
get_release_dates.py返回错误 - 解决方案:验证系统中存在该发布;可能太旧或尚未创建
- 回退:继续进行,不带日期过滤(省略
--start和--end参数)
- 症状:
-
无回归找到
- 症状:空的组件对象
- 解决方案:验证该发布有回归数据;可能开发早期
- 操作:通知用户此发布尚无回归数据
-
组件过滤器无匹配
- 症状:过滤后组件对象为空
- 解决方案:检查组件名称拼写;组件名称不区分大小写
- 操作:从未过滤查询中列出可用组件
-
HTML模板未找到
- 症状:生成HTML报告时出现FileNotFoundError
- 解决方案:验证模板存在于
plugins/teams/skills/analyze-regressions/report_template.html - 回退:仅提供文本报告
调试
通过检查标准错误启用详细输出:
python3 plugins/teams/skills/list-regressions/list_regressions.py \
--release 4.17 \
--short 2>&1 | tee debug.log
诊断消息包括:
- 查询的URL
- 获取的回归数量
- 过滤后的数量
- 过滤的疑似基础设施回归数量
输出格式
文本报告结构
文本报告应包括:
-
头部
- 发布版本
- 开发窗口日期(开始和结束/GA)
- 发布状态(GA发布或开发中)
-
整体健康评分
- 总回归数
- 过滤的基础设施回归计数
- 开放/关闭细分
- 处理覆盖率评分及等级
- 处理及时性评分及等级
- 解决速度评分及等级
-
组件健康记分卡
- 所有组件的排名表格
- 每个组件的关键指标
- 每个组件的健康评分
-
需要关注的组件
- 有特定问题的组件列表
- 可操作建议(仅针对开放未处理的回归)
- 每个问题的上下文
-
尾部
- Sippy仪表板链接(如果适用)
- 报告生成时间戳
HTML报告功能
HTML报告应包括:
- 交互式表格,带排序和过滤
- 视觉指示器用于健康评分(颜色、图标)
- 图表/图形显示:
- 每个组件的处理覆盖率
- 处理时间分布
- 开放与关闭细分
- 详细指标悬停或点击
- 导出功能(CSV、PDF)
- 响应式设计用于移动查看
示例
示例 1:评分整体发布健康
/teams:analyze-regressions 4.17
执行流程:
- 为4.17获取发布日期
- 运行list_regressions.py带–start和–end(GA发布)
- 显示整体健康评分
- 显示每个组件的记分卡
- 突出需要关注的组件
- 提供HTML报告生成
示例 2:评分特定组件
/teams:analyze-regressions 4.21 --components Monitoring etcd
执行流程:
- 为4.21获取发布日期(可能有null GA)
- 运行list_regressions.py带–components和–start仅(开发中)
- 仅显示Monitoring和etcd的健康评分
- 比较这两个组件
- 识别哪个需要更多关注
示例 3:评分单个组件
/teams:analyze-regressions 4.21 --components "kube-apiserver"
执行流程:
- 为4.21获取发布日期
- 运行list_regressions.py带单个组件过滤器
- 显示kube-apiserver的详细健康指标
- 显示开放与关闭细分
- 列出开放未处理的回归计数(如果有)
健康评分计算细节
组合健康评分
为组件计算整体健康评分,考虑所有三个指标:
def calculate_health_grade(summary):
"""基于三个关键指标计算组合健康评分。"""
triage_coverage = summary['triage_percentage']
triage_time = summary.get('time_to_triage_hrs_avg')
resolution_time = summary.get('time_to_close_hrs_avg')
# 评分每个指标(0-3)
coverage_score = (
3 if triage_coverage >= 90 else
2 if triage_coverage >= 70 else
1 if triage_coverage >= 50 else
0
)
time_score = 3 # 如果无数据,默认为优秀
if triage_time is not None:
time_score = (
3 if triage_time < 24 else
2 if triage_time < 72 else
1 if triage_time < 168 else
0
)
resolution_score = 3 # 如果无数据,默认为优秀
if resolution_time is not None:
resolution_score = (
3 if resolution_time < 168 else
2 if resolution_time < 336 else
1 if resolution_time < 720 else
0
)
# 平均评分
avg_score = (coverage_score + time_score + resolution_score) / 3
# 返回等级
if avg_score >= 2.5:
return "Excellent ✅"
elif avg_score >= 1.5:
return "Good ⚠️"
elif avg_score >= 0.5:
return "Needs Improvement ⚠️"
else:
return "Poor ❌"
优先需要关注的组件
基于以下内容按优先级对组件排名:
-
高开放未处理计数(最紧急)
- 计算:
summary.open.total - summary.open.triaged - 阈值:>3开放未处理回归
- 计算:
-
低处理覆盖率(第二优先级)
- 使用:
summary.triage_percentage - 阈值:<50%
- 使用:
-
处理响应慢(第三优先级)
- 使用:
summary.time_to_triage_hrs_avg - 阈值:>72小时
- 使用:
-
高总回归计数(第四优先级)
- 使用:
summary.total - 阈值:组件相关(前四分位数)
- 使用:
高级功能
趋势分析(未来增强)
跨发布比较指标:
/teams:analyze-regressions 4.17 --compare 4.16
导出到CSV
为电子表格分析生成CSV报告:
/teams:analyze-regressions 4.17 --export-csv
自定义阈值
允许用户自定义健康评分阈值:
/teams:analyze-regressions 4.17 --triage-threshold 80
与其他命令集成
本技能可用于:
/teams:analyze-regressions命令(主要)- 质量指标仪表板
- 发布准备报告
- 团队性能跟踪工具
相关技能
get-release-dates- 获取发布开发窗口日期list-regressions- 获取原始回归数据ci:analyze-prow-job-test-failure- 分析单个测试失败
备注
- 所有脚本仅使用Python标准库(无外部依赖)
- 输出缓存在
.work/目录中以提高性能 - 回归数据从API实时获取
- HTML报告独立(无外部依赖,嵌入CSS/JS)
--short标志关键,防止大型数据集时输出截断- 健康评分是主观的,旨在指导,而非批评
- 基础设施回归(在高流量日的96小时内关闭)自动过滤
- 工具不支持关闭回归的追溯处理
故障排除
问题:报告显示0回归
可能原因:
- 发布开发早期
- 日期过滤排除了所有回归
- 组件过滤器未匹配任何组件
解决方案:
- 使用
get_release_dates.py检查发布日期 - 尝试不带日期过滤
- 先列出不带过滤器的可用组件
问题:处理百分比似乎低
上下文:
- 许多团队仍在建立回归处理实践
- 低百分比表示改进机会,而非失败
- 关注随时间趋势,而非绝对数字
操作:
- 识别需要关注的特定未处理开放回归
- 按回归严重性和频率优先处理
- 跟踪后续发布的改进
问题:HTML报告未打开
可能原因:
- 浏览器对本地文件的安全限制
- 不正确文件路径
- 缺少文件权限
解决方案:
- 从文件资源管理器手动打开文件
- 验证文件在预期路径创建
- 检查文件权限:
ls -la .work/teams-*/report.html
总结
本技能通过以下方式提供全面的组件健康分析:
- 获取发布开发窗口日期
- 检索过滤到开发窗口的回归数据
- 基于处理指标计算健康评分
- 生成可操作报告(文本和HTML)
- 识别需要帮助的组件
关键焦点是可操作洞察 - 特别识别需要立即关注的开放未处理回归,同时避免建议处理关闭的回归,因为这些无法追溯处理。