拓冰建站拓冰建站
首页 / 资讯中心 / 正文

OneUptime Incoming Request Monitor 完整实战指南:心跳监控、死键检测与 Alertmanager/Grafana 告警接入

OneUptime Incoming Request Monitor 完整实战指南心跳监控、死键检测与 Alertmanager/Grafana 告警接入【免费下载链接】oneuptimeComplete open-source monitoring and observability platform.项目地址: https://gitcode.com/GitHub_Trending/on/oneuptimeIncoming Request Monitor入站请求监控是 OneUptime 平台中一种特殊的监控类型它不是让 OneUptime 主动探测你的服务而是提供一个唯一 URL让你自己的系统cron 任务、后台 Worker、防火墙内服务、Prometheus Alertmanager、Grafana 等主动向它发送 HTTP 请求。OneUptime 会依据你配置的监控标准Criteria对每一次入站请求进行评估进而切换监控状态、开启事件Incident并触发值班轮换。读完本文你将掌握 Incoming Request Monitor 的完整配置方法、请求地址与请求体规范、监控标准Filter Type / Filter Condition / Value的语义与源码级实现原理以及如何借助事件分组Incident Grouping将 Alertmanager/Grafana 的多条告警映射为独立事件。概述两种截然不同的用途同一种监控类型Incoming Request Monitor 同时覆盖两类差异很大的场景而它们共用同一个监控类型区别只在于你配置的监控标准心跳监控Heartbeat Monitoring——定时任务、Worker 或设备按固定时间表 ping 一个 URL当 ping 停止时OneUptime 触发事件。典型场景包括跟踪定时任务与 cron 任务、确认后台 Worker 是否存活、监控位于防火墙之后从外部不可达的服务。接收其他系统的告警Alert Ingestion——Prometheus Alertmanager、Grafana 或任何能发送 JSON POST 的系统把告警推送到该 URLOneUptime 将每条告警转换为一个事件并支持值班升级Escalation与自动恢复Auto Resolve。从代码层面看这两类场景最终都落入同一条入站请求处理链路Probe 侧的 Probe/API/IncomingRequestIngress.ts 接收/heartbeat/:secretkey与/incoming-request/:secretkey路由GET/POST 均注册转发到 OneUptime 后端后端再交由 Common/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.ts 依据监控标准逐条评估。创建 Incoming Request Monitor在 OneUptime 仪表盘中按以下步骤创建进入Monitors页面点击Create Monitor监控类型选择Incoming RequestOneUptime 会为这个监控生成一个Secret Key和一个专属地址打开该监控在左侧菜单点击Documentation复制该地址将你的服务配置为向该地址发送请求按下方说明配置监控标准创建完成后监控状态与事件流转完全由入站请求驱动请求内容决定在线/降级/离线状态请求缺失Dead Mans Switch 场景则由时间窗口标准触发。请求地址解析路径、方法与响应语义每个 Incoming Request Monitor 拥有一个唯一地址格式如下https://oneuptime.com/heartbeat/YOUR_SECRET_KEY如果你自托管Self-HostedOneUptime请将https://oneuptime.com替换为你自己实例的地址。HTTP 方法与认证支持向该地址发送GET或POST请求HEAD也会被接受并如同 GET 一样处理其他 HTTP 方法一律返回404。Secret Key 是唯一的凭据直接放在 URL 路径中——不需要任何 Header 或 Token。这从路由注册中可以得到印证Probe 入口同时注册了router.post(/incoming-request/:secretkey, ...)与router.get(/incoming-request/:secretkey, ...)见 Probe/API/IncomingRequestIngress.ts。安全警告任何知道该 URL 的人都可以把你的监控标记为“在线”所以请像对待密钥一样对待它。此外你发送的所有 Header 都会被存储在监控上任何能读取该监控的人都可见——绝对不要把 API Key 或 Token 放在 Header 中发送到这个端点。关于 200 响应的重要语义OneUptime 会立即返回一个空的200并把请求放入处理队列。这个响应在任何校验之前就已写出因此200并不代表请求已被接受即使 Secret Key 错误、监控已被删除或监控处于禁用状态也都会返回200。要确认请求是否真正到达请查看监控自身的时间线Timeline。这一“先响应、后处理”的设计在 Probe 转发实现中同样可见forwardToOneUptime在Response.sendEmptySuccessResponse之后才异步执行forwardWithRetry带指数退避重试确保客户端感知到的延迟极低。发送请求体Request Body如果你需要寻址请求体内部的字段——例如在事件标题中使用{{requestBody.status}}、在事件分组中使用 JSON 路径、或使用 JavaScript 表达式类型的标准——请发送Content-Type: application/json。本文档中的所有示例均基于这一格式。application/x-www-form-urlencoded的请求体也会被解析但只会解析顶层扁平字段。其他任何 Content-Type、或完全没有 Content-Type 的请求请求体不会被解析所有requestBody引用都会解析为空。请求体最大接受50 MB。不要使用Content-Encoding: gzip压缩请求体——它会以未解析的状态被存储内部的路径也无法解析。从源码看请求体最终以requestBody?: string | JSONObject | undefined的形式进入评估层见 Common/Types/Monitor/IncomingMonitor/IncomingMonitorRequest.ts评估时字符串类型的 body 会被JSON.stringify归一化后参与比较。发送心跳curl、cron 与程序代码使用 curl# Simple GET request curl https://oneuptime.com/heartbeat/YOUR_SECRET_KEY # POST request with custom body curl -X POST https://oneuptime.com/heartbeat/YOUR_SECRET_KEY \ -H Content-Type: application/json \ -d {status: healthy, version: 1.2.3}从 cron 任务发送# Add to crontab to send heartbeat every 5 minutes */5 * * * * curl -s https://oneuptime.com/heartbeat/YOUR_SECRET_KEY /dev/null从程序代码发送// Node.js example const https require(https); https.get(https://oneuptime.com/heartbeat/YOUR_SECRET_KEY);# Python example import requests requests.get(https://oneuptime.com/heartbeat/YOUR_SECRET_KEY)监控标准Criteria如何判定在线、降级与离线你可以配置多条监控标准以决定你的服务何时被视为在线Online、降级Degraded或离线Offline。每条过滤标准由三部分组成Filter Type看什么——检查对象Filter Condition怎么比——比较方式Value比较值——阈值或匹配内容新监控自带的默认标准新建的 Incoming Request Monitor 会自带两条基于请求体的标准标准过滤类型过滤条件值效果OfflineRequest BodyContainserror将监控标记为离线并打开一个事件OnlineRequest BodyNot Containserror将监控标记为在线这套默认配置覆盖了最常见的场景发送方在负载Payload中自报健康状况——请求体包含error的请求会让监控离线下一条不含error的请求则会把它恢复在线。完全没有请求体的请求会被视为“不包含error”所以单纯的心跳 ping 也能让监控保持在线。请把值改成你的发送方实际发出的内容例如status:firing、FAILED等——匹配是区分大小写的子串匹配。注意这些默认标准不是死键Dead Mans Switch。当请求停止到达时这里没有任何标准会触发。如果你想针对“沉默”告警需要按下方说明添加一条Incoming Request类型的Not Recieved In Minutes标准。可用的 Filter Type 一览过滤类型检查什么备注Incoming Request在某个时间窗口内是否收到了请求唯一能在“没有请求到达”时触发的检查类型Request Body请求体子串匹配。对象型请求体按压缩后的 JSON 比较Request Header请求中的 Header 名称与 Header 名称精确匹配且转为小写Request Header Value请求中 Header 的值与 Header 值精确匹配且转为小写JavaScript Expression针对requestBody与requestHeaders的任意表达式最灵活的选择——参见 JavaScript 表达式文档Filter Condition 一览每种 Filter Type 提供各自的条件集合。Incoming Request按仪表盘中的拼写呈现Recieved In Minutes——在指定分钟数内收到了请求Not Recieved In Minutes——在指定分钟数内未收到任何请求Request Body、Request Header 与 Request Header ValueContains和Not Contains。JavaScript ExpressionEvaluates To True。注意Header 名称与值在比较前都会转为小写且匹配是针对完整名称或值而非子串。请写content-type而不是Content-Type写application/json而不是application/JSON。只有 Request Body 是真正的子串匹配。对象型请求体按去空格压缩后的 JSON进行比较因此Request Body / Contains过滤必须写成status:firing——直接复制美化后pretty-printed负载中的status: firing永远不会匹配。源码级的匹配实现这些语义在 Common/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.ts 中逐条实现可作为你编写标准的“行为契约”Recieved In Minutes / Not Recieved In Minutes用incomingRequestReceivedAt最近一次请求到达时间与checkedAt计算分钟差differenceInMinutes value时 Recieved 命中differenceInMinutes value时 Not Recieved 命中。Request Body空请求体被归一化为而不是“未知”这正是默认 Online 标准Not Containserror能让无请求体的心跳 ping 命中的根本原因Contains 不受影响空字符串不含任何内容。Request Header / Request Header Value比较时两侧都转小写且是数组级别的整体包含判断headerKeys.includes(...)/headerValues.includes(...)即精确匹配而非子串。相关的枚举定义CheckOn、FilterType集中在 Common/Types/Monitor/CriteriaFilter.ts其中IncomingRequest Incoming Request、RequestBody Request Body、RequestHeader Request Header、RequestHeaderValue Request Header Value、JavaScriptExpression JavaScript ExpressionNotRecievedInMinutes/RecievedInMinutes也在此定义。标准配置示例10 分钟没有心跳即标记离线死键Filter Type: Incoming RequestFilter Condition: Not Recieved In MinutesValue: 10依据请求体内容标记降级Filter Type: Request BodyFilter Condition: ContainsValue:status:degraded警告一个监控只有在至少一条标准检查 Incoming Request 时才会在后台被重新评估。如果监控的标准只检查 Request Body、Request Header 或 JavaScript 表达式它只会在有请求到达时被评估其他时间一概不会——因此它永远无法自行离线。如果你需要“心跳丢失”告警就必须添加一条 Incoming Request 类型的标准。另外请注意从未收到过请求的监控会被当作“在创建时收到了最后一次请求”。因此Not Recieved In Minutes: 10的标准会在新监控创建 10 分钟后触发即使发送方从未接入——这是首次搭建时的常见“惊吓点”。接收其他系统的告警Alertmanager、Grafana 与事件分组Alertmanager、Grafana 以及类似的工具会 POST 一个描述一条或多条告警的 JSON 文档。默认情况下一条命中Criteria Match只打开一个事件——所以一个携带 5 条告警的负载只会产生一个事件。事件分组Incident Grouping可以改变这一点它从负载中提取一个值并为每个不同的值打开一个独立事件这些事件可以同时保持开启状态。启用事件分组打开标准Criteria展开Settings开启Group incidents and alerts by a payload field。此时会出现四个字段字段示例作用为每个……打开独立事件requestBody.alerts[*].labels.alertname其不同取值用于区分事件的路径表示恢复的字段requestBody.alerts[*].status用于判断某条告警是否恢复的路径表示已恢复的值resolved精确标记恢复的值每个请求的最大事件数100默认安全上限防止高基数字段打开无限数量的事件“每个请求的最大事件数”这一默认值 100 在源码中有直接对应IncomingRequestIncidentGrouping中定义了DEFAULT_MAX_KEYS_PER_PAYLOAD 100见 Common/Server/Utils/Monitor/IncomingRequestIncidentGrouping.ts。路径语法路径必须以字面量前缀requestBody.开头。缺少该前缀的路径如alerts[*].labels.alertname会静默地什么都不匹配。{{ }}包裹是可选的requestBody.status与{{requestBody.status}}行为相同。[*]通配符会展开一个数组——每个不同的值生成一个事件。两个产生相同值的元素会合并到同一个事件该事件的触发/恢复状态取自第一个匹配的元素。只有路径中的第一个[*]会被展开requestBody.groups[*].alerts[*].name不会匹配任何内容。[0]与[last]选择单个元素并且可以出现在[*]之后。对象与数组类型的值、空字符串和 null 会被忽略0与false是有效的键值。恢复是事件驱动的Event-Driven ResolutionWebhook 只描述它携带的负载中的内容因此 OneUptime绝不会因为某个键不再出现而自动恢复事件。事件只有在负载显式声明该键已恢复时才会被解决。两个条件必须同时成立表示恢复的字段与表示已恢复的值都已设置并且与负载匹配。比较是精确且区分大小写的——Resolved不会匹配resolved。该标准的事件Incident在Advanced Options事件表单下方中开启了Auto Resolve Incident选项。否则恢复事件会被忽略事件将一直保持开启。这一点对告警与Auto Resolve Alert同样适用。每个请求的最大事件数限制的不只是提取还包括恢复超过上限的键对恢复也不可见。因此在一个包含超过上限个不同键的负载中即使某个告警报告了resolved它的事件也不会被关闭。警告如果表示恢复的字段包含[*]而为每个……打开独立事件不包含那么永远不会恢复任何内容。要么两者都用[*]要么两者都不用。不带[*]的恢复路径会针对整个负载进行判断因此负载级别的status: resolved会恢复该负载中的每一个键——包括那些自身状态仍为 firing 的告警。事件命名分组键会作为变量提供给事件与告警模板变量名取路径的最后一段路径变量requestBody.alerts[*].labels.alertname{{alertname}}requestBody.alerts[*].fingerprint{{fingerprint}}requestBody.commonLabels.severity{{severity}}完整负载也一并可用所以标题设为{{alertname}}、描述引用{{requestBody.commonAnnotations.summary}}的事件可以同时工作。更多细节见 事件与告警的动态模板化。警告变量名是 OneUptime 用于把恢复事件与已打开事件匹配的身份标识的一部分。把分组路径改成结尾段不同的路径会让当前在该旧路径下已打开的所有事件“孤儿化”——它们将无法被自动恢复必须手动关闭。请注意[*]只在上述两个分组路径字段中生效。在其他地方它不会被展开且未展开的通配符会原样打印而非留空——例如标题为{{requestBody.alerts[*].labels.alertname}}会连同花括号一起渲染出来。标题为{{requestBody.alerts[0].annotations.summary}}会被展开但它永远读取负载中的第一条告警而不是为当前事件打开的那条告警。建议优先使用分组变量以及负载的公共字段commonAnnotations。集成实践完整的 Alertmanager 配置请参阅 Prometheus Alertmanager 集成。Grafana 的配置请参阅 Grafana 集成。最佳实践设置合适的时间窗口——如果你的 cron 任务每 5 分钟运行一次请把Not Recieved In Minutes阈值设为 10–15 分钟以容忍偶发的调度延迟。携带有意义的数据——在请求体中发送状态信息这样才能构建细粒度的监控标准。使用Content-Type: application/json的 POST——所有读取请求体内部字段的功能都依赖它。不要在一个监控上混用两种职责——接收事件驱动告警的监控没有固定节奏Not Recieved In Minutes标准会在其上抖动误报。请为死键场景单独使用一个监控。监控发送方——确保发送请求的服务具备正确的错误处理不要让失败的请求悄无声息地消失。进一步阅读Prometheus Alertmanager 集成——完整的入站告警接入指南Grafana 集成——Grafana 告警的同类接入事件与告警的动态模板化——标题与描述中可用的所有变量JavaScript 表达式——表达式语法与引号规则【免费下载链接】oneuptimeComplete open-source monitoring and observability platform.项目地址: https://gitcode.com/GitHub_Trending/on/oneuptime创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门