如何构建一个能准确跟踪 SLA 合规性的 Web 应用
学习如何设计并构建能够跟踪 SLA 合规性的 Web 应用:定义度量、收集事件、计算结果、在违约时告警并生成准确的报告。

定义 SLA 合规与你要构建的东西
SLA 合规意味着满足 服务等级协议(SLA) 中可度量的承诺——这是提供方与客户之间的合同。你要做的就是用证据回答一个简单问题:在这个客户、这段时间内,我们履行了承诺吗?
把三个相关但不同的术语分开很有帮助:
- SLI(Service Level Indicator):原始度量(例如“成功检查百分比”、“首次回复时间”或“恢复服务所用时间”)。
- SLO(Service Level Objective):针对 SLI 的内部目标(通常比 SLA 更严格)。示例:"99.95% 可用性目标"。
- SLA:对外约定的承诺,常与补偿或罚款挂钩。示例:"每月 99.9% 可用性"。
你将跟踪的常见 SLA 指标
大多数 SLA 跟踪 Web 应用从一小组映射到真实运营数据的指标开始:
- 可用性 / 正常运行时间:报告期内服务“可用”的百分比。
- 响应时间(支持):从用户工单创建到首次人工响应的时间。
- 解决时间:从事故/工单创建到关闭或恢复的时间。
- 可用性窗口:例如“只计工作时间”、“排除计划维护”或“按客户时区仅测量 08:00–18:00”。
谁会使用这个应用——及其目的
不同用户需要相同的事实,但展示方式不同:
- 运维 / SRE:尽早发现违约并验证事故时间线。
- 支持团队:跟踪每个客户的响应与解决承诺。
- 管理者:查看趋势、风险,以及团队是否持续达标。
- 客户:查看透明的报告(有时是状态页)显示发生了什么。
你要构建的(以及不属于本产品的)内容
本产品关注的是跟踪、证据与报告:收集信号、应用约定规则、生成审计友好的结果。它不保障性能;它是以准确、一致且可自证的方式去测量性能。
需求:指标、规则与各方需求
在你设计表或写代码之前,先把“合规”对你的业务意味着什么讲清楚。大多数 SLA 跟踪问题不是技术问题,而是需求问题。
收集输入(不要靠记忆)
先收集真实来源:
- 客户合同与主服务协议(含附件和工单附录)
- 服务层级(例如基础与高级),以及哪些客户属于哪个层级
- 每个客户(或服务)的工作时间与时区
- 排除与特殊规则:计划维护窗口、不可抗力、客户造成的延迟、第三方依赖、宽限期
把这些写成明确规则。如果一个规则无法清楚表述,就无法可靠计算。
决定必须被跟踪的事项
列出会影响 SLA 数字的现实“事物”:
- 事故/宕机(开始、结束、严重度、影响的服务)
- 请求/工单(创建、首次响应、解决、等待客户)
- 维护(计划 vs 紧急;是否计入可用性)
- 局部故障(性能降级)以及是否计入
还要识别谁需要什么:支持需要实时违约风险,管理者要周报汇总,客户要简明摘要(通常用于状态页)。
为首个版本选择 1–3 个指标
保持范围精简。选择能证明系统端到端工作的最小集合,例如:
- 每服务每月的可用性百分比
- 工作时间内的事故首次响应时间
- 严重度 1 事故的解决时间
需求清单与成功标准
创建一页检查表以便后续测试:
- 指标定义清晰(开始/结束时间戳、时区、舍入规则)
- 包含/排除规则(维护、客户等待时间)
- 各层级目标阈值(例如 99.9%,1 小时响应)
- 输出需求(客户报告、内部仪表盘、导出)
成功的样子:两个人手工计算同一个样本月,你的应用能完全匹配结果。
关于 SLA、服务、事故与事件的数据模型
一个正确的 SLA 跟踪器从能说明“为什么”一个数字如此开始。如果你不能将某个月的可用性数字追溯到用于计算的精确事件与规则,就会在客户争议与内部不确定性中挣扎。
核心实体(保持平凡且明确)
至少要建模:
- Customer(客户 / 租户 / 账号):拥有服务、日历、联系人与报告偏好。
- Service(服务):被度量的对象(API、Web 应用、特定区域组件)。如需汇总多个组件,可建父子关系。
- Plan(计划):商业外壳(例如“Gold”),主要用于附加默认的 SLA 策略集。
- SLA policy(SLA 策略):可度量的规则:可用性目标、响应时间目标、度量窗口及哪些情况被排除。
- Incident(事故):便于人阅读的分组(标题、严重度、时间线),引用底层事件。
- Event(事件):不可变事实(状态变化、监控信号、确认)驱动计算。
一个有用的关系是:customer → service → SLA policy(可能通过 plan)。事故与事件再引用服务与客户。
用于基于时间跟踪的最小模式
时间相关的错误是 SLA 计算错误的头号原因。请存储:
occurred_at为 UTC(带时区语义的时间戳)received_at(系统何时看到它)source(监控名、集成、手动)external_id(用于去重重试)payload(原始 JSON 以便将来调试)
同时保存 customer.timezone(IANA 字符串,如 America/New_York)用于展示与工作时间逻辑,但不要用它去改写事件时间。
工作时间与节假日
如果响应类 SLA 在非工作时间暂停,应显式建模日历:
- 每个客户(或按地区/服务)的
working_hours:周几 + 开始/结束时间 - 关联到区域或客户的
holiday_calendar,包含日期范围与标签
使规则数据化,以便运维可以在不部署代码的情况下更新假期。
可审计性:原始 vs 计算结果
将 原始事件 存入追加式表,并单独存储 计算结果(例如 sla_period_result)。每条结果行应包括:周期边界、输入版本(策略版本 + 引擎版本)以及被使用的事件 ID 引用。这使得重新计算安全且在客户询问“你算了哪些宕机分钟?”时能给出审计依据。
事件摄取:数据如何进入你的应用
你的 SLA 数字取决于你摄取事件的可靠性。目标很简单:捕获每一次重要变化(宕机开始、事故确认、服务恢复),带上统一的时间戳和足够的上下文以便稍后计算合规性。
常见事件来源
大多数团队会从多套系统拉取数据:
- 工单 / 事故工具(Jira Service Management、ServiceNow、Zendesk):创建/确认/解决时间戳,优先级变更,指派变更。
- 监控工具(Pingdom、Datadog、CloudWatch、Prometheus Alertmanager):上下线信号、告警触发/清除、合成检查结果。
- 基础设施与应用日志:部署事件、错误激增、健康检查失败(在监控噪声大或缺失时很有用)。
- 手工录入:用于“业务确认的宕机开始/结束”或“维护窗口开始”的小型 UI,当自动化无法判断真相时使用。
摄取选项(何时使用)
Webhook 通常是实时且准确的首选:上游系统主动推送到你的端点。
轮询 在 Webhook 不可用时是备选:应用周期性获取自上次游标以来的变化。需处理速率限制并小心“since”逻辑。
CSV 导入 有助于回填与迁移。将其作为一等摄取路径,以便无须 hack 就能重处理历史周期。
推荐的事件格式(含幂等性)
将所有不同上游负载规范化为单一内部“事件”形状:
event_id(必需):在重试间唯一且稳定。优先使用源系统的 GUID;否则生成确定性哈希。source(必需):例如datadog、servicenow、manual。event_type(必需):例如incident_opened、incident_acknowledged、service_down、service_up。occurred_at(必需):事件发生时间(而非接收时间),带时区信息。received_at(系统):你的应用摄取时间。service_id(必需):该事件影响的 SLA 相关服务。incident_id(可选但推荐):将多个事件链接到同一事故。attributes(可选):优先级、区域、客户分段等。
在 event_id 上加唯一约束以实现摄取的幂等性:重试不会产生重复。
防止坏数据的验证规则
拒绝或隔离:
- 缺失/无效时间戳,或
occurred_at明显在未来的事件 - 无法映射到已知
service_id的事件(或要求进入“未映射”工作流) - 已存在的
event_id(重复) - 以会破坏规则的顺序乱序到达(保留它们并标记为“需审查”,而不是静默覆盖)
这种前期的严谨能让你免于在 SLA 报表上争吵——因为你能指出清晰、可追溯的输入。
SLA 计算引擎:将事件转为合规结果
你的计算引擎是把“原始事件”变成可辩护 SLA 结果的地方。关键是把它当成会计:确定性规则、清晰输入以及可重放的轨迹。
从规范化时间线开始
将一切转换为每个事故(或每个服务影响)的一条有序流:
- 时间戳(UTC):事故开始、确认/首次响应、缓解、解决、重新打开
- 状态变化:暂停/恢复、等待客户、维护窗口激活
- 范围:哪些服务与客户受影响以及以何种严重度
从这条时间线上通过求和区间计算时长,而不是盲目减去两个时间戳。
首次响应时间(TTFR)与解决时间(TTR)
把 TTFR 定义为从 incident_start 到 first_agent_response(或 acknowledged,取决于 SLA 文本)之间的可计时长。把 TTR 定义为从 incident_start 到 resolved 的可计时长。
“可计”意味着移除不应计入的区间:
- 工作时间之外(若为工作时间 SLA)
- 明确的暂停(例如“等待客户”)
- 排除项如计划维护或客户造成的延迟
实现细节:存储一个日历函数(工作时间、假期)和一个规则函数,该函数接收时间线并返回计费区间。
局部故障与多服务事故
事先决定你是如何计算的:
- 按服务计算 SLA(推荐):一个事故可能产生多个服务影响记录,每个有独立的 TTFR/TTR
- 按客户计算 SLA:同一次宕机可能只影响部分租户
对局部故障,只有在合同要求加权影响时才按影响权重计算;否则把“降级”视为单独的违约类别。
可追溯性:存储输入、输出与重放数据
每次计算都应可复现。持久化:
- 用到的精确事件(含 id、时间戳与来源)
- 派生出的区间(哪些被排除以及为什么)
- 最终结果(TTFR、TTR、违约标记与规则版本)
当规则改变时,你可以按版本重跑计算而不改写历史——这对审计与客户争议至关重要。
报告逻辑:周期、可用性与边缘案例
报告是 SLA 跟踪赢得信任或被质疑的地方。你的应用应清晰说明正在测量的时间范围是什么、哪些分钟被计入以及最终数字如何得出。
周期:日历、计费与滚动窗口
支持客户实际使用的常见报告周期:
- 日历月/季度(例如 3 月 1–31 日)
- 计费周期(例如 15 日–次月 14 日,对齐发票)
- 滚动窗口(例如“过去 30 天”,每日更新)
以明确的开始/结束时间戳存储周期(不要只存“月份 = 3”),以便你能重放计算并解释结果。
可用性:总分钟数 vs 可计分钟数
一个常见混淆源是分母是否为整个周期还是仅“可计”时间。
为每个周期定义两个值:
- 可计分钟(eligible minutes):计入 SLA 的分钟(通常排除计划维护、客户造成的停机或支持时段外的时间)
- 停机分钟(downtime minutes):在可计分钟内被判定为不可用的分钟
然后计算:
availability_percent = 100 * (eligible_minutes - downtime_minutes) / eligible_minutes
如果可计分钟可能为零(例如服务只在工作时间被监控,而周期内无工作时间),事先定义规则:要么显示 “N/A”,要么视为 100%——但要一致并记录。
将数字转为清晰的通过/不通过结果
大多数 SLA 既需要百分比也需要二元结果:
- 百分比:例如本周期 99.95%
- 通过/不通过:与 SLA 目标比较(例如 ≥ 99.9% 则通过)
还要保留“距离违约的余量”(剩余停机预算),以便仪表盘在阈值被触及前给出预警。
必须有意识处理的边缘案例
- 时区:为每个客户/合同选择一个报告时区(通常为客户时区),并一致地转换事件。
- 夏令时:不要假设一天有 1440 分钟。使用时区感知的时间戳以保证在 DST 切换时周期长度正确。
- 缺失结束时间:事故有时缺少解决时间。把它们视为“未关闭”并在报告截止时打上上限,同时标记记录以便清理。
最后,保留原始输入(包含/排除的事件与调整),以便每份报告都能回答“这个数字为什么是这样的?”并避免含糊其辞。
使 SLA 状态一目了然的 UI 与仪表盘
即便你的计算引擎很完美,如果 UI 无法即时回答“我们现在是否达标,以及为什么?”,用户也会感到失望。设计时让每个页面以明确状态开始,然后让用户深入查看数字与产生这些数字的原始事件。
要构建的主要视图
总览仪表盘(给运维与管理者)。以少量卡片为主:当前周期合规性、可用性、响应时间合规与“距离违约的剩余时间”。标签要明确(例如用“本月可用性”而不是“Uptime”)。如果支持多 SLA,先展示最糟的状态并允许展开。
客户详情(给客户经理与对外报告)。客户页应汇总该客户的所有服务与 SLA 层级,显示通过/风险/失败状态与简短说明(例如“2 起事故被计入;计入停机 18 分钟”)。加入指向 /status 的链接和报告导出链接。
服务详情(用于深入调查)。展示精确 SLA 规则、计算窗口以及合规数字如何形成的分解。包括可用性时间序列图与被计入 SLA 的事故列表。
事故时间线(用于审计)。单一事故视图应显示事件时间线(检测、确认、缓解、解决)以及用于“响应”和“解决”指标的具体时间戳。
与实际问题匹配的筛选器
使筛选器在各屏一致:日期范围、客户、服务、层级与 严重度。全站使用相同单位(分钟 vs 秒;小数位数统一)。当用户更改日期范围时,更新页面上的所有指标以避免不一致。
钻取时保持信任
每个汇总指标都应有“为什么?”路径:
- 从合规百分比 → 本期被计入的事故列表
- 从事故 → 原始事件与用于计算的派生时间戳
- 从可用性 → 带来源标签的停机区间(监控事件 vs 手动调整)
避免过多使用提示(tooltip),而应在服务页明确显示术语定义(如“排除停机”或“工作时间”)和精确规则文本。
保持简洁但明确
优先使用明白的自然语言而非缩写(用“响应时间”而非“MTTA”,除非你的用户群熟悉缩写)。状态同时使用颜色与文字标签(例如“风险:已使用 92% 错误预算”)以避免歧义。如果支持审计日志,添加一个小的“最后修改”框在 SLA 规则与排除项上并链接到 /audit,以便用户核验规则何时变更。
违约告警与通知
告警是 SLA 跟踪应用从被动报告转为帮助团队避免罚款的关键点。最佳告警是及时、具体并可操作——告诉接收者接下来该做什么,而不仅仅是“情况糟糕”。
定义匹配实际决策的触发器
从三类触发器开始:
- 接近违约:例如“首次响应 SLA 仅剩 30 分钟预算”或“本月可用性已降至 99.92%(SLA 为 99.9%)”。这是最有价值的告警,因为它能驱动补救。
- 已违约:当计算引擎确认在相关窗口内未达标时触发。
- 重复违规:检测诸如“30 天内 3 次违约”或“同一服务本周已违约两次”的模式,通常指示系统性问题。
使触发器可按客户/服务/SLA 配置,因为不同合同可容忍的阈值不同。
选择渠道并保持消息可操作
发送告警到实际会响应的地方:
- Email:面向审计与外部利益相关者的通知。
- Slack:快速的内部协作渠道。
- 短信(可选):用于高严重度的升级通知。
每条告警应包含深度链接,如 /alerts、/customers/{id}、/services/{id} 以及事故或事件详情页,以便响应者快速核实数字。
降低噪声:去重、静默时段与升级
通过对相同键(customer + service + SLA + period)的告警进行分组实现去重,并在冷却窗口内抑制重复告警。
增加按团队时区的静默时段,让非关键的“接近违约”告警在工作时间到来时再发送,而“已违约”在高严重度时可覆盖静默时段。
最后,支持升级规则(例如 10 分钟后通知值班,30 分钟后升级给经理),以防告警停留在某个收件箱里无人处理。
访问控制、认证与审计日志
SLA 数据敏感,因为它可能暴露内部绩效与客户特定的权益。把访问控制视为 SLA “数学”的一部分:同一事故在不同客户的 SLA 应用下可能得到不同结果。
从一开始要支持的角色
保持角色简单,然后再细化权限。
- Admin:配置全局设置、管理服务、SLA、用户、集成与计费项。
- Agent:创建/更新事故与维护窗口、附加事件并添加事后说明。
- Manager:读取其范围内的所有信息、批准 SLA 定义并导出报告。
- Customer viewer(客户查看者):仅查看其自己的服务、SLA 目标、事故历史与对外报告。
一个实用的默认是 基于角色的访问控制(RBAC)+ 租户范围限制:
- 每条记录(服务、SLA 策略、报告)都有一个 所属租户/客户。
- 内部用户可被赋予多个租户访问;客户查看者仅限一个。
- 编辑权限一般比查看权限更严格:例如 agent 可以编辑事故但不能改 SLA 规则。
每个角色的可见/可编辑范围
明确客户特定数据的可见性:
- 客户查看者绝不应看到内部字段(根因假设、内部严重度、值班备注、私有标签)。
- SLA 策略应进行版本化,使客户能查看事故发生时适用的 SLA 条款。
不会把你局限住的认证选项
从 邮箱/密码 开始,并对内部角色强制多因素认证。通过将身份(他们是谁)与授权(他们能访问什么)分离,为将来的 SSO(SAML/OIDC) 做好准备。对于集成,发放与服务账户关联的 API key,有限作用域并支持轮换。
你会感激的审计日志
为以下操作添加不可变审计条目:
- SLA 规则变更(阈值、日历、排除、与服务/客户的映射)
- 事故编辑(时间戳、状态转变、手工停机覆盖)
- 权限与 API key 变更
记录 谁、变更了什么(前/后)、何时、在哪(IP/UA)以及关联 ID。使审计日志可搜索与导出(例如 /settings/audit-log)。
用于集成与自动化的 API 设计
SLA 跟踪应用很少独立存在。你需要一个 API,让监控工具、工单系统与内部工作流创建事故、推送事件并拉取报告,而不需人工干预。
从小而可预测的接口开始
使用版本化基础路径(例如 /api/v1/...),以便在不破坏现有集成的情况下演进负载结构。
覆盖多数用例的必要端点:
- Events:
POST /api/v1/events用于摄取状态变化(上下线、延迟样本、维护窗口)。GET /api/v1/events用于审计与调试。 - Incidents:
POST /api/v1/incidents、PATCH /api/v1/incidents/{id}(确认、解决、指派)、GET /api/v1/incidents。 - SLAs:
GET /api/v1/slas、POST /api/v1/slas、PUT /api/v1/slas/{id}用于管理合同与阈值。 - Reports:
GET /api/v1/reports/sla?service_id=...&from=...&to=...用于合规摘要。 - Alerts:
POST /api/v1/alerts/subscriptions管理 webhook/email 目标;GET /api/v1/alerts查看历史。
保持分页与过滤一致
挑一个约定并在所有接口中使用。例如:limit + cursor 分页,以及标准过滤器如 service_id、sla_id、status、from 与 to。排序要可预测(例如 sort=-created_at)。
为集成方定义可依赖的错误响应
返回结构化错误并包含稳定字段:
{ "error": { "code": "VALIDATION_ERROR", "message": "service_id is required", "fields": { "service_id": "missing" } } }
使用明确的 HTTP 状态(400 验证、401/403 认证、404 未找到、409 冲突、429 限速)。对于事件摄取,考虑幂等性(Idempotency-Key)以避免重试产生重复事故。
速率限制与基本安全
对每个令牌应用合理速率限制(对摄取端点设置更严格的限制),清理输入并验证时间戳/时区。优先使用有作用域的 API 令牌(只读报表 vs 写入事故),并始终记录谁调用了哪个端点以便追溯(详见审计日志章节上的 /blog/audit-logs)。
测试策略:证明数字是正确的
SLA 数字只有在被信任时才有价值。SLA 跟踪应用的测试应少关注“页面是否能加载”,而更多关注“时间数学是否完全符合合同”。把你的计算规则当作产品特性来写测试套件。
用固定时间线做单元测试
从使用确定性输入的单元测试开始:一组时间线事件(事故打开、确认、缓解、解决)和明确定义的 SLA 规则集。
用固定时间戳并“冻结时间”,确保测试不依赖系统时钟。覆盖常出错的边界情况:
- 事故在报告期前开始并在期内结束
- 重叠事故(停机应合并还是叠加?)
- 多次暂停(维护、客户等待)
- 边界分钟/秒(恰好在 00:00、月末、闰日)
整体端到端测试整条管线
添加一小组端到端测试跑完全流程:摄取事件 → 计算合规 → 生成报告 → 渲染 UI。这能捕捉“引擎计算的结果”与“仪表盘显示”的不一致。保留少量但高价值场景,并断言最终数字(可用性百分比、是否违约、首次响应时间)。
为日历与时区构建可复用的测试夹具
创建工作时间、假期与时区的测试夹具。你需要可重现的案例,比如“事故发生在本地时间周五 17:55”或“假期改变了响应时间计数”。
监控 SLA 应用自身
测试并不止于部署。为作业失败、队列/积压大小、重算耗时与错误率添加监控。如果摄取滞后或夜间作业失败,即便代码正确,SLA 报表也可能错误。
部署、运维与实用的 MVP 路线图
发布 SLA 跟踪应用更讲究可预测的运维:你的计算必须按时运行、数据必须安全、报告必须可复现。
简单可靠的部署路径
从托管服务开始以便专注于正确性:
- 托管数据库(PostgreSQL):自动备份、时间点恢复、加密。
- 容器托管(Web/API,例如托管容器平台):便于回滚与一致的环境。
- 对象存储 用于导出(CSV/PDF)与大文件,配合生命周期规则。
保持环境最简:dev → staging → prod,每个环境独立数据库与密钥。
从一开始就需要的后台作业
SLA 跟踪并非纯请求/响应;它依赖计划任务:
- 计算作业:从新事件重新计算 SLA 窗口,并在晚到数据出现时重跑。
- 报告生成:每日/每月摘要、面向客户的导出。
- 数据卫生:归档旧原始事件、压缩派生表、验证引用完整性。
通过 worker + 队列或由托管调度器调用内部端点来运行这些作业。确保作业幂等(可安全重试)并记录每次运行以便审计。
保留与导出(不要过度承诺)
按数据类型定义保留策略:保留派生合规结果时间比原始事件更久。导出先提供 CSV(快速、透明),后续再做 PDF 模板。声明清楚:导出为“尽力而为的格式化”,而数据库仍为事实来源。
一个分阶段的路线图以保持可控范围
- MVP: 一项服务、一个 SLA、一个时区、基础仪表盘 + 月度报告。
- 更多指标: 响应时间 SLA、维护窗口、排除项、多日历支持。
- 客户门户: 每客户视图、访问控制、可下载的报告。
- 状态页: 公共/私有页面,以你计算的可用性为数据源(参见 /blog/status-pages)。
用 Koder.ai 更快原型(可选)
如果想快速验证数据模型、摄取流程与报告 UI,像 Koder.ai 这样的即时编码平台可以让你在不投入完整工程周期的前提下得到端到端原型。因为 Koder.ai 能通过对话生成完整应用(Web UI + 后端),它能帮你快速构建:
- 一个 React 仪表盘用于合规、错误预算与钻取时间线,
- 一个 Go + PostgreSQL 后端用于存储原始事件与周期结果,
- 导出/报告端点与简单的客户门户视图。
一旦把需求与计算验证清楚(这才是艰难部分),你可以把源码导出并进入更传统的构建与运维流程——同时在快速迭代阶段保留快照与回滚功能。
常见问题
在 SLA 跟踪 Web 应用中,“SLA 合规”是什么意思?
一个 SLA 跟踪器用证据回答一个问题:在特定客户和时间段内,我们是否履行了合同承诺?
实际上,这意味着摄取原始信号(监控、工单、手动更新)、应用客户的规则(工作时间、排除项),并生成可审计的通过/未通过结果及支持性细节。
SLI、SLO 和 SLA 有何不同——为什么应用应分别建模?
将三者分别使用:
- SLI 用于原始度量(例如成功检查百分比、首次响应时间)。
- SLO 用于内部目标(通常比合同更严格)。
- SLA 为外部承诺(通常与补偿相关)。
将它们分开建模可以让你改进可靠性(通过 SLO)而不会意外更改对外报告(SLA)。
我在 MVP 中应该优先实现哪些 SLA 指标?
一个稳健的最小可行产品通常端到端跟踪 1–3 个指标:
- 每服务每月的 可用性百分比
- 首次人工响应时间(TTFR)(通常只计工作时间)
- 针对高优先级事故的 解决时间(TTR)
这些指标清晰对应真实数据源,并迫使你早期实现难点(周期、日历、排除项)。
在设计数据库或编写计算器之前,我需要哪些输入?
需求失败通常来自未明确的规则。先收集并写下:
- 合同 / SLA 文本(包含附录)
- 分层映射(哪个客户属于哪个计划)
- 每个客户/服务的时区与工作时间
- 明确的排除(维护、客户造成的延迟、不可抗力、宽限期)
如果一条规则无法清晰表述,不要在代码里“推断”它——标记并澄清后再实现。
值得信赖的 SLA 跟踪器的最小数据模型是什么?
从乏味但明确的实体开始:
- 客户(租户)
- 服务(被度量的对象)
- 计划(商业外壳)
- SLA 策略(目标 + 窗口 + 排除规则)
- 事件(用于计算的不可变事实)
- 事故(便于人理解的容器)
目标是可追溯性:每个报表数字应能链接回具体事件 ID和具体的策略版本。
我应该如何存储时间戳并处理时区(包括夏令时)?
正确且一致地存储时间:
- 将
occurred_at以 UTC 保存(带时区语义) - 另外保存
received_at(系统何时看到事件) - 将客户的 IANA 时区保存用于显示和工作时间逻辑,但不要用它去改写事件时间
并把周期明确为起止时间戳,这样即便跨 DST 也能复现报告。
如何可靠摄取事件以避免重复或错误数据污染报告?
把所有上游数据规范化为统一的内部事件形状,并用稳定唯一 ID:
event_id(唯一,能在重试间保持稳定)source、event_type、occurred_at、service_id- 可选的
incident_id与attributes
通过在 event_id 上加唯一约束实现幂等。对于未映射或乱序到达的事件,应隔离/标记处理——不要默默“修正”数据。
当涉及工作时间、暂停和排除时,如何正确计算 TTFR/TTR?
通过在时间线上的区间求和来计算时长,而不是简单地用两个时间戳相减。
明确“计费时间”要去除的区间,例如:
- 工作时间之外(若 SLA 仅计工作时间)
- 明确的暂停(如“等待客户”)
- 排除的计划维护(若策略如此规定)
将派生出的区间和原因码持久化,以便你能精确说明哪些时间被计入了计算。
应如何计算可用性(可计分钟数 vs 总分钟数)?
明确跟踪两个分母:
- 可计分钟数(eligible minutes):计入 SLA 的分钟(通常排除计划维护、客户造成的中断或支持时段外的时间)
- 停机分钟数(downtime minutes):在可计分钟内被判定为服务不可用的分钟
然后计算:
availability_percent = 100 * (eligible_minutes - downtime_minutes) / eligible_minutes
还需决定当可计分钟为零时的处理(例如显示 N/A 或视为 100%),并始终如一地记录该规则。
仪表板和告警应包含什么内容才能有用且不过度噪声?
让 UI 能在一眼之内回答“我们现在是否满足 SLA,为什么?”:
- 显示当前周期合规性以及“距离违约还剩多少时间/预算”
- 提供可钻取的路径:指标 → 本期被计入的事故清单 → 原始事件/区间
- 标签清晰(例如“本月可用性”),并在服务页显示准确的 SLA 规则文本
对于告警,优先可执行的触发类型:接近违约、已违约、重复违规——并把链接指向相关页面,如 /customers/{id} 或 /services/{id}。