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

Dozzle 告警与 Webhook 通知指南:用表达式监控容器日志、资源指标与生命周期事件

Dozzle 告警与 Webhook 通知指南用表达式监控容器日志、资源指标与生命周期事件【免费下载链接】dozzleRealtime log viewer for containers. Supports Docker, Swarm and K8s.项目地址: https://gitcode.com/GitHub_Trending/do/dozzleDozzle 内置了一套完整的告警系统它可以持续监听容器的日志、资源使用率和 Docker 生命周期事件一旦满足你编写的表达式条件就通过 Webhook、Slack、Discord、ntfy 或 Dozzle Cloud 通知你。本文以 docs/guide/alerts-and-webhooks.md及西班牙语文档 docs/es/guide/alerts-and-webhooks.md为核心结合仓库源码深入讲解三种告警类型的表达式语法、通知目标的配置方式、采样窗口与冷却机制的底层原理并给出可直接复制使用的实战示例。告警系统的核心概念Dozzle 的告警遵循规则留在自托管实例上的设计原则规则总是运行在存放日志的本地实例上因为日志就在那里。如果你的实例已经链接了 Dozzle Cloud这些规则会同时为云端供数而投递环节分组、摘要、静默、移动端通道则统一在云端配置不必在本地逐目标重复设置。每条告警都由两部分组成容器表达式container expression选择要监控哪些容器触发表达式trigger expressionlog、metric 或 event 三种之一定义触发条件。从源码角度看告警在仓库中被称为订阅Subscription。internal/notification/types.go 中的Subscription结构体同时保存了ContainerExpression、LogExpression、MetricExpression、EventExpression四类表达式字符串以及Cooldown冷却秒数默认 300和SampleWindow采样窗口秒数默认 15两个调优参数并缓存编译后的程序。表达式使用expr-lang/expr引擎编译执行见 CompileExpressions这一引擎同样被广泛用于其他表达式驱动的工具。三种告警类型Dozzle 支持三种告警全部可以在Notifications通知页面以同样的方式配置类型触发条件典型使用场景日志告警匹配特定模式的日志消息5xx 错误、堆栈跟踪指标告警CPU / 内存跨越阈值容器 CPU 占用超过 90%事件告警Docker 容器生命周期事件OOM kill、容器不健康前端入口为 assets/components/notifications/AlertForm.vue创建表单以 5 个步骤引导完成配置选择告警类型 → 编写容器过滤表达式 → 编写触发条件 → 选择投递目标 → 命名。持久化配置必须挂载 /data 目录[!IMPORTANT] 告警规则与通知目标的配置保存在/data目录中。你必须将该目录挂载为卷才能在容器重启后保留通知设置。这一约束在源码中有明确体现internal/notification/persist.go 定义了默认配置路径./data/notifications.yml和./data/cloud.ymlPersister.Load()在启动时读取、SaveNotifications()在每次变更后写盘。如果/data未挂载容器重建后一切告警配置都会丢失。以下两种部署方式都能正确持久化docker run -v /var/run/docker.sock:/var/run/docker.sock -v /path/to/data:/data -p 8080:8080 amir20/dozzle:latestservices: dozzle: image: amir20/dozzle:latest volumes: - /var/run/docker.sock:/var/run/docker.sock - /path/to/data:/data ports: - 8080:8080需要说明的是告警功能依赖 Docker 套接字读取日志、订阅事件、采集统计信息所以必须同时挂载/var/run/docker.sock。此外仓库自带的 e2e/data/notifications.yml 展示了该配置文件的持久化形态可供参考。配置通知目标在创建告警之前需要先在 Dozzle 的Notifications页面点击Add Destination添加目标至少配置一个通知目标。Webhook 目标Webhook 会向指定 URL 发送一次 HTTP POST 请求。Dozzle 为常见服务内置了可直接选用的 payload 模板Slack—— 使用 blocks 与 markdown 格式Discord—— 按 Discord Webhook API 格式化ntfy—— 按 ntfy.sh 推送通知格式化仅文档提及不输出外部链接Custom—— 可自由定制的通用 JSON payload。这些内置模板的完整内容定义在 assets/components/notifications/payloadTemplates.ts例如 Slack 模板使用{{ .Container.Name }}作为消息文本、{{ .Detail }}作为正文Discord 模板将信息放入embeds的fieldsntfy 模板生成topic、title、message三段式 JSONCustom 模板则只包含container与message两个字段是自研系统对接的起点。自定义 payload 模板除了内置模板你还可以使用 Go 的text/template语法编写自己的 payload 模板。可用变量如下变量说明{{.Detail}}摘要日志消息或指标值{{.Container.Name}}容器名称{{.Container.Image}}容器镜像{{.Container.HostName}}Docker 主机名{{.Container.State}}容器状态{{.Log.Message}}日志消息内容{{.Log.Level}}日志级别{{.Log.Timestamp}}日志时间戳{{.Log.Stream}}流类型stdout/stderr{{.Stat.CPUPercent}}CPU 使用百分比{{.Stat.MemoryPercent}}内存使用百分比{{.Stat.MemoryUsage}}内存使用量字节{{.Subscription.Name}}告警规则名称这些字段与后端定义一一对应。types/notification.go 中的NotificationContainer、NotificationLog、NotificationStat、NotificationEvent即为模板与表达式的共享数据模型其中NotificationStat还额外暴露了mounts字段磁盘挂载点的用量统计见 types/notification.go可配合any(mounts, .usedPercent 85)一类的写法做磁盘空间告警这属于原文档之外的扩展能力。值得深入说明的是模板执行原理。与传统text/template直接渲染整个字符串不同internal/notification/dispatcher/webhook.go 的executeJSONTemplate会先把模板文本按 JSON 解析再递归遍历结构仅对字符串值中出现的{{...}}占位符执行模板。这样做的效果是日志消息里即使包含引号、花括号等特殊字符最终 payload 也始终是合法 JSON不会被错误转义。如果模板本身不是合法 JSON则回退为纯text/template执行。Webhook 的 HTTP 行为同样由该文件定义NewWebhookDispatcher 只接受http和https两种 schemeHTTP 客户端配置了 10 秒超时默认请求头为Content-Type: application/json并带 Dozzle 的 User-Agent。安全防护内置 SSRF 防护Webhook 目标地址由管理员配置但 Dozzle 仍对其做了 SSRF服务端请求伪造防护isBlockedIP 会拒绝回环地址loopback、链路本地地址link-local、组播地址以及0.0.0.0/8等可能指向本机或元数据服务如169.254.169.254的地址段同时 embeddedIPv4 还会解开 6to4、NAT64、Teredo 等 IPv6 过渡机制中内嵌的 IPv4 地址再行检查。RFC1918 私网段是有意放行的——自托管 WebhookHome Assistant、内部 Mattermost 等通常就在局域网内。[!TIP] 保存 Webhook 前务必使用Test测试按钮验证其可用性。后端对应SendTest实现会真实发起请求并返回状态码或错误信息见 webhook.go。Dozzle Cloud 目标已链接的实例会自动获得Dozzle Cloud作为通知目标。与裸 Webhook 不同它会将重复失败聚合成单条通知、汇总事件经过并分发到邮件、Telegram、Discord、Slack、ntfy 和浏览器推送无需在此逐个配置。详见 Dozzle Cloud 文档。从实现上看云端目标对应DispatcherID 0的特殊约定manager.go 的getDispatcher在订阅的DispatcherID为 0 时返回专用的 CloudDispatcher当实例链接云端时persist.go 会自动创建该分发器并注册。创建告警进入Notifications页面并点击Add Alert添加告警。每条告警都有一个容器表达式外加 log、metric、event 三种触发表达式之一。容器表达式选择要监控的容器容器表达式用于筛选监控对象。可用属性属性类型示例name字符串name contains apiimage字符串image nginx:lateststate字符串state runninghealth字符串health unhealthyhostName字符串hostName prod-hostlabels映射labels[env] production这些属性来源于 types/notification.go 的NotificationContainer还有id、hostId可供使用。条件可用与、||或、!非自由组合name contains api labels[env] production在 internal/notification/processing.go 的处理流程中每个日志/统计/事件到达时都会先经MatchesContainer过滤见 types.go不匹配的容器直接跳过避免无谓的计算与日志流开销。另外isDozzleContainer 会排除 Dozzle 自身容器产生的日志与事件防止告警系统监控自己形成反馈循环。日志告警Log Alerts日志表达式日志表达式过滤哪些日志消息会触发告警。可用属性属性类型示例message字符串/映射message contains errorlevel字符串level errorstream字符串stream stderrtype字符串type complex对于 JSON 日志可以用点号访问嵌套字段message.status 500 message.path contains /api支持的字符串操作符包括contains、startsWith、endsWith和matches正则表达式。这里有一个值得注意的实现细节对于结构化JSON/对象日志extractMessage 会把有序映射转换为普通map[string]any以便与expr引擎的求值方式兼容而分片日志grouped fragments会被拼接成单条字符串ANSI 颜色码则通过StripANSI剥离。因此message.status这类点号访问对 JSON 日志天然有效而对纯文本日志执行该写法时只会求值失败并被静默忽略不会误报。日志告警示例对生产环境容器的全部错误告警Container: labels[env] production Log: level error对 API 容器的 HTTP 5xx 错误告警Container: name contains api Log: message.status 500对特定镜像的任何 stderr 输出告警Container: image startsWith myapp/ Log: stream stderr对生产环境 API 慢响应告警Container: name contains api labels[env] production Log: message.duration 5000 message.path contains /api使用正则对认证失败告警Container: name contains auth || name contains gateway Log: message matches (?i)(unauthorized|forbidden|invalid token)[!NOTE] 告警编辑器提供自动补全与实时校验。保存前可以预览匹配的容器和日志。后端对应 internal/web/notifications.go 的PreviewResult它不仅返回编译错误还会实际扫描匹配容器中的近期日志、给出命中样本与总数让这条规则到底会命中什么在保存前就一目了然。指标告警Metric Alerts指标告警在容器的 CPU 或内存使用量跨越阈值时触发。触发表达式是基于移动窗口内采样统计的平滑平均值进行求值的从而避免短暂尖峰造成的误报。指标表达式可用属性属性类型说明cpu数字CPU 使用百分比0-100与界面显示一致memory数字内存使用百分比0-100memoryUsage数字内存使用量字节采样窗口与冷却机制采样窗口Sample Window求值表达式前对多少秒的统计数据取平均。窗口越长尖峰越被平滑窗口越短反应越快。冷却Cooldown同一容器连续两次触发之间的最小秒数防止容器持续高于阈值时告警洪泛。这两个参数在源码中有清晰的默认值与边界约束GetCooldownSecondsCooldown取值被限制在[0, 3600]秒默认不设置时为 0不限流GetSampleWindowSecondsSampleWindow默认15秒合法范围为[1, 300]秒RecordMetricSample 是窗口平滑的核心每个容器维护一个容量等于窗口大小的环形缓冲区当缓冲区写满且匹配样本占比 ≥ 80% 时才真正触发告警——这就是平滑平均值的具体实现也解释了为什么短暂尖峰不会误报窗口为 1 时则直接按单次结果判定。另一个细节是 CPU 归一化processing.go 在求值前会按容器 CPU 配额或主机核心数将原始每核百分比归一化为 0-100 的整体负载与界面上看到的数值保持一致。指标告警示例生产环境容器 CPU 过高Container: labels[env] production Metric: cpu 90特定服务内存压力Container: name contains api Metric: memory 85绝对内存用量1 GiBContainer: name postgres Metric: memoryUsage 1073741824事件告警Event Alerts事件告警基于 Docker 容器生命周期事件触发适用于捕捉崩溃、OOM kill 和健康状态变化无需解析日志。事件表达式可用属性属性类型说明name字符串事件名称见下actorId字符串Docker actor ID通常为容器 IDattributes映射Docker 事件属性随事件类型而异timestamp时间事件发生时间常见的 Docker 事件名称包括start、stop、die、kill、oom、restart、destroy和health_status。对于health_status事件Dozzle 将当前状态暴露为attributes[healthStatus]healthy或unhealthy。这一点在源码层面有专门的规范化逻辑event_listener.go 的normalizeEvent会把 Docker 原始格式health_status: healthy/health_status: unhealthy折叠为裸事件名health_status并将状态写入healthStatus属性从而让name health_status attributes[healthStatus] unhealthy这类表达式可以稳定匹配。同时 allowedEventNames 只放行start、stop、die、restart、health_status、oom、kill七个白名单事件其余一律丢弃Dozzle 自身容器的事件同样被过滤。事件告警示例任何生产环境容器死亡时告警Container: labels[env] production Event: name dieOOM kill 告警Container: true Event: name oom容器变为不健康时告警Container: true Event: name health_status attributes[healthStatus] unhealthy意外退出告警忽略正常与优雅关闭退出码 0成功、130SIGINT、143SIGTERM和 137SIGKILL会在docker stop、CtrlC 和更新循环中产生因此被排除以免制造噪音。真正的错误退出1、2、125 等仍会触发告警。Container: name contains worker Event: name die !(attributes[exitCode] in [0, 130, 143, 137])源码对退出码有更细致的标注processing.go 定义了signalExitCodes映射将 129/130/131/134/137/139/143 分别标注为 SIGHUP/SIGINT/SIGQUIT/SIGABRT/SIGKILL/SIGSEGV/SIGTERM。发送事件通知时die事件的Detail会附带退出码及信号名如137, SIGKILL避免把普通的更新重启误判为 OOM——真正的内存溢出会以独立的oom事件到达。事件监听器本身还带有 30 秒的容器信息 TTL 缓存与 1000 条容量的缓冲通道见 event_listener.go用于在高频事件下保持性能。底层架构从事件到通知的完整链路理解告警系统的整体数据流有助于调试与预估负载。核心调度器是 internal/notification/manager.go 中的Manager它同时驱动三个监听器日志监听器ContainerLogListener—— 仅在存在启用中的日志告警时按需订阅相关容器的日志流ShouldListenToContainer 表明只有日志类告警需要日志流纯指标告警不产生流式开销统计监听器ContainerStatsListener—— 存在指标告警时启动否则停止事件监听器ContainerEventListener—— 存在事件告警时启动否则停止。三个监听器将事件推入各自的 channel由 processing.go 的三个processXxxEvents协程消费每个事件依次经过订阅是否启用 → 是否为对应类型 → 容器表达式 → 触发表达式→ 采样窗口 → 冷却的级联过滤命中后构造types.Notification并交给订阅绑定的分发器异步发送。异步发送受信号量保护sendNotification 使用容量为 5 的semaphore.Weighted限制并发单次发送超时 30 秒避免网络阻塞拖垮主流程每个分发器的 HTTP 客户端另有 10 秒超时。触发次数、最近触发时间、命中容器集合等运行时统计由 GetNotificationStats 汇总最终通过 API 呈现在管理界面。管理告警在 Notifications 页面你可以启用/禁用告警而不删除它们编辑告警表达式与目标查看统计信息包括触发次数、匹配的容器数以及最近触发时间删除不再需要的告警。这些操作全部通过 internal/web/notifications.go 暴露的 REST API 完成其中NotificationRuleUpdateInput支持对单个字段做部分更新如仅切换enabled而不动表达式。前端 AlertForm.vue 在保存前会校验容器表达式、条件、目标与名称四项是否齐全并带有未保存变更的关闭确认守卫防止误操作丢失半成品规则。结语Dozzle 的告警系统把监控哪些容器和什么条件触发抽象成了两个可组合的表达式覆盖日志、指标、事件三大信号源再配合采样窗口、冷却与按需启动的监听器在功能完备的同时控制了资源开销。建议从日志告警的level error起步逐步叠加指标阈值与事件规则并善用编辑器自带的实时预览功能验证每一条规则的实际命中范围同时牢记挂载/data目录让告警配置像日志一样持久可靠。【免费下载链接】dozzleRealtime log viewer for containers. Supports Docker, Swarm and K8s.项目地址: https://gitcode.com/GitHub_Trending/do/dozzle创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

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

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