docs/alerts.md
本文档记录 Issue #1202 P0 的告警中心基线、数据契约、存储评估和兼容边界。P0 只定义后续实现可以复用的契约,不新增 API、Web 页面、数据库表、触发历史写入、冷却执行或规则迁移。
当前运行时告警由 src/agent/events.py 中的 EventMonitor 提供,并通过 schedule 模式后台轮询执行。
AGENT_EVENT_MONITOR_ENABLED、AGENT_EVENT_MONITOR_INTERVAL_MINUTES、AGENT_EVENT_ALERT_RULES_JSON。main.py 在 schedule 模式中调用 build_event_monitor_from_config(),并注册 agent_event_monitor 后台任务。NotificationService.send(..., route_type="alert"),继续遵守通知网关的 alert 路由配置。src/services/system_config_service.py 会对 AGENT_EVENT_ALERT_RULES_JSON 做 JSON 与规则语义校验。当前 runtime 支持三类规则:
alert_type | 方向字段 | 阈值字段 | 当前语义 |
|---|---|---|---|
price_cross | direction: above / below | price | 实时价格上破或下破固定价格 |
price_change_percent | direction: up / down | change_pct | 实时涨跌幅达到指定百分比 |
volume_spike | - | multiplier | 最新成交量超过近 20 日均量的指定倍数 |
sentiment_shift、risk_flag、custom 等类型只作为未来扩展占位;当前运行时不接受这些类型作为可执行规则。
P0 保留 AGENT_EVENT_ALERT_RULES_JSON 作为唯一运行时规则来源,不自动迁移、删除、覆盖或改写用户已有 .env / Web 配置。
triggered,这不是告警中心冷却模型,也不提供跨进程或重启后的触发历史。以下契约用于后续 P1+ API、worker、Web 和存储实现对齐。P0 只定义字段和语义边界,不代表当前已经存在这些持久化实体。
alert_rule可管理的告警规则。
| 字段 | 说明 |
|---|---|
id | 规则 ID;legacy JSON 规则在 P0 中没有持久化 ID |
name | 用户可读名称;没有提供时可由规则类型和目标生成 |
target_scope | 目标范围,例如 single symbol、watchlist、portfolio、market |
target | 目标标的或目标引用,例如股票代码、watchlist ID、portfolio ID |
alert_type | 规则类型;P1 初始只允许 price_cross、price_change_percent、volume_spike |
parameters | 规则参数,例如 direction、price、change_pct、multiplier |
severity | 告警等级,例如 info、warning、critical |
enabled | 是否启用 |
cooldown_policy | 冷却策略;P0 只定义字段,P4 才实现执行语义 |
notification_policy | 通知策略;默认复用 NotificationService 的 alert 路由 |
source | 创建来源,例如 legacy_env、web、api、import |
created_at / updated_at | 创建和更新时间 |
alert_trigger一次真实或可记录的规则触发。
| 字段 | 说明 |
|---|---|
id | 触发记录 ID |
rule_id | 对应规则 ID;legacy env 规则可记录临时引用 |
target | 实际触发目标 |
observed_value | 观察值,例如现价、涨跌幅、成交量倍数 |
threshold | 触发阈值 |
reason | 可读触发原因 |
data_source | 数据源或 provider |
data_timestamp | 数据时间;缺失时不得伪造为当前时间 |
triggered_at | 触发时间 |
status | 触发状态,例如 triggered、skipped、degraded、failed |
diagnostics | 脱敏后的诊断信息 |
alert_notification一次触发对应的通知尝试。
| 字段 | 说明 |
|---|---|
id | 通知尝试 ID |
trigger_id | 对应触发记录 ID |
channel | 通知渠道 |
attempt | 第几次尝试 |
success | 是否成功 |
error_code | 结构化错误码 |
retryable | 是否建议重试 |
latency_ms | 耗时 |
diagnostics | 脱敏后的发送诊断,不得包含 token、完整 webhook URL、邮箱密码或 bot secret |
created_at | 尝试时间 |
alert_cooldown规则或目标维度的冷却状态。
| 字段 | 说明 |
|---|---|
rule_id | 对应规则 ID |
target | 冷却目标 |
severity | 可选等级维度 |
last_triggered_at | 最近触发时间 |
cooldown_until | 冷却截止时间 |
reason | 冷却原因 |
state | 当前状态,例如 active、expired |
updated_at | 更新时间 |
当前仓库已有 SQLite 存储层和 repository/service 分层:
src/storage.py 管理 SQLite 连接、SQLAlchemy ORM 模型和 DatabaseManager。src/repositories/ 放置数据访问层,例如 PortfolioRepository。src/services/ 放置业务服务层,例如 PortfolioService、PortfolioRiskService。data/stock_analysis.db。P1/P2 实现告警持久化时,推荐优先复用以上模式:在 storage 层定义 alert ORM 模型,在 repository 层封装 CRUD 和查询,在 service 层处理规则校验、评估状态、通知结果和冷却语义。P0 不新建表,不改变现有数据库。
如果后续 PR 需要 schema 变更,必须同时给出:
AGENT_EVENT_ALERT_RULES_JSON,除非用户显式执行导入动作。P1 新增后端 Alert API 与 schema,锁定告警中心最小 API 契约,不接入 Web 页面或后台 worker。
api/v1/endpoints/alerts.py。api/v1/schemas/alerts.py。GET /api/v1/alerts/rulesPOST /api/v1/alerts/rulesGET /api/v1/alerts/rules/{rule_id}PATCH /api/v1/alerts/rules/{rule_id}DELETE /api/v1/alerts/rules/{rule_id}POST /api/v1/alerts/rules/{rule_id}/enablePOST /api/v1/alerts/rules/{rule_id}/disablePOST /api/v1/alerts/rules/{rule_id}/testGET /api/v1/alerts/triggersGET /api/v1/alerts/notificationsprice_cross、price_change_percent、volume_spike;sentiment_shift、risk_flag、custom 等未来类型返回结构化 unsupported 错误。test 接口只做一次性 dry-run 评估,不发送通知,不写入真实触发记录或通知 attempt。cooldown_policy / notification_policy 在 P1 中只是保留字段:API 可存储和返回这些 opaque 配置,但不执行冷却或自定义通知语义。AGENT_EVENT_ALERT_RULES_JSON 继续保留为 legacy 配置入口;P1 不自动迁移、删除、覆盖或改写 legacy 配置。P1 不做:
alert_trigger / alert_notification 写入;P1 只提供查询接口和表结构。alert_cooldown 执行语义。api/v1/schemas/alerts.py 或 Alert API。AGENT_EVENT_ALERT_RULES_JSON。NotificationService 或通知路由框架。alert_rules / alert_triggers / alert_notifications SQLite 表。最小回滚方式是 revert P1 PR;revert 会移除 API、service、repository、schema 和 ORM 定义,但已经由 Base.metadata.create_all() 创建的 SQLite 表与数据不会自动删除。如需清理,需要维护者在确认不再需要历史数据后手动删除相关表。