| Author | SHA1 | Message | Date |
|---|---|---|---|
|
|
b7cc7d6065 | go mod tidy | 3 years ago |
|
|
c77c9de5a7
|
Feishu support MsgCard (#1388)
* feishu support MsgCard Signed-off-by: zhihuanzhu <zhihuanzhu@deeproute.ai> * add Feishu_Card Support lark_md Signed-off-by: zhihuanzhu <jicki@qq.com> * add Feishu_Card Support lark_md Signed-off-by: zhihuanzhu <jicki@qq.com> * add Feishu_Card Support lark_md Signed-off-by: zhihuanzhu <jicki@qq.com> * add Feishu_Card Support lark_md Signed-off-by: zhihuanzhu <jicki@qq.com> * add Feishu_Card Support lark_md Signed-off-by: zhihuanzhu <jicki@qq.com> * delete at email Signed-off-by: zhihuanzhu <jicki@qq.com> * fix: template Signed-off-by: zhihuanzhu <jicki@qq.com> --------- Signed-off-by: zhihuanzhu <zhihuanzhu@deeproute.ai> Signed-off-by: zhihuanzhu <jicki@qq.com> |
3 years ago |
|
|
52e0ba2eae | Merge branch 'main' of github.com:ccfos/nightingale | 3 years ago |
|
|
9957c4e42a | refactor extract ident from TimeSeries | 3 years ago |
|
|
68ea466f59
|
build(deps): bump golang.org/x/net (#1397)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.0.0-20220722155237-a158d28d115b to 0.7.0. - [Release notes](https://github.com/golang/net/releases) - [Commits](https://github.com/golang/net/commits/v0.7.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
3 years ago |
|
|
41adc6f586
|
build(deps): bump golang.org/x/crypto (#1398)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.0.0-20210817164053-32db794688a5 to 0.1.0. - [Release notes](https://github.com/golang/crypto/releases) - [Commits](https://github.com/golang/crypto/commits/v0.1.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
3 years ago |
|
|
aa6daffe7b
|
build(deps): bump golang.org/x/text from 0.3.7 to 0.3.8 (#1393)
Bumps [golang.org/x/text](https://github.com/golang/text) from 0.3.7 to 0.3.8. - [Release notes](https://github.com/golang/text/releases) - [Commits](https://github.com/golang/text/compare/v0.3.7...v0.3.8) --- updated-dependencies: - dependency-name: golang.org/x/text dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
3 years ago |
|
|
f0c28bb271 | code refactor for extracting ident label | 3 years ago |
|
|
707a35bc06
|
Update metrics.yaml (#1389) | 3 years ago |
|
|
88f1645d3a
|
build(deps): bump github.com/gin-gonic/gin from 1.7.4 to 1.7.7 (#1374)
Bumps [github.com/gin-gonic/gin](https://github.com/gin-gonic/gin) from 1.7.4 to 1.7.7. - [Release notes](https://github.com/gin-gonic/gin/releases) - [Changelog](https://github.com/gin-gonic/gin/blob/master/CHANGELOG.md) - [Commits](https://github.com/gin-gonic/gin/compare/v1.7.4...v1.7.7) --- updated-dependencies: - dependency-name: github.com/gin-gonic/gin dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
3 years ago |
|
|
d8255d0cd3
|
docs: prometheus image version (#1381) | 3 years ago |
|
|
fcc26f6410 | update wechat name | 3 years ago |
|
|
6ff112f5da
|
update readme and screenshots (#1369) | 3 years ago |
| @@ -1,7 +1,6 @@ | |||||
| <p align="center"> | <p align="center"> | ||||
| <a href="https://github.com/ccfos/nightingale"> | <a href="https://github.com/ccfos/nightingale"> | ||||
| <img src="doc/img/ccf-n9e.png" alt="nightingale - cloud native monitoring" width="240" /></a> | |||||
| <p align="center">夜莺是一款开源的云原生监控系统,采用 all-in-one 的设计,提供企业级的功能特性,开箱即用的产品体验。推荐升级您的 Prometheus + AlertManager + Grafana 组合方案到夜莺</p> | |||||
| <img src="doc/img/nightingale_logo_h.png" alt="nightingale - cloud native monitoring" width="240" /></a> | |||||
| </p> | </p> | ||||
| <p align="center"> | <p align="center"> | ||||
| @@ -11,14 +10,23 @@ | |||||
| <a href="https://hub.docker.com/u/flashcatcloud"> | <a href="https://hub.docker.com/u/flashcatcloud"> | ||||
| <img alt="Docker pulls" src="https://img.shields.io/docker/pulls/flashcatcloud/nightingale"/></a> | <img alt="Docker pulls" src="https://img.shields.io/docker/pulls/flashcatcloud/nightingale"/></a> | ||||
| <img alt="GitHub Repo stars" src="https://img.shields.io/github/stars/ccfos/nightingale"> | <img alt="GitHub Repo stars" src="https://img.shields.io/github/stars/ccfos/nightingale"> | ||||
| <img alt="GitHub Repo issues" src="https://img.shields.io/github/issues/ccfos/nightingale"> | |||||
| <img alt="GitHub Repo issues closed" src="https://img.shields.io/github/issues-closed/ccfos/nightingale"> | |||||
| <img alt="GitHub forks" src="https://img.shields.io/github/forks/ccfos/nightingale"> | <img alt="GitHub forks" src="https://img.shields.io/github/forks/ccfos/nightingale"> | ||||
| <a href="https://github.com/ccfos/nightingale/graphs/contributors"> | <a href="https://github.com/ccfos/nightingale/graphs/contributors"> | ||||
| <img alt="GitHub contributors" src="https://img.shields.io/github/contributors-anon/ccfos/nightingale"/></a> | <img alt="GitHub contributors" src="https://img.shields.io/github/contributors-anon/ccfos/nightingale"/></a> | ||||
| <img alt="License" src="https://img.shields.io/badge/license-Apache--2.0-blue"/> | <img alt="License" src="https://img.shields.io/badge/license-Apache--2.0-blue"/> | ||||
| </p> | </p> | ||||
| <p align="center"> | |||||
| <b>All-in-one</b> 的开源云原生监控系统 <br/> | |||||
| <b>开箱即用</b>,集数据采集、可视化、监控告警于一体 <br/> | |||||
| 推荐升级您的 <b>Prometheus + AlertManager + Grafana</b> 组合方案到夜莺! | |||||
| </p> | |||||
| [English](./README_EN.md) | [中文](./README.md) | [English](./README_EN.md) | [中文](./README.md) | ||||
| ## Highlighted Features | ## Highlighted Features | ||||
| - **开箱即用** | - **开箱即用** | ||||
| @@ -26,59 +34,59 @@ | |||||
| - **专业告警** | - **专业告警** | ||||
| - 可视化的告警配置和管理,支持丰富的告警规则,提供屏蔽规则、订阅规则的配置能力,支持告警多种送达渠道,支持告警自愈、告警事件管理等; | - 可视化的告警配置和管理,支持丰富的告警规则,提供屏蔽规则、订阅规则的配置能力,支持告警多种送达渠道,支持告警自愈、告警事件管理等; | ||||
| - **云原生** | - **云原生** | ||||
| - 以交钥匙的方式快速构建企业级的云原生监控体系,支持 [**Categraf**](https://github.com/flashcatcloud/categraf)、Telegraf、Grafana-agent 等多种采集器,支持 Prometheus、VictoriaMetrics、M3DB、ElasticSearch 等多种数据库,兼容支持导入 Grafana 仪表盘,**与云原生生态无缝集成**; | |||||
| - **高性能,高可用** | |||||
| - 以交钥匙的方式快速构建企业级的云原生监控体系,支持 [Categraf](https://github.com/flashcatcloud/categraf)、Telegraf、Grafana-agent 等多种采集器,支持 Prometheus、VictoriaMetrics、M3DB、ElasticSearch 等多种数据库,兼容支持导入 Grafana 仪表盘,**与云原生生态无缝集成**; | |||||
| - **高性能 高可用** | |||||
| - 得益于夜莺的多数据源管理引擎,和夜莺引擎侧优秀的架构设计,借助于高性能时序库,可以满足数亿时间线的采集、存储、告警分析场景,节省大量成本; | - 得益于夜莺的多数据源管理引擎,和夜莺引擎侧优秀的架构设计,借助于高性能时序库,可以满足数亿时间线的采集、存储、告警分析场景,节省大量成本; | ||||
| - 夜莺监控组件均可水平扩展,无单点,已在上千家企业部署落地,经受了严苛的生产实践检验。众多互联网头部公司,夜莺集群机器达百台,处理数亿级时间线,重度使用夜莺监控; | - 夜莺监控组件均可水平扩展,无单点,已在上千家企业部署落地,经受了严苛的生产实践检验。众多互联网头部公司,夜莺集群机器达百台,处理数亿级时间线,重度使用夜莺监控; | ||||
| - **灵活扩展,中心化管理** | |||||
| - **灵活扩展 中心化管理** | |||||
| - 夜莺监控,可部署在 1 核 1G 的云主机,可在上百台机器集群化部署,可运行在 K8s 中;也可将时序库、告警引擎等组件下沉到各机房、各 Region,兼顾边缘部署和中心化统一管理,**解决数据割裂,缺乏统一视图的难题**; | - 夜莺监控,可部署在 1 核 1G 的云主机,可在上百台机器集群化部署,可运行在 K8s 中;也可将时序库、告警引擎等组件下沉到各机房、各 Region,兼顾边缘部署和中心化统一管理,**解决数据割裂,缺乏统一视图的难题**; | ||||
| - **开放社区** | - **开放社区** | ||||
| - 托管于[中国计算机学会开源发展委员会](https://www.ccf.org.cn/kyfzwyh/),有[**快猫星云**](https://flashcat.cloud)和众多公司的持续投入,和数千名社区用户的积极参与,以及夜莺监控项目清晰明确的定位,都保证了夜莺开源社区健康、长久的发展。活跃、专业的社区用户也在持续迭代和沉淀更多的最佳实践于产品中; | |||||
| - 托管于[中国计算机学会开源发展委员会](https://www.ccf.org.cn/kyfzwyh/),有[快猫星云](https://flashcat.cloud)和众多公司的持续投入,和数千名社区用户的积极参与,以及夜莺监控项目清晰明确的定位,都保证了夜莺开源社区健康、长久的发展。活跃、专业的社区用户也在持续迭代和沉淀更多的最佳实践于产品中; | |||||
| > 如果您在使用 Prometheus 过程中,有以下的一个或者多个需求场景,推荐您无缝升级到夜莺: | |||||
| **如果您在使用 Prometheus 过程中,有以下的一个或者多个需求场景,推荐您无缝升级到夜莺**: | |||||
| - Prometheus、Alertmanager、Grafana 等多个系统较为割裂,缺乏统一视图,无法开箱即用; | - Prometheus、Alertmanager、Grafana 等多个系统较为割裂,缺乏统一视图,无法开箱即用; | ||||
| - 通过修改配置文件来管理 Prometheus、Alertmanager 的方式,学习曲线大,协同有难度; | - 通过修改配置文件来管理 Prometheus、Alertmanager 的方式,学习曲线大,协同有难度; | ||||
| - 数据量过大而无法扩展您的 Prometheus 集群; | - 数据量过大而无法扩展您的 Prometheus 集群; | ||||
| - 生产环境运行多套 Prometheus 集群,面临管理和使用成本高的问题; | - 生产环境运行多套 Prometheus 集群,面临管理和使用成本高的问题; | ||||
| > 如果您在使用 Zabbix,有以下的场景,推荐您升级到夜莺: | |||||
| **如果您在使用 Zabbix,有以下的场景,推荐您升级到夜莺**: | |||||
| - 监控的数据量太大,希望有更好的扩展解决方案; | - 监控的数据量太大,希望有更好的扩展解决方案; | ||||
| - 学习曲线高,多人多团队模式下,希望有更好的协同使用效率; | - 学习曲线高,多人多团队模式下,希望有更好的协同使用效率; | ||||
| - 微服务和云原生架构下,监控数据的生命周期多变、监控数据维度基数高,Zabbix 数据模型不易适配; | - 微服务和云原生架构下,监控数据的生命周期多变、监控数据维度基数高,Zabbix 数据模型不易适配; | ||||
| > 如果您在使用 [Open-Falcon](https://github.com/open-falcon/falcon-plus),我们更推荐您升级到夜莺: | |||||
| > 了解更多Zabbix和夜莺监控的对比,推荐您进一步阅读[《Zabbix 和夜莺监控选型对比》](https://flashcat.cloud/blog/zabbx-vs-nightingale/) | |||||
| **如果您在使用 [Open-Falcon](https://github.com/open-falcon/falcon-plus),我们推荐您升级到夜莺:** | |||||
| - 关于 Open-Falcon 和夜莺的详细介绍,请参考阅读:[云原生监控的十个特点和趋势](https://mp.weixin.qq.com/s?__biz=MzkzNjI5OTM5Nw==&mid=2247483738&idx=1&sn=e8bdbb974a2cd003c1abcc2b5405dd18&chksm=c2a19fb0f5d616a63185cd79277a79a6b80118ef2185890d0683d2bb20451bd9303c78d083c5#rd)。 | |||||
| - 关于 Open-Falcon 和夜莺的详细介绍,请参考阅读:[《云原生监控的十个特点和趋势》](http://flashcat.cloud/blog/10-trends-of-cloudnative-monitoring/) | |||||
| > 我们推荐您使用 [Categraf](https://github.com/flashcatcloud/categraf) 作为首选的监控数据采集器: | |||||
| **我们推荐您使用 [Categraf](https://github.com/flashcatcloud/categraf) 作为首选的监控数据采集器**: | |||||
| - [Categraf](https://github.com/flashcatcloud/categraf) 是夜莺监控的默认采集器,采用开放插件机制和 all-in-one 的设计,同时支持 metric、log、trace、event 的采集。Categraf 不仅可以采集 CPU、内存、网络等系统层面的指标,也集成了众多开源组件的采集能力,支持K8s生态。Categraf 内置了对应的仪表盘和告警规则,开箱即用。 | |||||
| - [Categraf](https://github.com/flashcatcloud/categraf) 是夜莺监控的默认采集器,采用开放插件机制和 All-in-one 的设计理念,同时支持 metric、log、trace、event 的采集。Categraf 不仅可以采集 CPU、内存、网络等系统层面的指标,也集成了众多开源组件的采集能力,支持K8s生态。Categraf 内置了对应的仪表盘和告警规则,开箱即用。 | |||||
| ## Getting Started | ## Getting Started | ||||
| - [国外文档](https://n9e.github.io/) | |||||
| - [国内文档](http://n9e.flashcat.cloud/) | |||||
| [国外文档](https://n9e.github.io/) | [国内文档](http://n9e.flashcat.cloud/) | |||||
| ## Screenshots | ## Screenshots | ||||
| <img src="doc/img/intro.gif" width="480"> | |||||
| https://user-images.githubusercontent.com/792850/216888712-2565fcea-9df5-47bd-a49e-d60af9bd76e8.mp4 | |||||
| ## Architecture | ## Architecture | ||||
| <img src="doc/img/arch-product.png" width="480"> | |||||
| <img src="doc/img/arch-product.png" width="600"> | |||||
| 夜莺监控可以接收各种采集器上报的监控数据(比如 [Categraf](https://github.com/flashcatcloud/categraf)、telegraf、grafana-agent、Prometheus),并写入多种流行的时序数据库中(可以支持Prometheus、M3DB、VictoriaMetrics、Thanos、TDEngine等),提供告警规则、屏蔽规则、订阅规则的配置能力,提供监控数据的查看能力,提供告警自愈机制(告警触发之后自动回调某个webhook地址或者执行某个脚本),提供历史告警事件的存储管理、分组查看的能力。 | 夜莺监控可以接收各种采集器上报的监控数据(比如 [Categraf](https://github.com/flashcatcloud/categraf)、telegraf、grafana-agent、Prometheus),并写入多种流行的时序数据库中(可以支持Prometheus、M3DB、VictoriaMetrics、Thanos、TDEngine等),提供告警规则、屏蔽规则、订阅规则的配置能力,提供监控数据的查看能力,提供告警自愈机制(告警触发之后自动回调某个webhook地址或者执行某个脚本),提供历史告警事件的存储管理、分组查看的能力。 | ||||
| <img src="doc/img/arch-system.png" width="480"> | |||||
| <img src="doc/img/arch-system.png" width="600"> | |||||
| 夜莺 v5 版本的设计非常简单,核心是 server 和 webapi 两个模块,webapi 无状态,放到中心端,承接前端请求,将用户配置写入数据库;server 是告警引擎和数据转发模块,一般随着时序库走,一个时序库就对应一套 server,每套 server 可以只用一个实例,也可以多个实例组成集群,server 可以接收 Categraf、Telegraf、Grafana-Agent、Datadog-Agent、Falcon-Plugins 上报的数据,写入后端时序库,周期性从数据库同步告警规则,然后查询时序库做告警判断。每套 server 依赖一个 redis。 | 夜莺 v5 版本的设计非常简单,核心是 server 和 webapi 两个模块,webapi 无状态,放到中心端,承接前端请求,将用户配置写入数据库;server 是告警引擎和数据转发模块,一般随着时序库走,一个时序库就对应一套 server,每套 server 可以只用一个实例,也可以多个实例组成集群,server 可以接收 Categraf、Telegraf、Grafana-Agent、Datadog-Agent、Falcon-Plugins 上报的数据,写入后端时序库,周期性从数据库同步告警规则,然后查询时序库做告警判断。每套 server 依赖一个 redis。 | ||||
| <img src="doc/img/install-vm.png" width="480"> | |||||
| <img src="doc/img/install-vm.png" width="600"> | |||||
| 如果单机版本的时序数据库(比如 Prometheus) 性能有瓶颈或容灾较差,我们推荐使用 [VictoriaMetrics](https://github.com/VictoriaMetrics/VictoriaMetrics),VictoriaMetrics 架构较为简单,性能优异,易于部署和运维,架构图如上。VictoriaMetrics 更详尽的文档,还请参考其[官网](https://victoriametrics.com/)。 | 如果单机版本的时序数据库(比如 Prometheus) 性能有瓶颈或容灾较差,我们推荐使用 [VictoriaMetrics](https://github.com/VictoriaMetrics/VictoriaMetrics),VictoriaMetrics 架构较为简单,性能优异,易于部署和运维,架构图如上。VictoriaMetrics 更详尽的文档,还请参考其[官网](https://victoriametrics.com/)。 | ||||
| @@ -96,14 +104,14 @@ | |||||
| **尊重、认可和记录每一位贡献者的工作**是夜莺开源社区的第一指导原则,我们提倡**高效的提问**,这既是对开发者时间的尊重,也是对整个社区知识沉淀的贡献: | **尊重、认可和记录每一位贡献者的工作**是夜莺开源社区的第一指导原则,我们提倡**高效的提问**,这既是对开发者时间的尊重,也是对整个社区知识沉淀的贡献: | ||||
| - 提问之前请先查阅 [FAQ](https://www.gitlink.org.cn/ccfos/nightingale/wiki/faq) | - 提问之前请先查阅 [FAQ](https://www.gitlink.org.cn/ccfos/nightingale/wiki/faq) | ||||
| - 我们使用[GitHub Discussions](https://github.com/ccfos/nightingale/discussions)作为交流论坛,有问题可以到这里搜索、提问 | - 我们使用[GitHub Discussions](https://github.com/ccfos/nightingale/discussions)作为交流论坛,有问题可以到这里搜索、提问 | ||||
| - 我们也推荐你加入微信群,和其他夜莺用户交流经验 (请先加好友:[UlricGO](https://www.gitlink.org.cn/UlricQin/gist/tree/master/self.jpeg) 备注:夜莺加群+姓名+公司) | |||||
| - 我们也推荐你加入微信群,和其他夜莺用户交流经验 (请先加好友:[picobyte](https://www.gitlink.org.cn/UlricQin/gist/tree/master/self.jpeg) 备注:夜莺加群+姓名+公司) | |||||
| ## Who is using | |||||
| ## Who is using Nightingale | |||||
| 您可以通过在 **[Who is Using Nightingale](https://github.com/ccfos/nightingale/issues/897)** 登记您的使用情况,分享您的使用经验。 | 您可以通过在 **[Who is Using Nightingale](https://github.com/ccfos/nightingale/issues/897)** 登记您的使用情况,分享您的使用经验。 | ||||
| ## Stargazers | |||||
| ## Stargazers over time | |||||
| [](https://starchart.cc/ccfos/nightingale) | [](https://starchart.cc/ccfos/nightingale) | ||||
| ## Contributors | ## Contributors | ||||
| @@ -36,7 +36,7 @@ services: | |||||
| - nightingale | - nightingale | ||||
| prometheus: | prometheus: | ||||
| image: prom/prometheus | |||||
| image: prom/prometheus:v2.37.5 | |||||
| container_name: prometheus | container_name: prometheus | ||||
| hostname: prometheus | hostname: prometheus | ||||
| restart: always | restart: always | ||||
| @@ -53,7 +53,7 @@ services: | |||||
| - "--storage.tsdb.path=/prometheus" | - "--storage.tsdb.path=/prometheus" | ||||
| - "--web.console.libraries=/usr/share/prometheus/console_libraries" | - "--web.console.libraries=/usr/share/prometheus/console_libraries" | ||||
| - "--web.console.templates=/usr/share/prometheus/consoles" | - "--web.console.templates=/usr/share/prometheus/consoles" | ||||
| - "--enable-feature=remote-write-receiver" | |||||
| - "--web.enable-remote-write-receiver" | |||||
| - "--query.lookback-delta=2m" | - "--query.lookback-delta=2m" | ||||
| ibex: | ibex: | ||||
| @@ -78,7 +78,7 @@ Timeout=30000 | |||||
| TemplatesDir = "./etc/template" | TemplatesDir = "./etc/template" | ||||
| NotifyConcurrency = 10 | NotifyConcurrency = 10 | ||||
| # use builtin go code notify | # use builtin go code notify | ||||
| NotifyBuiltinChannels = ["email", "dingtalk", "wecom", "feishu", "mm", "telegram"] | |||||
| NotifyBuiltinChannels = ["email", "dingtalk", "wecom", "feishu", "feishucard","mm", "telegram"] | |||||
| [Alerting.CallScript] | [Alerting.CallScript] | ||||
| # built in sending capability in go code | # built in sending capability in go code | ||||
| @@ -0,0 +1,15 @@ | |||||
| {{ if .IsRecovered }} | |||||
| **告警集群:** {{.Cluster}} | |||||
| **级别状态:** S{{.Severity}} Recovered | |||||
| **告警名称:** {{.RuleName}} | |||||
| **恢复时间:** {{timeformat .LastEvalTime}} | |||||
| **告警描述:** **服务已恢复** | |||||
| {{- else }} | |||||
| **告警集群:** {{.Cluster}} | |||||
| **级别状态:** S{{.Severity}} Triggered | |||||
| **告警名称:** {{.RuleName}} | |||||
| **触发时间:** {{timeformat .TriggerTime}} | |||||
| **发送时间:** {{timestamp}} | |||||
| **触发时值:** {{.TriggerValue}} | |||||
| {{if .RuleNote }}**告警描述:** **{{.RuleNote}}**{{end}} | |||||
| {{- end -}} | |||||
| @@ -39,6 +39,11 @@ Label = "飞书机器人" | |||||
| # do not change Key | # do not change Key | ||||
| Key = "feishu" | Key = "feishu" | ||||
| [[NotifyChannels]] | |||||
| Label = "飞书机器人消息卡片" | |||||
| # do not change Key | |||||
| Key = "feishucard" | |||||
| [[NotifyChannels]] | [[NotifyChannels]] | ||||
| Label = "mm bot" | Label = "mm bot" | ||||
| # do not change Key | # do not change Key | ||||
| @@ -1,4 +1,6 @@ | |||||
| zh: | zh: | ||||
| ip_conntrack_count: 连接跟踪表条目总数(单位:int, count) | |||||
| ip_conntrack_max: 连接跟踪表最大容量(单位:int, size) | |||||
| cpu_usage_idle: CPU空闲率(单位:%) | cpu_usage_idle: CPU空闲率(单位:%) | ||||
| cpu_usage_active: CPU使用率(单位:%) | cpu_usage_active: CPU使用率(单位:%) | ||||
| cpu_usage_system: CPU内核态时间占比(单位:%) | cpu_usage_system: CPU内核态时间占比(单位:%) | ||||
| @@ -250,6 +252,8 @@ zh: | |||||
| cloudwatch_aws_rds_write_throughput_sum: rds 写入吞吐量总和 | cloudwatch_aws_rds_write_throughput_sum: rds 写入吞吐量总和 | ||||
| en: | en: | ||||
| ip_conntrack_count: the number of entries in the conntrack table(unit:int, count) | |||||
| ip_conntrack_max: the max capacity of the conntrack table(unit:int, size) | |||||
| cpu_usage_idle: "CPU idle rate(unit:%)" | cpu_usage_idle: "CPU idle rate(unit:%)" | ||||
| cpu_usage_active: "CPU usage rate(unit:%)" | cpu_usage_active: "CPU usage rate(unit:%)" | ||||
| cpu_usage_system: "CPU kernel state time proportion(unit:%)" | cpu_usage_system: "CPU kernel state time proportion(unit:%)" | ||||
| @@ -81,7 +81,7 @@ Timeout=30000 | |||||
| TemplatesDir = "./etc/template" | TemplatesDir = "./etc/template" | ||||
| NotifyConcurrency = 10 | NotifyConcurrency = 10 | ||||
| # use builtin go code notify | # use builtin go code notify | ||||
| NotifyBuiltinChannels = ["email", "dingtalk", "wecom", "feishu", "mm", "telegram"] | |||||
| NotifyBuiltinChannels = ["email", "dingtalk", "wecom", "feishu", "feishucard","mm", "telegram"] | |||||
| [Alerting.CallScript] | [Alerting.CallScript] | ||||
| # built in sending capability in go code | # built in sending capability in go code | ||||
| @@ -0,0 +1,15 @@ | |||||
| {{ if .IsRecovered }} | |||||
| **告警集群:** {{.Cluster}} | |||||
| **级别状态:** S{{.Severity}} Recovered | |||||
| **告警名称:** {{.RuleName}} | |||||
| **恢复时间:** {{timeformat .LastEvalTime}} | |||||
| **告警描述:** **服务已恢复** | |||||
| {{- else }} | |||||
| **告警集群:** {{.Cluster}} | |||||
| **级别状态:** S{{.Severity}} Triggered | |||||
| **告警名称:** {{.RuleName}} | |||||
| **触发时间:** {{timeformat .TriggerTime}} | |||||
| **发送时间:** {{timestamp}} | |||||
| **触发时值:** {{.TriggerValue}} | |||||
| {{if .RuleNote }}**告警描述:** **{{.RuleNote}}**{{end}} | |||||
| {{- end -}} | |||||
| @@ -39,6 +39,11 @@ Label = "飞书机器人" | |||||
| # do not change Key | # do not change Key | ||||
| Key = "feishu" | Key = "feishu" | ||||
| [[NotifyChannels]] | |||||
| Label = "飞书机器人消息卡片" | |||||
| # do not change Key | |||||
| Key = "feishucard" | |||||
| [[NotifyChannels]] | [[NotifyChannels]] | ||||
| Label = "mm bot" | Label = "mm bot" | ||||
| # do not change Key | # do not change Key | ||||
| @@ -6,7 +6,7 @@ require ( | |||||
| github.com/coreos/go-oidc v2.2.1+incompatible | github.com/coreos/go-oidc v2.2.1+incompatible | ||||
| github.com/dgrijalva/jwt-go v3.2.0+incompatible | github.com/dgrijalva/jwt-go v3.2.0+incompatible | ||||
| github.com/gin-contrib/pprof v1.3.0 | github.com/gin-contrib/pprof v1.3.0 | ||||
| github.com/gin-gonic/gin v1.7.4 | |||||
| github.com/gin-gonic/gin v1.7.7 | |||||
| github.com/go-ldap/ldap/v3 v3.4.1 | github.com/go-ldap/ldap/v3 v3.4.1 | ||||
| github.com/go-redis/redis/v9 v9.0.0-rc.1 | github.com/go-redis/redis/v9 v9.0.0-rc.1 | ||||
| github.com/gogo/protobuf v1.3.2 | github.com/gogo/protobuf v1.3.2 | ||||
| @@ -24,7 +24,7 @@ require ( | |||||
| github.com/prometheus/common v0.32.1 | github.com/prometheus/common v0.32.1 | ||||
| github.com/prometheus/prometheus v2.5.0+incompatible | github.com/prometheus/prometheus v2.5.0+incompatible | ||||
| github.com/tidwall/gjson v1.14.0 | github.com/tidwall/gjson v1.14.0 | ||||
| github.com/toolkits/pkg v1.3.1-0.20220824084030-9f9f830a05d5 | |||||
| github.com/toolkits/pkg v1.3.2 | |||||
| github.com/urfave/cli/v2 v2.3.0 | github.com/urfave/cli/v2 v2.3.0 | ||||
| golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c | golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c | ||||
| gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df | gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df | ||||
| @@ -74,10 +74,10 @@ require ( | |||||
| github.com/tidwall/pretty v1.2.0 // indirect | github.com/tidwall/pretty v1.2.0 // indirect | ||||
| github.com/ugorji/go/codec v1.1.7 // indirect | github.com/ugorji/go/codec v1.1.7 // indirect | ||||
| go.uber.org/automaxprocs v1.4.0 // indirect | go.uber.org/automaxprocs v1.4.0 // indirect | ||||
| golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect | |||||
| golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect | |||||
| golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect | |||||
| golang.org/x/text v0.3.7 // indirect | |||||
| golang.org/x/crypto v0.1.0 // indirect | |||||
| golang.org/x/net v0.7.0 // indirect | |||||
| golang.org/x/sys v0.5.0 // indirect | |||||
| golang.org/x/text v0.7.0 // indirect | |||||
| google.golang.org/appengine v1.6.6 // indirect | google.golang.org/appengine v1.6.6 // indirect | ||||
| google.golang.org/genproto v0.0.0-20211007155348-82e027067bd4 // indirect | google.golang.org/genproto v0.0.0-20211007155348-82e027067bd4 // indirect | ||||
| google.golang.org/grpc v1.41.0 // indirect | google.golang.org/grpc v1.41.0 // indirect | ||||
| @@ -97,8 +97,9 @@ github.com/gin-contrib/pprof v1.3.0/go.mod h1:waMjT1H9b179t3CxuG1cV3DHpga6ybizwf | |||||
| github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= | github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= | ||||
| github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= | github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= | ||||
| github.com/gin-gonic/gin v1.6.2/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= | github.com/gin-gonic/gin v1.6.2/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= | ||||
| github.com/gin-gonic/gin v1.7.4 h1:QmUZXrvJ9qZ3GfWvQ+2wnW/1ePrTEJqPKMYEU3lD/DM= | |||||
| github.com/gin-gonic/gin v1.7.4/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY= | github.com/gin-gonic/gin v1.7.4/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY= | ||||
| github.com/gin-gonic/gin v1.7.7 h1:3DoBmSbJbZAWqXJC3SLjAPfutPJJRN1U5pALB7EeTTs= | |||||
| github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U= | |||||
| github.com/go-asn1-ber/asn1-ber v1.5.1 h1:pDbRAunXzIUXfx4CB2QJFv5IuPiuoW+sWvr/Us009o8= | github.com/go-asn1-ber/asn1-ber v1.5.1 h1:pDbRAunXzIUXfx4CB2QJFv5IuPiuoW+sWvr/Us009o8= | ||||
| github.com/go-asn1-ber/asn1-ber v1.5.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= | github.com/go-asn1-ber/asn1-ber v1.5.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= | ||||
| github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= | github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= | ||||
| @@ -372,8 +373,8 @@ github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= | |||||
| github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= | github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= | ||||
| github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= | github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= | ||||
| github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= | github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= | ||||
| github.com/toolkits/pkg v1.3.1-0.20220824084030-9f9f830a05d5 h1:kMCwr2gNHjHEVgw+uNVdiPbGadj4TekbIfrTXElZeI0= | |||||
| github.com/toolkits/pkg v1.3.1-0.20220824084030-9f9f830a05d5/go.mod h1:PvTBg/UxazPgBz6VaCM7FM7kJldjfVrsuN6k4HT/VuY= | |||||
| github.com/toolkits/pkg v1.3.2 h1:elEW//SWOO956RQymAwcxBHGBKhrvCUAfXDo8wAkmJs= | |||||
| github.com/toolkits/pkg v1.3.2/go.mod h1:PvTBg/UxazPgBz6VaCM7FM7kJldjfVrsuN6k4HT/VuY= | |||||
| github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= | github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= | ||||
| github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= | github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= | ||||
| github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= | github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= | ||||
| @@ -415,8 +416,9 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh | |||||
| golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= | golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= | ||||
| golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= | golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= | ||||
| golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= | golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= | ||||
| golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ= | |||||
| golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= | golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= | ||||
| golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU= | |||||
| golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= | |||||
| golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= | ||||
| golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= | golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= | ||||
| golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= | golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= | ||||
| @@ -480,8 +482,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY | |||||
| golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= | ||||
| golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= | golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= | ||||
| golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= | golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= | ||||
| golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0= | |||||
| golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= | |||||
| golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= | |||||
| golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= | |||||
| golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= | ||||
| golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= | golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= | ||||
| golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= | golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= | ||||
| @@ -544,8 +546,8 @@ golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBc | |||||
| golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||
| golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||
| golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||
| golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s= | |||||
| golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | |||||
| golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= | |||||
| golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | |||||
| golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= | golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= | ||||
| golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= | ||||
| golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||||
| @@ -556,8 +558,9 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | |||||
| golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | ||||
| golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | ||||
| golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | ||||
| golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= | |||||
| golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= | ||||
| golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= | |||||
| golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= | |||||
| golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= | golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= | ||||
| golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= | golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= | ||||
| golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= | golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= | ||||
| @@ -19,12 +19,13 @@ import ( | |||||
| ) | ) | ||||
| const ( | const ( | ||||
| Dingtalk = "dingtalk" | |||||
| Wecom = "wecom" | |||||
| Feishu = "feishu" | |||||
| Mm = "mm" | |||||
| Telegram = "telegram" | |||||
| Email = "email" | |||||
| Dingtalk = "dingtalk" | |||||
| Wecom = "wecom" | |||||
| Feishu = "feishu" | |||||
| FeishuCard = "feishucard" | |||||
| Mm = "mm" | |||||
| Telegram = "telegram" | |||||
| Email = "email" | |||||
| DingtalkKey = "dingtalk_robot_token" | DingtalkKey = "dingtalk_robot_token" | ||||
| WecomKey = "wecom_robot_token" | WecomKey = "wecom_robot_token" | ||||
| @@ -581,6 +582,9 @@ func (u *User) ExtractToken(key string) (string, bool) { | |||||
| case Feishu: | case Feishu: | ||||
| ret := gjson.GetBytes(bs, FeishuKey) | ret := gjson.GetBytes(bs, FeishuKey) | ||||
| return ret.String(), ret.Exists() | return ret.String(), ret.Exists() | ||||
| case FeishuCard: | |||||
| ret := gjson.GetBytes(bs, FeishuKey) | |||||
| return ret.String(), ret.Exists() | |||||
| case Mm: | case Mm: | ||||
| ret := gjson.GetBytes(bs, MmKey) | ret := gjson.GetBytes(bs, MmKey) | ||||
| return ret.String(), ret.Exists() | return ret.String(), ret.Exists() | ||||
| @@ -609,6 +613,7 @@ func (u *User) ExtractAllToken() map[string]string { | |||||
| ret[Dingtalk] = gjson.GetBytes(bs, DingtalkKey).String() | ret[Dingtalk] = gjson.GetBytes(bs, DingtalkKey).String() | ||||
| ret[Wecom] = gjson.GetBytes(bs, WecomKey).String() | ret[Wecom] = gjson.GetBytes(bs, WecomKey).String() | ||||
| ret[Feishu] = gjson.GetBytes(bs, FeishuKey).String() | ret[Feishu] = gjson.GetBytes(bs, FeishuKey).String() | ||||
| ret[FeishuCard] = gjson.GetBytes(bs, FeishuKey).String() | |||||
| ret[Mm] = gjson.GetBytes(bs, MmKey).String() | ret[Mm] = gjson.GetBytes(bs, MmKey).String() | ||||
| ret[Telegram] = gjson.GetBytes(bs, TelegramKey).String() | ret[Telegram] = gjson.GetBytes(bs, TelegramKey).String() | ||||
| return ret | return ret | ||||
| @@ -0,0 +1,161 @@ | |||||
| package sender | |||||
| import ( | |||||
| "fmt" | |||||
| "html/template" | |||||
| "strings" | |||||
| "time" | |||||
| "github.com/toolkits/pkg/logger" | |||||
| "github.com/didi/nightingale/v5/src/models" | |||||
| "github.com/didi/nightingale/v5/src/pkg/poster" | |||||
| ) | |||||
| type feishuCardContent struct { | |||||
| Text string `json:"text"` | |||||
| } | |||||
| type Conf struct { | |||||
| WideScreenMode bool `json:"wide_screen_mode"` | |||||
| EnableForward bool `json:"enable_forward"` | |||||
| } | |||||
| type Te struct { | |||||
| Content string `json:"content"` | |||||
| Tag string `json:"tag"` | |||||
| } | |||||
| type Element struct { | |||||
| Tag string `json:"tag"` | |||||
| Text Te `json:"text"` | |||||
| Content string `json:"content"` | |||||
| Elements []Element `json:"elements"` | |||||
| } | |||||
| type Titles struct { | |||||
| Content string `json:"content"` | |||||
| Tag string `json:"tag"` | |||||
| } | |||||
| type Headers struct { | |||||
| Title Titles `json:"title"` | |||||
| Template string `json:"template"` | |||||
| } | |||||
| type Cards struct { | |||||
| Config Conf `json:"config"` | |||||
| Elements []Element `json:"elements"` | |||||
| Header Headers `json:"header"` | |||||
| } | |||||
| type feishuCard struct { | |||||
| Msgtype string `json:"msg_type"` | |||||
| Content feishuCardContent `json:"content"` | |||||
| Card Cards `json:"card"` | |||||
| } | |||||
| type FeishuCardSender struct { | |||||
| tpl *template.Template | |||||
| } | |||||
| func (fs *FeishuCardSender) Send(ctx MessageContext) { | |||||
| if len(ctx.Users) == 0 || ctx.Rule == nil || ctx.Event == nil { | |||||
| return | |||||
| } | |||||
| urls, _ := fs.extract(ctx.Users) | |||||
| message := BuildTplMessage(fs.tpl, ctx.Event) | |||||
| for _, url := range urls { | |||||
| var color string | |||||
| if strings.Count(message, "Recovered") > 0 && strings.Count(message, "Triggered") > 0 { | |||||
| color = "orange" | |||||
| } else if strings.Count(message, "Recovered") > 0 { | |||||
| color = "green" | |||||
| } else { | |||||
| color = "red" | |||||
| } | |||||
| SendTitle := fmt.Sprintf("🔔 [告警提醒] - %s", ctx.Rule.Name) | |||||
| body := feishuCard{ | |||||
| Msgtype: "interactive", | |||||
| Card: Cards{ | |||||
| Config: Conf{ | |||||
| WideScreenMode: true, | |||||
| EnableForward: true, | |||||
| }, | |||||
| Header: Headers{ | |||||
| Title: Titles{ | |||||
| Content: SendTitle, | |||||
| Tag: "plain_text", | |||||
| }, | |||||
| Template: color, | |||||
| }, | |||||
| Elements: []Element{ | |||||
| Element{ | |||||
| Tag: "div", | |||||
| Text: Te{ | |||||
| Content: message, | |||||
| Tag: "lark_md", | |||||
| }, | |||||
| }, | |||||
| { | |||||
| Tag: "hr", | |||||
| }, | |||||
| { | |||||
| Tag: "note", | |||||
| Elements: []Element{ | |||||
| { | |||||
| Content: SendTitle, | |||||
| Tag: "lark_md", | |||||
| }, | |||||
| }, | |||||
| }, | |||||
| }, | |||||
| }, | |||||
| } | |||||
| fs.doSend(url, body) | |||||
| } | |||||
| } | |||||
| func (fs *FeishuCardSender) SendRaw(users []*models.User, title, message string) { | |||||
| if len(users) == 0 { | |||||
| return | |||||
| } | |||||
| urls, _ := fs.extract(users) | |||||
| body := feishuCard{ | |||||
| Msgtype: "text", | |||||
| Content: feishuCardContent{ | |||||
| Text: message, | |||||
| }, | |||||
| } | |||||
| for _, url := range urls { | |||||
| fs.doSend(url, body) | |||||
| } | |||||
| } | |||||
| func (fs *FeishuCardSender) extract(users []*models.User) ([]string, []string) { | |||||
| urls := make([]string, 0, len(users)) | |||||
| ats := make([]string, 0, len(users)) | |||||
| for _, user := range users { | |||||
| if user.Phone != "" { | |||||
| ats = append(ats, user.Phone) | |||||
| } | |||||
| if token, has := user.ExtractToken(models.FeishuCard); has { | |||||
| url := token | |||||
| if !strings.HasPrefix(token, "https://") { | |||||
| url = "https://open.feishu.cn/open-apis/bot/v2/hook/" + token | |||||
| } | |||||
| urls = append(urls, url) | |||||
| } | |||||
| } | |||||
| return urls, ats | |||||
| } | |||||
| func (fs *FeishuCardSender) doSend(url string, body feishuCard) { | |||||
| res, code, err := poster.PostJSON(url, time.Second*5, body, 3) | |||||
| if err != nil { | |||||
| logger.Errorf("feishu_sender: result=fail url=%s code=%d error=%v response=%s", url, code, err, string(res)) | |||||
| } else { | |||||
| logger.Infof("feishu_sender: result=succ url=%s code=%d response=%s", url, code, string(res)) | |||||
| } | |||||
| } | |||||
| @@ -40,6 +40,8 @@ func NewSender(key string, tpls map[string]*template.Template) Sender { | |||||
| return &WecomSender{tpl: tpls["wecom.tpl"]} | return &WecomSender{tpl: tpls["wecom.tpl"]} | ||||
| case models.Feishu: | case models.Feishu: | ||||
| return &FeishuSender{tpl: tpls["feishu.tpl"]} | return &FeishuSender{tpl: tpls["feishu.tpl"]} | ||||
| case models.FeishuCard: | |||||
| return &FeishuCardSender{tpl: tpls["feishucard.tpl"]} | |||||
| case models.Email: | case models.Email: | ||||
| return &EmailSender{subjectTpl: tpls["subject.tpl"], contentTpl: tpls["mailbody.tpl"]} | return &EmailSender{subjectTpl: tpls["subject.tpl"], contentTpl: tpls["mailbody.tpl"]} | ||||
| case models.Mm: | case models.Mm: | ||||
| @@ -36,12 +36,13 @@ func reloadTpls() error { | |||||
| } | } | ||||
| senders := map[string]sender.Sender{ | senders := map[string]sender.Sender{ | ||||
| models.Email: sender.NewSender(models.Email, tmpTpls), | |||||
| models.Dingtalk: sender.NewSender(models.Dingtalk, tmpTpls), | |||||
| models.Wecom: sender.NewSender(models.Wecom, tmpTpls), | |||||
| models.Feishu: sender.NewSender(models.Feishu, tmpTpls), | |||||
| models.Mm: sender.NewSender(models.Mm, tmpTpls), | |||||
| models.Telegram: sender.NewSender(models.Telegram, tmpTpls), | |||||
| models.Email: sender.NewSender(models.Email, tmpTpls), | |||||
| models.Dingtalk: sender.NewSender(models.Dingtalk, tmpTpls), | |||||
| models.Wecom: sender.NewSender(models.Wecom, tmpTpls), | |||||
| models.Feishu: sender.NewSender(models.Feishu, tmpTpls), | |||||
| models.FeishuCard: sender.NewSender(models.FeishuCard, tmpTpls), | |||||
| models.Mm: sender.NewSender(models.Mm, tmpTpls), | |||||
| models.Telegram: sender.NewSender(models.Telegram, tmpTpls), | |||||
| } | } | ||||
| rwLock.Lock() | rwLock.Lock() | ||||
| @@ -74,6 +74,32 @@ func duplicateLabelKey(series *prompb.TimeSeries) bool { | |||||
| return false | return false | ||||
| } | } | ||||
| func extractIdentFromTimeSeries(s *prompb.TimeSeries) string { | |||||
| for i := 0; i < len(s.Labels); i++ { | |||||
| if s.Labels[i].Name == "ident" { | |||||
| return s.Labels[i].Value | |||||
| } | |||||
| } | |||||
| // agent_hostname for grafana-agent and categraf | |||||
| for i := 0; i < len(s.Labels); i++ { | |||||
| if s.Labels[i].Name == "agent_hostname" { | |||||
| s.Labels[i].Name = "ident" | |||||
| return s.Labels[i].Value | |||||
| } | |||||
| } | |||||
| // telegraf, output plugin: http, format: prometheusremotewrite | |||||
| for i := 0; i < len(s.Labels); i++ { | |||||
| if s.Labels[i].Name == "host" { | |||||
| s.Labels[i].Name = "ident" | |||||
| return s.Labels[i].Value | |||||
| } | |||||
| } | |||||
| return "" | |||||
| } | |||||
| func remoteWrite(c *gin.Context) { | func remoteWrite(c *gin.Context) { | ||||
| req, err := DecodeWriteRequest(c.Request.Body) | req, err := DecodeWriteRequest(c.Request.Body) | ||||
| if err != nil { | if err != nil { | ||||
| @@ -100,32 +126,14 @@ func remoteWrite(c *gin.Context) { | |||||
| continue | continue | ||||
| } | } | ||||
| ident = "" | |||||
| ident = extractIdentFromTimeSeries(req.Timeseries[i]) | |||||
| // find ident label | |||||
| for j := 0; j < len(req.Timeseries[i].Labels); j++ { | for j := 0; j < len(req.Timeseries[i].Labels); j++ { | ||||
| if req.Timeseries[i].Labels[j].Name == "ident" { | |||||
| ident = req.Timeseries[i].Labels[j].Value | |||||
| } else if req.Timeseries[i].Labels[j].Name == "host" { | |||||
| ident = req.Timeseries[i].Labels[j].Value | |||||
| } | |||||
| if req.Timeseries[i].Labels[j].Name == "__name__" { | if req.Timeseries[i].Labels[j].Name == "__name__" { | ||||
| metric = req.Timeseries[i].Labels[j].Value | metric = req.Timeseries[i].Labels[j].Value | ||||
| } | } | ||||
| } | } | ||||
| if ident == "" { | |||||
| // not found, try agent_hostname | |||||
| for j := 0; j < len(req.Timeseries[i].Labels); j++ { | |||||
| // agent_hostname for grafana-agent | |||||
| if req.Timeseries[i].Labels[j].Name == "agent_hostname" { | |||||
| req.Timeseries[i].Labels[j].Name = "ident" | |||||
| ident = req.Timeseries[i].Labels[j].Value | |||||
| } | |||||
| } | |||||
| } | |||||
| // 当数据是通过prometheus抓取(也许直接remote write到夜莺)的时候,prometheus会自动产生部分系统指标 | // 当数据是通过prometheus抓取(也许直接remote write到夜莺)的时候,prometheus会自动产生部分系统指标 | ||||
| // 例如最典型的有up指标,是prometheus为exporter生成的指标,即使exporter挂掉的时候也会送up=0的指标 | // 例如最典型的有up指标,是prometheus为exporter生成的指标,即使exporter挂掉的时候也会送up=0的指标 | ||||
| // 此类指标当剔除,否则会导致redis数据中时间戳被意外更新,导致由此类指标中携带的ident的相关target_up指标无法变为实际的0值 | // 此类指标当剔除,否则会导致redis数据中时间戳被意外更新,导致由此类指标中携带的ident的相关target_up指标无法变为实际的0值 | ||||