KeepHQ项目中的Incidents页面过滤器默认行为异常分析
问题背景
在KeepHQ开源告警管理平台的Incidents(事件)页面中,用户报告了一个关于过滤器默认行为的异常现象。当用户首次访问Incidents页面时,页面会自动应用某些默认过滤器,但这一行为与用户的预期不符,导致显示的事件列表不完整或不符合业务需求。
默认过滤器行为机制分析
核心代码实现
通过分析KeepHQ前端代码,我们发现Incidents页面的默认过滤器行为由以下关键组件控制:
// 默认过滤的状态列表
export const DefaultIncidentFilteredStatuses: string[] = [
Status.Firing,
Status.Acknowledged,
Status.Merged,
];
// 默认过滤器配置
export const DefaultIncidentFilters: object = {
status: DefaultIncidentFilteredStatuses,
};
// 初始页面加载时显示的活跃事件
export const DEFAULT_INCIDENTS_CHECKED_OPTIONS = [
Status.Firing,
Status.Acknowledged,
];
过滤器上下文实现
const setFilterValue = useCallback(
(filterName: string, defaultValues: string[] | undefined = undefined) => {
return () => {
if (incidentsMeta === undefined) return [];
const values = searchParams?.get(filterName);
let valuesArray = values?.split(",");
if (!valuesArray) {
valuesArray = defaultValues; // 这里应用默认值
}
valuesArray = valuesArray?.filter((value) =>
incidentsMeta[filterName as keyof IncidentsMetaDto]?.includes(value)
);
return (valuesArray || []) as string[];
};
},
[incidentsMeta, searchParams]
);
异常行为表现
1. 默认状态过滤过于严格
当前实现中,默认只显示三种状态的事件:
firing(触发中)acknowledged(已确认)merged(已合并)
2. URL参数处理逻辑缺陷
当URL中包含过滤器参数时,系统会优先使用URL参数,但存在逻辑缺陷:
const values = searchParams?.get(filterName);
let valuesArray = values?.split(",");
if (!valuesArray) {
valuesArray = defaultValues; // 仅在无URL参数时使用默认值
}
这种实现导致:
- 用户无法通过URL清除默认过滤器
- 页面刷新后默认过滤器重新生效
- 书签功能受到限制
技术深度分析
CEL表达式过滤机制
后端使用CEL(Common Expression Language)表达式进行事件过滤:
export const DEFAULT_INCIDENTS_CEL = `is_candidate == false &&
(status in ['firing', 'acknowledged'])`;
这个表达式与前端默认过滤器存在不一致:
- 前端默认包含
merged状态 - 后端CEL默认不包含
merged状态 - 导致前后端过滤结果不一致
状态枚举定义
export enum Status {
Firing = "firing",
Resolved = "resolved", // 默认被过滤
Acknowledged = "acknowledged",
Merged = "merged", // 默认包含但CEL不包含
Deleted = "deleted", // 默认被过滤
}
影响评估
对用户体验的影响
| 影响维度 | 严重程度 | 描述 |
|---|---|---|
| 数据完整性 | 高 | 用户无法看到完整的事件列表 |
| 操作效率 | 中 | 需要手动调整过滤器 |
| 功能一致性 | 高 | 前后端过滤逻辑不一致 |
业务场景影响
- 运维监控场景:无法快速查看已解决的事件历史
- 事故分析场景:缺失完整的事件生命周期视图
- 审计合规场景:无法追溯所有状态的事件记录
解决方案建议
方案一:调整默认过滤器行为
// 修改默认过滤器配置
export const DefaultIncidentFilteredStatuses: string[] = [
Status.Firing,
Status.Acknowledged,
Status.Resolved, // 新增已解决状态
Status.Merged,
];
// 或者提供配置选项
export const getDefaultIncidentFilters = (userPreferences?: UserPreferences) => {
return userPreferences?.defaultFilters || {
status: [Status.Firing, Status.Acknowledged, Status.Merged, Status.Resolved]
};
};
方案二:改进URL参数处理
const setFilterValue = useCallback(
(filterName: string, defaultValues: string[] = []) => {
return () => {
if (incidentsMeta === undefined) return [];
const explicitParam = searchParams?.get('explicit_filter');
const values = searchParams?.get(filterName);
// 只有当用户明确设置过过滤器时才使用URL参数
if (explicitParam === 'true' && values) {
return values.split(",").filter(value =>
incidentsMeta[filterName as keyof IncidentsMetaDto]?.includes(value)
);
}
// 否则使用默认值
return defaultValues.filter(value =>
incidentsMeta[filterName as keyof IncidentsMetaDto]?.includes(value)
);
};
},
[incidentsMeta, searchParams]
);
方案三:提供用户配置界面
// 用户偏好设置存储
interface UserFilterPreferences {
defaultStatusFilters: string[];
rememberLastFilter: boolean;
defaultPageSize: number;
}
// 持久化用户设置
const saveUserFilterPreferences = (prefs: UserFilterPreferences) => {
localStorage.setItem('incidentFilterPrefs', JSON.stringify(prefs));
};
实施路线图
短期修复(1-2周)
- 统一前后端默认过滤逻辑
- 修复URL参数处理缺陷
- 提供基本的过滤器重置功能
中期优化(2-4周)
- 实现用户过滤器偏好设置
- 添加过滤器预设功能
- 改进过滤器UI/UX设计
长期规划(1-2月)
- 高级过滤器语法支持
- 过滤器模板共享功能
- 智能过滤器推荐系统
总结
KeepHQ Incidents页面的默认过滤器行为异常主要源于:
- 过于严格的默认状态过滤
- URL参数处理逻辑缺陷
- 前后端过滤逻辑不一致
通过系统性的代码分析和解决方案设计,我们可以为用户提供更灵活、更符合预期的过滤器行为,显著提升产品的可用性和用户体验。建议优先实施短期修复方案,快速解决最紧迫的用户痛点。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



