feat: add tpl & status api
This commit is contained in:
parent
39de0892f1
commit
258e9738f7
|
@ -30,6 +30,12 @@ type ConfigStruct struct {
|
||||||
Trans transSection `yaml:"trans"`
|
Trans transSection `yaml:"trans"`
|
||||||
ContactKeys []contactKey `yaml:"contactKeys"`
|
ContactKeys []contactKey `yaml:"contactKeys"`
|
||||||
NotifyChannels []string `yaml:"notifyChannels"`
|
NotifyChannels []string `yaml:"notifyChannels"`
|
||||||
|
Tpl tplSection `yaml:"tpl"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type tplSection struct {
|
||||||
|
AlertRulePath string `yaml:"alertRulePath"`
|
||||||
|
DashboardPath string `yaml:"dashboardPath"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type alertSection struct {
|
type alertSection struct {
|
||||||
|
@ -116,6 +122,8 @@ func Parse() error {
|
||||||
viper.SetDefault("trans.backend.prometheus.maxConcurrentQuery", 30)
|
viper.SetDefault("trans.backend.prometheus.maxConcurrentQuery", 30)
|
||||||
viper.SetDefault("trans.backend.prometheus.maxSamples", 50000000)
|
viper.SetDefault("trans.backend.prometheus.maxSamples", 50000000)
|
||||||
viper.SetDefault("trans.backend.prometheus.maxFetchAllSeriesLimitMinute", 5)
|
viper.SetDefault("trans.backend.prometheus.maxFetchAllSeriesLimitMinute", 5)
|
||||||
|
viper.SetDefault("tpl.alertRulePath", "./etc/alert_rule")
|
||||||
|
viper.SetDefault("tpl.dashboardPath", "./etc/dashboard")
|
||||||
|
|
||||||
err = viper.Unmarshal(&Config)
|
err = viper.Unmarshal(&Config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -0,0 +1,176 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "内存利用率大于75%",
|
||||||
|
"type": 0,
|
||||||
|
"expression": {
|
||||||
|
"trigger_conditions": [
|
||||||
|
{
|
||||||
|
"optr": ">",
|
||||||
|
"func": "all",
|
||||||
|
"metric": "system_mem_pct_used",
|
||||||
|
"params": [],
|
||||||
|
"threshold": 75
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tags_filters": []
|
||||||
|
},
|
||||||
|
"status": 0,
|
||||||
|
"enable_stime": "00:00",
|
||||||
|
"enable_etime": "23:59",
|
||||||
|
"enable_days_of_week": "1 2 3 4 5 6 7",
|
||||||
|
"recovery_notify": 0,
|
||||||
|
"priority": 2,
|
||||||
|
"notify_channels": "sms email",
|
||||||
|
"runbook_url": "",
|
||||||
|
"note": "",
|
||||||
|
"create_at": 1625831623,
|
||||||
|
"alert_duration": 60,
|
||||||
|
"notify_users_detail": null,
|
||||||
|
"notify_groups_detail": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "机器loadavg大于16",
|
||||||
|
"type": 0,
|
||||||
|
"expression": {
|
||||||
|
"trigger_conditions": [
|
||||||
|
{
|
||||||
|
"optr": ">",
|
||||||
|
"func": "all",
|
||||||
|
"metric": "node_load1",
|
||||||
|
"params": [],
|
||||||
|
"threshold": 16
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tags_filters": []
|
||||||
|
},
|
||||||
|
"status": 0,
|
||||||
|
"enable_stime": "00:00",
|
||||||
|
"enable_etime": "23:59",
|
||||||
|
"enable_days_of_week": "1 2 3 4 5 6 7",
|
||||||
|
"recovery_notify": 0,
|
||||||
|
"priority": 1,
|
||||||
|
"notify_channels": "sms email",
|
||||||
|
"runbook_url": "",
|
||||||
|
"note": "",
|
||||||
|
"create_at": 1625831689,
|
||||||
|
"alert_duration": 60,
|
||||||
|
"notify_users_detail": null,
|
||||||
|
"notify_groups_detail": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "磁盘利用率达到85%",
|
||||||
|
"type": 0,
|
||||||
|
"expression": {
|
||||||
|
"trigger_conditions": [
|
||||||
|
{
|
||||||
|
"optr": ">",
|
||||||
|
"func": "all",
|
||||||
|
"metric": "system_disk_in_use",
|
||||||
|
"params": [],
|
||||||
|
"threshold": 85
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tags_filters": []
|
||||||
|
},
|
||||||
|
"status": 0,
|
||||||
|
"enable_stime": "00:00",
|
||||||
|
"enable_etime": "23:59",
|
||||||
|
"enable_days_of_week": "1 2 3 4 5 6 7",
|
||||||
|
"recovery_notify": 0,
|
||||||
|
"priority": 3,
|
||||||
|
"notify_channels": "email",
|
||||||
|
"runbook_url": "",
|
||||||
|
"note": "",
|
||||||
|
"create_at": 1625831738,
|
||||||
|
"alert_duration": 60,
|
||||||
|
"notify_users_detail": null,
|
||||||
|
"notify_groups_detail": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "磁盘利用率达到88%",
|
||||||
|
"type": 0,
|
||||||
|
"expression": {
|
||||||
|
"trigger_conditions": [
|
||||||
|
{
|
||||||
|
"optr": ">",
|
||||||
|
"func": "all",
|
||||||
|
"metric": "system_disk_in_use",
|
||||||
|
"params": [],
|
||||||
|
"threshold": 88
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tags_filters": []
|
||||||
|
},
|
||||||
|
"status": 0,
|
||||||
|
"enable_stime": "00:00",
|
||||||
|
"enable_etime": "23:59",
|
||||||
|
"enable_days_of_week": "1 2 3 4 5 6 7",
|
||||||
|
"recovery_notify": 0,
|
||||||
|
"priority": 2,
|
||||||
|
"notify_channels": "email sms",
|
||||||
|
"runbook_url": "",
|
||||||
|
"note": "",
|
||||||
|
"create_at": 1625831774,
|
||||||
|
"alert_duration": 60,
|
||||||
|
"notify_users_detail": null,
|
||||||
|
"notify_groups_detail": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "磁盘利用率达到92%",
|
||||||
|
"type": 0,
|
||||||
|
"expression": {
|
||||||
|
"trigger_conditions": [
|
||||||
|
{
|
||||||
|
"optr": ">",
|
||||||
|
"func": "all",
|
||||||
|
"metric": "system_disk_in_use",
|
||||||
|
"params": [],
|
||||||
|
"threshold": 88
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tags_filters": []
|
||||||
|
},
|
||||||
|
"status": 0,
|
||||||
|
"enable_stime": "00:00",
|
||||||
|
"enable_etime": "23:59",
|
||||||
|
"enable_days_of_week": "1 2 3 4 5 6 7",
|
||||||
|
"recovery_notify": 0,
|
||||||
|
"priority": 1,
|
||||||
|
"notify_channels": "email sms voice",
|
||||||
|
"runbook_url": "",
|
||||||
|
"note": "",
|
||||||
|
"create_at": 1625831752,
|
||||||
|
"alert_duration": 60,
|
||||||
|
"notify_users_detail": null,
|
||||||
|
"notify_groups_detail": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "端口挂了",
|
||||||
|
"type": 0,
|
||||||
|
"expression": {
|
||||||
|
"trigger_conditions": [
|
||||||
|
{
|
||||||
|
"optr": "<",
|
||||||
|
"func": "all",
|
||||||
|
"metric": "proc_port_listen",
|
||||||
|
"params": [],
|
||||||
|
"threshold": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tags_filters": []
|
||||||
|
},
|
||||||
|
"status": 0,
|
||||||
|
"enable_stime": "00:00",
|
||||||
|
"enable_etime": "23:59",
|
||||||
|
"enable_days_of_week": "1 2 3 4 5 6 7",
|
||||||
|
"recovery_notify": 0,
|
||||||
|
"priority": 2,
|
||||||
|
"notify_channels": "sms email",
|
||||||
|
"runbook_url": "",
|
||||||
|
"note": "",
|
||||||
|
"create_at": 1625831564,
|
||||||
|
"alert_duration": 60,
|
||||||
|
"notify_users_detail": null,
|
||||||
|
"notify_groups_detail": null
|
||||||
|
}
|
||||||
|
]
|
|
@ -0,0 +1,42 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": 0,
|
||||||
|
"name": "日常巡检大盘",
|
||||||
|
"tags": "",
|
||||||
|
"configs": "",
|
||||||
|
"chart_groups": [
|
||||||
|
{
|
||||||
|
"id": 0,
|
||||||
|
"dashboard_id": 0,
|
||||||
|
"name": "Default chart group",
|
||||||
|
"weight": 0,
|
||||||
|
"charts": [
|
||||||
|
{
|
||||||
|
"id": 158,
|
||||||
|
"group_id": 60,
|
||||||
|
"configs": "{\"name\":\"CPU使用率\",\"mode\":\"nightingale\",\"metric\":[\"system_cpu_used\"],\"tags\":{},\"layout\":{\"h\":2,\"w\":2,\"x\":0,\"y\":0,\"i\":\"0\"}}",
|
||||||
|
"weight": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 159,
|
||||||
|
"group_id": 60,
|
||||||
|
"configs": "{\"name\":\"硬盘使用率\",\"mode\":\"nightingale\",\"metric\":[\"system_disk_in_use\"],\"tags\":{},\"layout\":{\"h\":2,\"w\":2,\"x\":6,\"y\":0,\"i\":\"1\"}}",
|
||||||
|
"weight": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 160,
|
||||||
|
"group_id": 60,
|
||||||
|
"configs": "{\"name\":\"内存使用率\",\"mode\":\"nightingale\",\"metric\":[\"system_mem_pct_used\"],\"tags\":{},\"layout\":{\"h\":2,\"w\":2,\"x\":2,\"y\":0,\"i\":\"2\"}}",
|
||||||
|
"weight": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 161,
|
||||||
|
"group_id": 60,
|
||||||
|
"configs": "{\"name\":\"IO使用率\",\"mode\":\"nightingale\",\"metric\":[\"system_io_util\"],\"tags\":{},\"layout\":{\"h\":2,\"w\":2,\"x\":4,\"y\":0,\"i\":\"3\"}}",
|
||||||
|
"weight": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
|
@ -158,11 +158,17 @@ func configRoutes(r *gin.Engine) {
|
||||||
pages.GET("/contact-channels", contactChannelsGet)
|
pages.GET("/contact-channels", contactChannelsGet)
|
||||||
pages.GET("/notify-channels", notifyChannelsGet)
|
pages.GET("/notify-channels", notifyChannelsGet)
|
||||||
|
|
||||||
|
pages.GET("/tpl/list", tplNameGets)
|
||||||
|
pages.GET("/tpl/content", tplGet)
|
||||||
|
|
||||||
|
pages.GET("/status", Status)
|
||||||
|
|
||||||
pages.POST("/query", GetData)
|
pages.POST("/query", GetData)
|
||||||
pages.POST("/tag-keys", GetTagKeys)
|
pages.POST("/tag-keys", GetTagKeys)
|
||||||
pages.POST("/tag-values", GetTagValues)
|
pages.POST("/tag-values", GetTagValues)
|
||||||
pages.POST("/tag-metrics", GetMetrics)
|
pages.POST("/tag-metrics", GetMetrics)
|
||||||
pages.POST("/tag-pairs", GetTagPairs)
|
pages.POST("/tag-pairs", GetTagPairs)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// for thirdparty, do not expose location in nginx.conf
|
// for thirdparty, do not expose location in nginx.conf
|
||||||
|
@ -279,6 +285,8 @@ func configRoutes(r *gin.Engine) {
|
||||||
|
|
||||||
v1.POST("/push", PushData)
|
v1.POST("/push", PushData)
|
||||||
|
|
||||||
|
v1.GET("/status", Status)
|
||||||
|
|
||||||
v1.POST("/query", GetData)
|
v1.POST("/query", GetData)
|
||||||
v1.GET("/check-promql", checkPromeQl)
|
v1.GET("/check-promql", checkPromeQl)
|
||||||
v1.POST("/tag-keys", GetTagKeys)
|
v1.POST("/tag-keys", GetTagKeys)
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
package http
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/didi/nightingale/v5/models"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Status(c *gin.Context) {
|
||||||
|
var err error
|
||||||
|
data := make(map[string]int64)
|
||||||
|
data["user_total"], err = models.UserTotal("")
|
||||||
|
dangerous(err)
|
||||||
|
|
||||||
|
data["user_group_total"], err = models.UserGroupTotal("")
|
||||||
|
dangerous(err)
|
||||||
|
|
||||||
|
data["resource_total"], err = models.ResourceTotal("")
|
||||||
|
dangerous(err)
|
||||||
|
|
||||||
|
data["alert_rule_total"], err = models.AlertRuleTotal("")
|
||||||
|
dangerous(err)
|
||||||
|
|
||||||
|
data["dashboard_total"], err = models.DashboardCount("")
|
||||||
|
dangerous(err)
|
||||||
|
|
||||||
|
now := time.Now().Unix()
|
||||||
|
stime := now - 24*3600
|
||||||
|
data["event_total_day"], err = models.AlertEventTotal(stime, now, "", -1, -1)
|
||||||
|
dangerous(err)
|
||||||
|
|
||||||
|
stime = now - 7*24*3600
|
||||||
|
data["event_total_week"], err = models.AlertEventTotal(stime, now, "", -1, -1)
|
||||||
|
dangerous(err)
|
||||||
|
|
||||||
|
stime = now - 30*24*3600
|
||||||
|
data["event_total_month"], err = models.AlertEventTotal(stime, now, "", -1, -1)
|
||||||
|
dangerous(err)
|
||||||
|
|
||||||
|
renderData(c, data, nil)
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
package http
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"path"
|
||||||
|
|
||||||
|
"github.com/didi/nightingale/v5/config"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/toolkits/pkg/file"
|
||||||
|
)
|
||||||
|
|
||||||
|
func tplNameGets(c *gin.Context) {
|
||||||
|
tplType := queryStr(c, "tpl_type")
|
||||||
|
|
||||||
|
var files []string
|
||||||
|
var err error
|
||||||
|
switch tplType {
|
||||||
|
case "alert_rule":
|
||||||
|
files, err = file.FilesUnder(config.Config.Tpl.AlertRulePath)
|
||||||
|
dangerous(err)
|
||||||
|
case "dashboard":
|
||||||
|
files, err = file.FilesUnder(config.Config.Tpl.DashboardPath)
|
||||||
|
dangerous(err)
|
||||||
|
default:
|
||||||
|
bomb(http.StatusBadRequest, "tpl type not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
renderData(c, files, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func tplGet(c *gin.Context) {
|
||||||
|
tplName := path.Base(queryStr(c, "tpl_name"))
|
||||||
|
tplType := queryStr(c, "tpl_type")
|
||||||
|
|
||||||
|
var filePath string
|
||||||
|
switch tplType {
|
||||||
|
case "alert_rule":
|
||||||
|
filePath = config.Config.Tpl.AlertRulePath + "/" + tplName
|
||||||
|
case "dashboard":
|
||||||
|
filePath = config.Config.Tpl.DashboardPath + "/" + tplName
|
||||||
|
default:
|
||||||
|
bomb(http.StatusBadRequest, "tpl type not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !file.IsExist(filePath) {
|
||||||
|
bomb(http.StatusBadRequest, "tpl not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
b, err := ioutil.ReadFile(filePath)
|
||||||
|
dangerous(err)
|
||||||
|
|
||||||
|
var content interface{}
|
||||||
|
err = json.Unmarshal(b, &content)
|
||||||
|
renderData(c, content, err)
|
||||||
|
}
|
|
@ -26,6 +26,10 @@ func (d *Dashboard) TableName() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Dashboard) Validate() error {
|
func (d *Dashboard) Validate() error {
|
||||||
|
if d.Name == "" {
|
||||||
|
return _e("Dashboard name is empty")
|
||||||
|
}
|
||||||
|
|
||||||
if str.Dangerous(d.Name) {
|
if str.Dangerous(d.Name) {
|
||||||
return _e("Dashboard name has invalid characters")
|
return _e("Dashboard name has invalid characters")
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue