资讯详情

资讯详情

Dozzle 告警与 Webhook 通知体系详解:Log、Metric、Event 三类告警的配置与源码实现

Dozzle 告警与 Webhook 通知体系详解Log、Metric、Event 三类告警的配置与源码实现【免费下载链接】dozzleRealtime log viewer for containers. Supports Docker, Swarm and K8s.项目地址: https://gitcode.com/GitHub_Trending/do/dozzleDozzle 除了实时查看容器日志还内置了一套基于表达式expression的告警引擎它可以监视容器日志、CPU/内存指标和 Docker 生命周期事件在你描述的条件成立时把通知投递到 Webhook、Slack、Discord、ntfy 或 Dozzle Cloud。本文以官方文档 alerts-and-webhooks英文原版见 docs/guide/alerts-and-webhooks.md为主体完整覆盖三类告警的配置语法与实战示例并结合 internal/notification 包中的源码解释每条规则从匹配、冷却到投递的完整执行链路。告警体系概览Dozzle 支持三种告警类型它们都在界面的Notifications通知页面以相同的方式配置类型触发条件典型场景Log日志某条日志消息匹配了模式5xx 错误、堆栈跟踪Metric指标CPU / 内存超过阈值容器 CPU 超过 90%Event事件Docker 容器生命周期事件OOM Kill、容器变为不健康每条告警都由两部分组成一个**容器表达式container expression决定监视哪些容器一个触发表达式trigger expression**描述触发条件。规则始终保存在你自托管的实例上因为日志就在你的实例里如果实例接入了 Dozzle Cloud同一批规则也会喂给云端由云端负责投递策略聚合、摘要、免打扰、移动端通道。重要告警与目标的配置存放在/data目录中必须将该目录挂载为 Volume否则容器重启后通知配置会丢失。docker run -v /var/run/docker.sock:/var/run/docker.sock -v /path/to/data:/data -p 8080:8080 amir20/dozzle:latest# docker-compose.yml services: dozzle: image: amir20/dozzle:latest volumes: - /var/run/docker.sock:/var/run/docker.sock - /path/to/data:/data ports: - 8080:8080从源码看这个挂载要求对应 persist.go 中的两个默认路径const ( DefaultNotificationConfigPath ./data/notifications.yml DefaultCloudConfigPath ./data/cloud.yml )也就是说所有告警规则与目标最终会以 YAML 形式落在/data/notifications.yml云端凭据落在/data/cloud.yml。Persister结构体persist.go负责读写这两个文件并在启动时将其应用回内存中的Manager写文件通过utils.WriteFile完成配置在 API 变更后即被持久化。端到端测试数据文件 e2e/data/notifications.yml 也展示了该 YAML 配置的形态。配置通知目标Destination创建告警前至少要配置一个通知目标。进入 Dozzle 的Notifications页面点击Add Destination。Webhook 目标Webhook 会向任意 URL 发送一条 HTTP POST 请求。Dozzle 为常用服务内置了 Payload 模板定义在前端 payloadTemplates.ts 中Slack— 使用 Blocks 和 Markdown 格式化Discord— 按 Discord Webhook API 格式化ntfy— 按 ntfy 推送通知格式Custom— 可自定义的通用 JSON Payload也可以自己编写 Payload 模板使用 Go 的text/template语法。可用的变量如下界面中TemplateVariables组件会展示这些变量对应 assets/components/notifications/TemplateVariables.vue变量说明{{.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它包含Detail、Container、可选的Log/Stat/Event三个负载按告警类型填充其一、Subscription和时间戳。提示保存前可以使用Test按钮验证 Webhook 是否可用。测试与正式发送走同一个SendTest实现webhook.go成功与否以响应状态码是否为 2xx 判定。Webhook 发送器的源码细节阅读 dispatcher/webhook.go 可以了解几个文档未展开的约束URL 只允许 http/https。NewWebhookDispatcherL162-L196会先解析 URLscheme 不是 http/https 直接报错。内置 SSRF 防护。发送器使用自定义safeDialContext拨号isBlockedIPL33-L62拒绝回环地址、链路本地地址如云元数据端点 169.254.169.254、组播地址、0.0.0.0/8和有限广播地址并对 6to4/NAT64/Teredo 等 IPv6 过渡地址做了内嵌 IPv4 的解包检查RFC1918 私网段被有意放行因为自托管 WebhookHome Assistant、内部 Mattermost 等通常就在内网。模板执行是JSON 优先的。executeJSONTemplateL273-L297会先尝试把模板按 JSON 解析若成功则递归遍历结构、只渲染字符串值中出现的{{...}}占位符再整体序列化回 JSON——这保证日志消息里即使含有引号、花括号也不会破坏 JSON 转义若模板不是合法 JSON则退化为原始text/template执行。超时与错误日志。HTTP 客户端整体超时 10 秒响应非 2xx 时响应体最多读取 1MB 仅用于运维侧 debug 日志不会回显到 API 响应中避免成为 SSRF 数据外泄通道。Dozzle Cloud 目标已关联云端的实例会自动获得Dozzle Cloud目标。与裸 Webhook 不同它会把重复发生的故障聚合成一条通知、生成摘要并扇出到邮件、Telegram、Discord、Slack、ntfy 和浏览器推送无需在本地逐个配置渠道。云端目标由 dispatcher/cloud.go 实现并在 cloud_config.go / 持久层中通过/data/cloud.yml保存 API Key详见 Dozzle Cloud 文档。创建告警容器表达式在Notifications页面点击Add Alert。每条告警都有一个容器表达式加上Log / Metric / Event三选一 的触发表达式。容器表达式选择要监视哪些容器可用属性如下属性类型示例namestringname contains apiimagestringimage nginx:lateststatestringstate runninghealthstringhealth unhealthyhostNamestringhostName prod-hostlabelsmaplabels[env] production条件可以用与、||或、!非组合name contains api labels[env] production从源码看表达式由 expr-lang/expr把每个表达式分别针对 types.NotificationContainer、NotificationLog、NotificationStat、NotificationEvent四个环境类型做expr.Compile编译失败会在保存时返回明确错误——这就是编辑器能做实时校验的原因。运行时匹配则非常宽松MatchesContainer求值出错或非 bool 结果一律视为不匹配types.go不会因为一条坏日志让规则引擎崩溃。Log 告警日志表达式日志表达式过滤哪些日志消息会触发告警可用属性属性类型示例messagestring/mapmessage contains errorlevelstringlevel errorstreamstringstream stderrtypestringtype complexmessage之所以可能是 map对 JSON 日志complex 类型extractMessagetypes.go会把消息解析成普通 map 交给表达式引擎因此可以用点号访问嵌套字段message.status 500 message.path contains /api支持的字符串操作符包括contains、startsWith、endsWith和matches正则。日志告警示例生产容器出现任何错误都告警Container: labels[env] production Log: level errorAPI 容器出现 HTTP 5xxContainer: 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)说明告警编辑器提供自动补全与实时校验保存前可以预览命中的容器和日志。日志告警的执行链路日志告警的底层由 log_listener.go 与 processing.go 协作完成有两个值得注意的设计按需订阅日志流。ContainerLogListenerL27-L48并不会为每个容器无条件开日志流它先用ContainerMatcher判断某容器是否被任何启用的告警需要只对命中的容器调用client.StreamLogs建立流L120-L141当规则变更时UpdateStreamsL95-L117会动态增删监听避免无谓的日志读取开销。先容器匹配、后日志匹配。processLogEventprocessing.go对每条日志先解析容器带 5 秒超时的 TTL 缓存跳过 Dozzle 自身容器镜像含amir20/dozzle防止告警自我放大然后遍历所有启用的 Log 型订阅先MatchesContainer再MatchesLog命中后更新触发统计并异步投递。消息在匹配前已经过 ANSI 转义序列剥离因此matches正则不需要考虑颜色码。Metric 告警指标告警在容器的 CPU 或内存使用率越过阈值时触发。触发表达式针对一个滚动采样窗口内的统计结果求值用以避免瞬时尖峰造成误报。指标表达式属性类型说明cpunumberCPU 使用百分比0–100与界面口径一致memorynumber内存使用百分比0–100memoryUsagenumber内存用量字节两个源码级细节CPU 已按核心数归一化。Docker 原始 stats 的 CPU 是每核口径100% 打满一个核processStatEventprocessing.go会先除以CPULimit或主机核数再交给表达式所以cpu 90的含义和 UI 上看到的一致。额外可查询的mounts字段。NotificationStat 除了三个标量还暴露了mounts数组含usedPercent、availableBytes等字段见 NotificationMount可以写any(mounts, .usedPercent 85)这类卷空间表达式无法测量空闲空间的卷如 Windows 卷、权限错误会被跳过不会误触发。采样窗口与冷却时间采样窗口Sample window求值前对多少秒的采样做平滑。窗口越长越能抹平尖峰越短反应越快。冷却时间Cooldown同一容器两次触发之间的最小秒数防止容器长期超阈值时告警刷屏。源码给出了明确的取值范围types.go采样窗口经GetSampleWindowSeconds限制在1–300 秒未设置时默认15 秒冷却时间经GetCooldownSeconds限制在0–3600 秒0表示关闭冷却。触发判定的精确逻辑在RecordMetricSampletypes.go每个容器维护一个环状缓冲ring buffer每次 stats 采样记录一次布尔匹配结果窗口填满后至少 80% 的采样命中才触发然后进入逐容器冷却。也就是说文档中平滑平均的描述落地实现是窗口内 80% 命中率的投票机制——比单次瞬时值稳健又比长时间平均更灵敏。指标告警示例生产容器高 CPUContainer: labels[env] production Metric: cpu 90特定服务内存压力Container: name contains api Metric: memory 85绝对内存用量1 GiBContainer: name postgres Metric: memoryUsage 1073741824指标事件来自 stats_listener.go它订阅所有客户端的 stats 流约每秒一个 tick为每条 stat 附带容器与主机元数据带 5 秒 TTL 缓存同样会跳过 Dozzle 自身容器再交给 Manager 处理。Event 告警事件告警在 Docker 容器生命周期事件上触发适合不解析日志就能发现崩溃、OOM 与健康状态变化。事件表达式属性类型说明namestring事件名见下文actorIdstringDocker actor ID通常是容器 IDattributesmapDocker 事件属性随事件类型而变timestamptime事件发生时间常见的 Docker 事件名包括start、stop、die、kill、oom、restart、destroy和health_status。需要注意从源码结构看event_listener.go 中的转发白名单目前是start、stop、die、restart、health_status、oom、kill七种未列入白名单的事件如destroy不会进入告警求值。对health_status事件Dozzle 会把当前状态暴露为attributes[healthStatus]healthy或unhealthy。这是normalizeEventevent_listener.go做的归一化Docker 原生发出的是health_status: healthy/health_status: unhealthy这类带冒号后缀的名字Dozzle 将其折叠为纯health_status并把状态写入healthStatus属性使得name health_status attributes[healthStatus] unhealthy这样的表达式成立。事件告警示例生产容器死亡时告警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])一个源码中的贴心细节die事件的通知详情会自动附带退出码并且signalExitCodes映射表processing.go会把 128N 型退出码翻译成信号名如137, SIGKILL、143, SIGTERM。代码注释解释了动机裸的 exit code 137 经常被误读为 OOM Kill而实际上 SIGKILL 更多来自docker stop宽限期超时、主机重启或镜像更新如 Watchtower真正的 OOM 会以独立的oom事件到来。命名信号从源头上消除了这种歧义。告警的管理与投递细节在Notifications页面你可以启用/禁用告警而不删除对应Subscription.Enabled字段编辑告警表达式与目标查看统计包括触发次数TriggerCount、命中的容器集合与最近一次触发时间LastTriggeredAt即 SubscriptionStats 暴露的内容删除不再需要的告警。前端管理界面由 assets/components/notifications 下的组件构成AlertForm.vue、DestinationForm.vue、WebhookDestinationForm.vue、LogAlertFields.vue、MetricAlertFields.vue、EventAlertFields.vue等后端 API 见 internal/web/notifications.go。投递环节还有两处影响可靠性的实现细节processing.go并发受限所有发送共享一个信号量获取令牌最长等 1 分钟拿不到就丢弃并记警告Notification dropped: too many pending避免下游故障时堆积无界 goroutine发送超时 30 秒单次 Webhook/云端投递带 30 秒上下文超时失败只记错误日志不影响其他订阅继续求值。另外三类监听器日志、stats、事件在入口处统一跳过 Dozzle 自身容器isDozzleContainertypes.go防止告警服务自己触发告警的反馈回路。小结Dozzle 的告警体系可以用三句话概括规则是表达式容器表达式 × Log/Metric/Event 触发表达式由 expr 引擎编译后在本地实例实时求值指标告警用窗口 80% 命中 逐容器冷却抑制误报与刷屏投递层内置模板、测试按钮与 SSRF 防护。所有配置持久化在/data/notifications.yml以及/data/cloud.yml挂载 Volume 后即可跨重启保留。若需要聚合、摘要与移动端推送可在此基础上接入 Dozzle Cloud。相关实现可继续在 internal/notification 目录求值与监听、internal/notification/dispatcherWebhook/Cloud 投递和 types/notification.go通知数据模型中深入阅读。【免费下载链接】dozzleRealtime log viewer for containers. Supports Docker, Swarm and K8s.项目地址: https://gitcode.com/GitHub_Trending/do/dozzle创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →