parent
2ef9a77325
commit
4e6e70c14d
|
@ -23,4 +23,4 @@ jobs:
|
|||
uses: actions/checkout@v2
|
||||
|
||||
- name: Build
|
||||
run: ./control build
|
||||
run: ./build.sh
|
||||
|
|
|
@ -26,27 +26,24 @@ _test
|
|||
/log*
|
||||
/bin
|
||||
/out
|
||||
/meta
|
||||
/pub
|
||||
/build
|
||||
/dist
|
||||
/etc/*.local.yml
|
||||
/etc/plugins/*.local.yml
|
||||
/etc/log/log.test.json
|
||||
/data*
|
||||
/tarball
|
||||
/run
|
||||
/vendor
|
||||
/tmp
|
||||
/pub
|
||||
|
||||
.alerts
|
||||
.idea
|
||||
.index
|
||||
.vscode
|
||||
.DS_Store
|
||||
.cache-loader
|
||||
queries.active
|
||||
|
||||
/n9e-*
|
||||
|
||||
tmp/
|
||||
main
|
||||
Makefile
|
||||
src/modules/monapi/plugins/snmp/
|
||||
src/modules/monapi/plugins/oracle/
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
- 官网:[n9e.didiyun.com](https://n9e.didiyun.com/) 右上角切换版本,当下是v4,6月底7月初发布v5,没有上生产的用户建议等v5
|
||||
- 官网:[n9e.didiyun.com](https://n9e.didiyun.com/) 右上角切换版本
|
||||
- 招聘:前后端都要,base北京,薪资open,可将简历发至邮箱 `echo cWlueWVuaW5nQGRpZGlnbG9iYWwuY29t | base64 -d` 一起来做开源
|
||||
- 加群:加入网友互助交流群,和IT同仁一起交流运维监控,扫描如下二维码,加小助手微信,备注“夜莺加群”,小助手会拉你入群
|
||||
|
||||
<img src="https://s3-gz01.didistatic.com/n9e-pub/image/n9e-invite.png" width="250" alt="Nightingale"/>
|
||||
|
||||
<img src="https://s3-gz01.didistatic.com/n9e-pub/image/n9e-invite.png" width="250" alt="Nightingale"/>
|
|
@ -0,0 +1,7 @@
|
|||
package alert
|
||||
|
||||
import "context"
|
||||
|
||||
func Start(ctx context.Context) {
|
||||
go popEvent()
|
||||
}
|
|
@ -0,0 +1,293 @@
|
|||
package alert
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/didi/nightingale/v5/cache"
|
||||
"github.com/didi/nightingale/v5/config"
|
||||
"github.com/didi/nightingale/v5/judge"
|
||||
"github.com/didi/nightingale/v5/models"
|
||||
|
||||
"github.com/toolkits/pkg/concurrent/semaphore"
|
||||
"github.com/toolkits/pkg/logger"
|
||||
"github.com/toolkits/pkg/net/httplib"
|
||||
"github.com/toolkits/pkg/sys"
|
||||
)
|
||||
|
||||
func popEvent() {
|
||||
sema := semaphore.NewSemaphore(config.Config.Alert.NotifyConcurrency)
|
||||
duration := time.Duration(100) * time.Millisecond
|
||||
for {
|
||||
events := judge.EventQueue.PopBackBy(200)
|
||||
if len(events) < 1 {
|
||||
time.Sleep(duration)
|
||||
continue
|
||||
}
|
||||
consume(events, sema)
|
||||
}
|
||||
}
|
||||
|
||||
func consume(events []interface{}, sema *semaphore.Semaphore) {
|
||||
for i := range events {
|
||||
if events[i] == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
event := events[i].(*models.AlertEvent)
|
||||
|
||||
alertRule, exists := cache.AlertRules.Get(event.RuleId)
|
||||
if !exists {
|
||||
logger.Errorf("event_consume: alert rule not found, event:%+v", event)
|
||||
continue
|
||||
}
|
||||
logger.Debugf("[event_consume_success][type:%v][event:%+v]", event.IsPromePull, event)
|
||||
if isNoneffective(event, alertRule) {
|
||||
// 告警规则非生效时段
|
||||
continue
|
||||
}
|
||||
|
||||
event.RuleName = alertRule.Name
|
||||
event.RuleNote = alertRule.Note
|
||||
event.NotifyChannels = alertRule.NotifyChannels
|
||||
classpaths := cache.ResClasspath.GetValues(event.ResIdent)
|
||||
event.ResClasspaths = strings.Join(classpaths, " ")
|
||||
enrichTag(event, alertRule)
|
||||
|
||||
if isEventMute(event) {
|
||||
// 被屏蔽的事件
|
||||
event.MarkMuted()
|
||||
|
||||
if config.Config.Alert.MutedAlertPersist {
|
||||
err := event.Add()
|
||||
if err != nil {
|
||||
logger.Warningf("event_consume: insert muted event err:%v, event:%+v", err, event)
|
||||
}
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
// 操作数据库
|
||||
persist(event)
|
||||
|
||||
// 不管是告警还是恢复,都触发回调,接收端自己处理
|
||||
if alertRule.Callbacks != "" {
|
||||
go callback(event, alertRule)
|
||||
}
|
||||
|
||||
uids := genNotifyUserIDs(alertRule)
|
||||
if len(uids) == 0 {
|
||||
logger.Warningf("event_consume: notify users not found, event:%+v", event)
|
||||
continue
|
||||
}
|
||||
|
||||
users := cache.UserCache.GetByIds(uids)
|
||||
if len(users) == 0 {
|
||||
logger.Warningf("event_consume: notify users not found, event:%+v", event)
|
||||
continue
|
||||
}
|
||||
|
||||
alertMsg := AlertMsg{
|
||||
Event: event,
|
||||
Rule: alertRule,
|
||||
Users: users,
|
||||
}
|
||||
|
||||
logger.Infof("event_consume: notify alert:%+v", alertMsg)
|
||||
|
||||
sema.Acquire()
|
||||
go func(alertMsg AlertMsg) {
|
||||
defer sema.Release()
|
||||
notify(alertMsg)
|
||||
}(alertMsg)
|
||||
}
|
||||
}
|
||||
|
||||
func genNotifyUserIDs(alertRule *models.AlertRule) []int64 {
|
||||
uidMap := make(map[int64]struct{})
|
||||
|
||||
groupIds := strings.Fields(alertRule.NotifyGroups)
|
||||
for _, groupId := range groupIds {
|
||||
gid, err := strconv.ParseInt(groupId, 10, 64)
|
||||
if err != nil {
|
||||
logger.Warningf("event_consume: strconv groupid(%s) fail: %v", groupId, err)
|
||||
continue
|
||||
}
|
||||
|
||||
um, exists := cache.UserGroupMember.Get(gid)
|
||||
if !exists {
|
||||
continue
|
||||
}
|
||||
|
||||
for uid := range um {
|
||||
uidMap[uid] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
userIds := strings.Fields(alertRule.NotifyUsers)
|
||||
for _, userId := range userIds {
|
||||
uid, err := strconv.ParseInt(userId, 10, 64)
|
||||
if err != nil {
|
||||
logger.Warningf("event_consume: strconv userid(%s) fail: %v", userId, err)
|
||||
continue
|
||||
}
|
||||
|
||||
uidMap[uid] = struct{}{}
|
||||
}
|
||||
|
||||
uids := make([]int64, 0, len(uidMap))
|
||||
for uid := range uidMap {
|
||||
uids = append(uids, uid)
|
||||
}
|
||||
|
||||
return uids
|
||||
}
|
||||
|
||||
// 如果是告警,就存库,如果是恢复,就从未恢复的告警表里删除
|
||||
func persist(event *models.AlertEvent) {
|
||||
if event.IsRecov() {
|
||||
err := event.DelByHashId()
|
||||
if err != nil {
|
||||
logger.Warningf("event_consume: delete recovery event err:%v, event:%+v", err, event)
|
||||
}
|
||||
} else {
|
||||
err := event.Add()
|
||||
if err != nil {
|
||||
logger.Warningf("event_consume: insert alert event err:%v, event:%+v", err, event)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type AlertMsg struct {
|
||||
Event *models.AlertEvent `json:"event"`
|
||||
Rule *models.AlertRule `json:"rule"`
|
||||
Users []*models.User `json:"users"`
|
||||
}
|
||||
|
||||
func notify(alertMsg AlertMsg) {
|
||||
//增加并发控制
|
||||
bs, err := json.Marshal(alertMsg)
|
||||
if err != nil {
|
||||
logger.Errorf("notify: marshal alert %+v err:%v", alertMsg, err)
|
||||
}
|
||||
|
||||
fpath := config.Config.Alert.NotifyScriptPath
|
||||
cmd := exec.Command(fpath)
|
||||
cmd.Stdin = bytes.NewReader(bs)
|
||||
|
||||
// combine stdout and stderr
|
||||
var buf bytes.Buffer
|
||||
cmd.Stdout = &buf
|
||||
cmd.Stderr = &buf
|
||||
|
||||
err = cmd.Start()
|
||||
if err != nil {
|
||||
logger.Errorf("notify: run cmd err:%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
err, isTimeout := sys.WrapTimeout(cmd, time.Duration(10)*time.Second)
|
||||
|
||||
if isTimeout {
|
||||
if err == nil {
|
||||
logger.Errorf("notify: timeout and killed process %s", fpath)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
logger.Errorf("notify: kill process %s occur error %v", fpath, err)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
logger.Errorf("notify: exec script %s occur error: %v", fpath, err)
|
||||
return
|
||||
}
|
||||
|
||||
logger.Infof("notify: exec %s output: %s", fpath, buf.String())
|
||||
}
|
||||
|
||||
func callback(event *models.AlertEvent, alertRule *models.AlertRule) {
|
||||
urls := strings.Fields(alertRule.Callbacks)
|
||||
for _, url := range urls {
|
||||
if url == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
if !(strings.HasPrefix(url, "http://") || strings.HasPrefix(url, "https://")) {
|
||||
url = "http://" + url
|
||||
}
|
||||
|
||||
resp, code, err := httplib.PostJSON(url, 5*time.Second, event, map[string]string{})
|
||||
if err != nil {
|
||||
logger.Errorf("callback[%s] fail, callback content: %+v, resp: %s, err: %v, code:%d", url, event, string(resp), err, code)
|
||||
} else {
|
||||
logger.Infof("callback[%s] succ, callback content: %+v, resp: %s, code:%d", url, event, string(resp), code)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func isNoneffective(event *models.AlertEvent, alertRule *models.AlertRule) bool {
|
||||
// 生效时间过滤
|
||||
if alertRule.Status == models.ALERT_RULE_DISABLED {
|
||||
logger.Debugf("event:%+v alert rule:%+v disable", event, alertRule)
|
||||
return true
|
||||
}
|
||||
|
||||
tm := time.Unix(event.TriggerTime, 0)
|
||||
triggerTime := tm.Format("15:04")
|
||||
triggerWeek := strconv.Itoa(int(tm.Weekday()))
|
||||
|
||||
if alertRule.EnableStime <= alertRule.EnableEtime {
|
||||
if triggerTime < alertRule.EnableStime || triggerTime > alertRule.EnableEtime {
|
||||
logger.Debugf("event:%+v alert rule:%+v triggerTime Noneffective", event, alertRule)
|
||||
return true
|
||||
}
|
||||
} else {
|
||||
if triggerTime < alertRule.EnableStime && triggerTime > alertRule.EnableEtime {
|
||||
logger.Debugf("event:%+v alert rule:%+v triggerTime Noneffective", event, alertRule)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
if !strings.Contains(alertRule.EnableDaysOfWeek, triggerWeek) {
|
||||
logger.Debugf("event:%+v alert rule:%+v triggerWeek Noneffective", event, alertRule)
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// 事件的tags有多种tags组成:ident作为一个tag,数据本身的tags(前期已经把res的tags也附到数据tags里了)、规则的tags
|
||||
func enrichTag(event *models.AlertEvent, alertRule *models.AlertRule) {
|
||||
if event.ResIdent != "" {
|
||||
event.TagMap["ident"] = event.ResIdent
|
||||
}
|
||||
|
||||
if alertRule.AppendTags != "" {
|
||||
appendTags := strings.Fields(alertRule.AppendTags)
|
||||
for _, tag := range appendTags {
|
||||
arr := strings.Split(tag, "=")
|
||||
if len(arr) != 2 {
|
||||
logger.Warningf("alertRule AppendTags:%+v illagel", alertRule.AppendTags)
|
||||
continue
|
||||
}
|
||||
event.TagMap[arr[0]] = arr[1]
|
||||
}
|
||||
}
|
||||
|
||||
var tagList []string
|
||||
for key, value := range event.TagMap {
|
||||
tagList = append(tagList, fmt.Sprintf("%s=%s", key, value))
|
||||
}
|
||||
sort.Strings(tagList)
|
||||
event.Tags = strings.Join(tagList, " ")
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
package alert
|
||||
|
||||
import (
|
||||
"github.com/didi/nightingale/v5/cache"
|
||||
"github.com/didi/nightingale/v5/models"
|
||||
"github.com/toolkits/pkg/logger"
|
||||
)
|
||||
|
||||
func isEventMute(event *models.AlertEvent) bool {
|
||||
historyPoints, err := event.GetHistoryPoints()
|
||||
if err != nil {
|
||||
logger.Errorf("get event HistoryPoints:%+v failed, err: %v", event.HistoryPoints, err)
|
||||
return false
|
||||
}
|
||||
|
||||
// 先去匹配一下metric为空的mute
|
||||
if matchMute("", event.ResIdent, event.TagMap) {
|
||||
return true
|
||||
}
|
||||
|
||||
// 如果是与条件,就会有多个metric,任一个匹配了屏蔽规则都算被屏蔽
|
||||
for i := 0; i < len(historyPoints); i++ {
|
||||
if matchMute(historyPoints[i].Metric, event.ResIdent, event.TagMap) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
resAndTags, exists := cache.ResTags.Get(event.ResIdent)
|
||||
if exists {
|
||||
if event.TriggerTime > resAndTags.Resource.MuteBtime && event.TriggerTime < resAndTags.Resource.MuteEtime {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func matchMute(metric, ident string, tags map[string]string) bool {
|
||||
filters, exists := cache.AlertMute.GetByKey(metric)
|
||||
if !exists {
|
||||
// 没有屏蔽规则跟这个事件相关
|
||||
return false
|
||||
}
|
||||
|
||||
// 只要有一个屏蔽规则命中,那这个事件就是被屏蔽了
|
||||
for _, filter := range filters {
|
||||
if matchMuteOnce(filter, ident, tags) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func matchMuteOnce(filter cache.Filter, ident string, tags map[string]string) bool {
|
||||
if filter.ResReg != nil && !filter.ResReg.MatchString(ident) {
|
||||
// 比如屏蔽规则配置的是:c3-ceph.*
|
||||
// 当前事件的资源标识是:c4-ceph01.bj
|
||||
// 只要有任一点不满足,那这个屏蔽规则也没有继续验证下去的必要
|
||||
return false
|
||||
}
|
||||
|
||||
// 每个mute中的tags都得出现在event.tags,否则就是不匹配
|
||||
return mapContains(tags, filter.TagsMap)
|
||||
}
|
||||
|
||||
func mapContains(big, small map[string]string) bool {
|
||||
for tagk, tagv := range small {
|
||||
val, exists := big[tagk]
|
||||
if !exists {
|
||||
return false
|
||||
}
|
||||
|
||||
if val != tagv {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
package backend
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/prometheus/prometheus/promql"
|
||||
|
||||
"github.com/didi/nightingale/v5/vos"
|
||||
"github.com/toolkits/pkg/container/list"
|
||||
|
||||
pp "github.com/didi/nightingale/v5/backend/prome"
|
||||
)
|
||||
|
||||
type BackendSection struct {
|
||||
DataSource string `yaml:"datasource"`
|
||||
Prometheus pp.PromeSection `yaml:"prometheus"`
|
||||
}
|
||||
|
||||
type DataSource interface {
|
||||
PushEndpoint
|
||||
|
||||
QueryData(inputs vos.DataQueryParam) []*vos.DataQueryResp // 查询一段时间
|
||||
QueryTagKeys(recv vos.CommonTagQueryParam) *vos.TagKeyQueryResp // 获取标签的names
|
||||
QueryTagValues(recv vos.CommonTagQueryParam) *vos.TagValueQueryResp // 根据一个label_name获取 values
|
||||
QueryTagPairs(recv vos.CommonTagQueryParam) *vos.TagPairQueryResp // 根据匹配拿到所有 series 上面三个使用统一的结构体
|
||||
QueryMetrics(recv vos.MetricQueryParam) *vos.MetricQueryResp // 根据标签查 metric_names
|
||||
QueryVector(ql string) promql.Vector // prometheus pull alert 所用,其他数据源留空即可
|
||||
CleanUp() // 数据源退出时需要做的清理工作
|
||||
}
|
||||
|
||||
type PushEndpoint interface {
|
||||
Push2Queue(items []*vos.MetricPoint)
|
||||
}
|
||||
|
||||
var (
|
||||
defaultDataSource string
|
||||
registryDataSources = make(map[string]DataSource)
|
||||
registryPushEndpoints = make(map[string]PushEndpoint)
|
||||
)
|
||||
|
||||
func Init(cfg BackendSection) {
|
||||
defaultDataSource = cfg.DataSource
|
||||
|
||||
// init prometheus
|
||||
if cfg.Prometheus.Enable {
|
||||
promeDs := &pp.PromeDataSource{
|
||||
Section: cfg.Prometheus,
|
||||
PushQueue: list.NewSafeListLimited(10240000),
|
||||
}
|
||||
promeDs.Init()
|
||||
RegisterDataSource(cfg.Prometheus.Name, promeDs)
|
||||
}
|
||||
}
|
||||
|
||||
// get backend datasource
|
||||
// (pluginId == "" for default datasource)
|
||||
func GetDataSourceFor(pluginId string) (DataSource, error) {
|
||||
if pluginId == "" {
|
||||
pluginId = defaultDataSource
|
||||
}
|
||||
if source, exists := registryDataSources[pluginId]; exists {
|
||||
return source, nil
|
||||
}
|
||||
return nil, fmt.Errorf("could not find datasource for plugin: %s", pluginId)
|
||||
}
|
||||
|
||||
func DatasourceCleanUp() {
|
||||
for _, ds := range registryDataSources {
|
||||
ds.CleanUp()
|
||||
}
|
||||
}
|
||||
|
||||
// get all push endpoints
|
||||
func GetPushEndpoints() ([]PushEndpoint, error) {
|
||||
if len(registryPushEndpoints) > 0 {
|
||||
items := make([]PushEndpoint, 0, len(registryPushEndpoints))
|
||||
for _, value := range registryPushEndpoints {
|
||||
items = append(items, value)
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
return nil, fmt.Errorf("could not find any pushendpoint")
|
||||
}
|
||||
|
||||
func RegisterDataSource(pluginId string, datasource DataSource) {
|
||||
registryDataSources[pluginId] = datasource
|
||||
registryPushEndpoints[pluginId] = datasource
|
||||
}
|
|
@ -0,0 +1,162 @@
|
|||
package backend
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"time"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
"github.com/golang/snappy"
|
||||
"github.com/opentracing-contrib/go-stdlib/nethttp"
|
||||
"github.com/opentracing/opentracing-go"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prometheus/common/model"
|
||||
"github.com/prometheus/prometheus/pkg/labels"
|
||||
"github.com/prometheus/prometheus/prompb"
|
||||
|
||||
"github.com/didi/nightingale/v5/vos"
|
||||
)
|
||||
|
||||
var MetricNameRE = regexp.MustCompile(`^[a-zA-Z_:][a-zA-Z0-9_:]*$`)
|
||||
|
||||
type sample struct {
|
||||
labels labels.Labels
|
||||
t int64
|
||||
v float64
|
||||
}
|
||||
|
||||
func labelsToLabelsProto(labels labels.Labels, buf []prompb.Label) []prompb.Label {
|
||||
result := buf[:0]
|
||||
if cap(buf) < len(labels) {
|
||||
result = make([]prompb.Label, 0, len(labels))
|
||||
}
|
||||
for _, l := range labels {
|
||||
result = append(result, prompb.Label{
|
||||
Name: l.Name,
|
||||
Value: l.Value,
|
||||
})
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (pd *PromeDataSource) convertOne(item *vos.MetricPoint) (prompb.TimeSeries, error) {
|
||||
pt := prompb.TimeSeries{}
|
||||
pt.Samples = []prompb.Sample{{}}
|
||||
s := sample{}
|
||||
s.t = item.Time
|
||||
s.v = item.Value
|
||||
// name
|
||||
if !MetricNameRE.MatchString(item.Metric) {
|
||||
return pt, errors.New("invalid metrics name")
|
||||
}
|
||||
nameLs := labels.Label{
|
||||
Name: LABEL_NAME,
|
||||
Value: item.Metric,
|
||||
}
|
||||
s.labels = append(s.labels, nameLs)
|
||||
if item.Ident != "" {
|
||||
identLs := labels.Label{
|
||||
Name: LABEL_IDENT,
|
||||
Value: item.Ident,
|
||||
}
|
||||
s.labels = append(s.labels, identLs)
|
||||
}
|
||||
|
||||
for k, v := range item.TagsMap {
|
||||
if model.LabelNameRE.MatchString(k) {
|
||||
ls := labels.Label{
|
||||
Name: k,
|
||||
Value: v,
|
||||
}
|
||||
s.labels = append(s.labels, ls)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pt.Labels = labelsToLabelsProto(s.labels, pt.Labels)
|
||||
// 时间赋值问题,使用毫秒时间戳
|
||||
tsMs := time.Unix(s.t, 0).UnixNano() / 1e6
|
||||
pt.Samples[0].Timestamp = tsMs
|
||||
pt.Samples[0].Value = s.v
|
||||
return pt, nil
|
||||
}
|
||||
|
||||
type RecoverableError struct {
|
||||
error
|
||||
}
|
||||
|
||||
func remoteWritePost(c *HttpClient, req []byte) error {
|
||||
httpReq, err := http.NewRequest("POST", c.url.String(), bytes.NewReader(req))
|
||||
if err != nil {
|
||||
// Errors from NewRequest are from unparsable URLs, so are not
|
||||
// recoverable.
|
||||
return err
|
||||
}
|
||||
|
||||
httpReq.Header.Add("Content-Encoding", "snappy")
|
||||
httpReq.Header.Set("Content-Type", "application/x-protobuf")
|
||||
httpReq.Header.Set("User-Agent", "n9e-v5")
|
||||
httpReq.Header.Set("X-Prometheus-Remote-Write-Version", "0.1.0")
|
||||
ctx, cancel := context.WithTimeout(context.Background(), c.timeout)
|
||||
defer cancel()
|
||||
|
||||
httpReq = httpReq.WithContext(ctx)
|
||||
|
||||
if parentSpan := opentracing.SpanFromContext(ctx); parentSpan != nil {
|
||||
var ht *nethttp.Tracer
|
||||
httpReq, ht = nethttp.TraceRequest(
|
||||
parentSpan.Tracer(),
|
||||
httpReq,
|
||||
nethttp.OperationName("Remote Store"),
|
||||
nethttp.ClientTrace(false),
|
||||
)
|
||||
defer ht.Finish()
|
||||
}
|
||||
|
||||
httpResp, err := c.Client.Do(httpReq)
|
||||
if err != nil {
|
||||
// Errors from Client.Do are from (for example) network errors, so are
|
||||
// recoverable.
|
||||
return RecoverableError{err}
|
||||
}
|
||||
defer func() {
|
||||
io.Copy(ioutil.Discard, httpResp.Body)
|
||||
httpResp.Body.Close()
|
||||
}()
|
||||
|
||||
if httpResp.StatusCode/100 != 2 {
|
||||
scanner := bufio.NewScanner(io.LimitReader(httpResp.Body, 512))
|
||||
line := ""
|
||||
if scanner.Scan() {
|
||||
line = scanner.Text()
|
||||
}
|
||||
err = errors.Errorf("server returned HTTP status %s: %s", httpResp.Status, line)
|
||||
}
|
||||
if httpResp.StatusCode/100 == 5 {
|
||||
return RecoverableError{err}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (pd *PromeDataSource) buildWriteRequest(samples []prompb.TimeSeries) ([]byte, error) {
|
||||
|
||||
req := &prompb.WriteRequest{
|
||||
Timeseries: samples,
|
||||
Metadata: nil,
|
||||
}
|
||||
|
||||
data, err := proto.Marshal(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
compressed := snappy.Encode(nil, data)
|
||||
return compressed, nil
|
||||
}
|
|
@ -0,0 +1,253 @@
|
|||
package backend
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/go-kit/kit/log"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
config_util "github.com/prometheus/common/config"
|
||||
"github.com/prometheus/common/model"
|
||||
"github.com/prometheus/common/promlog"
|
||||
pc "github.com/prometheus/prometheus/config"
|
||||
"github.com/prometheus/prometheus/prompb"
|
||||
"github.com/prometheus/prometheus/promql"
|
||||
"github.com/prometheus/prometheus/storage"
|
||||
"github.com/prometheus/prometheus/storage/remote"
|
||||
"github.com/toolkits/pkg/container/list"
|
||||
"github.com/toolkits/pkg/logger"
|
||||
"go.uber.org/atomic"
|
||||
|
||||
"github.com/didi/nightingale/v5/vos"
|
||||
)
|
||||
|
||||
const (
|
||||
DefaultPopNum = 1000
|
||||
)
|
||||
|
||||
type PromeSection struct {
|
||||
Enable bool `yaml:"enable"`
|
||||
Name string `yaml:"name"`
|
||||
Batch int `yaml:"batch"`
|
||||
MaxRetry int `yaml:"maxRetry"`
|
||||
LookbackDeltaMinute int `yaml:"lookbackDeltaMinute"`
|
||||
MaxConcurrentQuery int `yaml:"maxConcurrentQuery"`
|
||||
MaxSamples int `yaml:"maxSamples"`
|
||||
MaxFetchAllSeriesLimitMinute int64 `yaml:"maxFetchAllSeriesLimitMinute"`
|
||||
RemoteWrite []RemoteConfig `yaml:"remoteWrite"`
|
||||
RemoteRead []RemoteConfig `yaml:"remoteRead"`
|
||||
}
|
||||
|
||||
type RemoteConfig struct {
|
||||
Name string `yaml:"name"`
|
||||
Url string `yaml:"url"`
|
||||
RemoteTimeoutSecond int `yaml:"remoteTimeoutSecond"`
|
||||
}
|
||||
|
||||
type PromeDataSource struct {
|
||||
Section PromeSection
|
||||
LocalTmpDir string
|
||||
// 除了promql的查询,需要后端存储
|
||||
Queryable storage.SampleAndChunkQueryable
|
||||
// promql相关查询
|
||||
QueryEngine *promql.Engine
|
||||
PushQueue *list.SafeListLimited
|
||||
WriteTargets []*HttpClient
|
||||
}
|
||||
type safePromQLNoStepSubqueryInterval struct {
|
||||
value atomic.Int64
|
||||
}
|
||||
|
||||
type HttpClient struct {
|
||||
remoteName string // Used to differentiate clients in metrics.
|
||||
url *url.URL
|
||||
Client *http.Client
|
||||
timeout time.Duration
|
||||
}
|
||||
|
||||
func durationToInt64Millis(d time.Duration) int64 {
|
||||
return int64(d / time.Millisecond)
|
||||
}
|
||||
func (i *safePromQLNoStepSubqueryInterval) Set(ev model.Duration) {
|
||||
i.value.Store(durationToInt64Millis(time.Duration(ev)))
|
||||
}
|
||||
func (i *safePromQLNoStepSubqueryInterval) Get(int64) int64 {
|
||||
return i.value.Load()
|
||||
}
|
||||
func (pd *PromeDataSource) CleanUp() {
|
||||
err := os.RemoveAll(pd.LocalTmpDir)
|
||||
logger.Infof("[remove_prome_tmp_dir_err][dir:%+v][err: %v]", pd.LocalTmpDir, err)
|
||||
|
||||
}
|
||||
func (pd *PromeDataSource) Init() {
|
||||
// 模拟创建本地存储目录
|
||||
dbDir, err := ioutil.TempDir("", "tsdb-api-ready")
|
||||
if err != nil {
|
||||
logger.Errorf("[error_create_local_tsdb_dir][err: %v]", err)
|
||||
return
|
||||
}
|
||||
pd.LocalTmpDir = dbDir
|
||||
|
||||
promlogConfig := promlog.Config{}
|
||||
// 使用本地目录创建remote-storage
|
||||
remoteS := remote.NewStorage(promlog.New(&promlogConfig), prometheus.DefaultRegisterer, func() (int64, error) {
|
||||
return 0, nil
|
||||
}, dbDir, 1*time.Minute, nil)
|
||||
|
||||
// ApplyConfig 加载queryables
|
||||
remoteReadC := make([]*pc.RemoteReadConfig, 0)
|
||||
for _, u := range pd.Section.RemoteRead {
|
||||
|
||||
ur, err := url.Parse(u.Url)
|
||||
if err != nil {
|
||||
logger.Errorf("[prome_ds_init_error][parse_url_error][url:%+v][err:%+v]", u.Url, err)
|
||||
continue
|
||||
}
|
||||
|
||||
remoteReadC = append(remoteReadC,
|
||||
&pc.RemoteReadConfig{
|
||||
URL: &config_util.URL{URL: ur},
|
||||
RemoteTimeout: model.Duration(time.Duration(u.RemoteTimeoutSecond) * time.Second),
|
||||
ReadRecent: true,
|
||||
},
|
||||
)
|
||||
}
|
||||
if len(remoteReadC) == 0 {
|
||||
logger.Errorf("[prome_ds_error_got_zero_remote_read_storage]")
|
||||
return
|
||||
}
|
||||
err = remoteS.ApplyConfig(&pc.Config{RemoteReadConfigs: remoteReadC})
|
||||
if err != nil {
|
||||
logger.Errorf("[error_load_remote_read_config][err: %v]", err)
|
||||
return
|
||||
}
|
||||
pLogger := log.NewNopLogger()
|
||||
|
||||
noStepSubqueryInterval := &safePromQLNoStepSubqueryInterval{}
|
||||
|
||||
queryQueueDir, err := ioutil.TempDir(dbDir, "prom_query_concurrency")
|
||||
opts := promql.EngineOpts{
|
||||
Logger: log.With(pLogger, "component", "query engine"),
|
||||
Reg: prometheus.DefaultRegisterer,
|
||||
MaxSamples: pd.Section.MaxSamples,
|
||||
Timeout: 30 * time.Second,
|
||||
ActiveQueryTracker: promql.NewActiveQueryTracker(queryQueueDir, pd.Section.MaxConcurrentQuery, log.With(pLogger, "component", "activeQueryTracker")),
|
||||
LookbackDelta: time.Duration(pd.Section.LookbackDeltaMinute) * time.Minute,
|
||||
NoStepSubqueryIntervalFn: noStepSubqueryInterval.Get,
|
||||
EnableAtModifier: true,
|
||||
}
|
||||
|
||||
queryEngine := promql.NewEngine(opts)
|
||||
pd.QueryEngine = queryEngine
|
||||
pd.Queryable = remoteS
|
||||
|
||||
// 初始化writeClients
|
||||
if len(pd.Section.RemoteWrite) == 0 {
|
||||
logger.Warningf("[prome_ds_init_with_zero_RemoteWrite_target]")
|
||||
logger.Infof("[successfully_init_prometheus_datasource][remote_read_num:%+v][remote_write_num:%+v]",
|
||||
len(pd.Section.RemoteRead),
|
||||
len(pd.Section.RemoteWrite),
|
||||
)
|
||||
return
|
||||
}
|
||||
writeTs := make([]*HttpClient, 0)
|
||||
for _, u := range pd.Section.RemoteWrite {
|
||||
ur, err := url.Parse(u.Url)
|
||||
if err != nil {
|
||||
logger.Errorf("[prome_ds_init_error][parse_url_error][url:%+v][err:%+v]", u.Url, err)
|
||||
continue
|
||||
}
|
||||
writeTs = append(writeTs,
|
||||
&HttpClient{
|
||||
remoteName: u.Name,
|
||||
url: ur,
|
||||
Client: &http.Client{},
|
||||
timeout: time.Duration(u.RemoteTimeoutSecond) * time.Second,
|
||||
})
|
||||
}
|
||||
pd.WriteTargets = writeTs
|
||||
// 开启prometheus 队列消费协程
|
||||
go pd.remoteWrite()
|
||||
logger.Infof("[successfully_init_prometheus_datasource][remote_read_num:%+v][remote_write_num:%+v]",
|
||||
len(remoteReadC),
|
||||
len(writeTs),
|
||||
)
|
||||
}
|
||||
|
||||
func (pd *PromeDataSource) Push2Queue(points []*vos.MetricPoint) {
|
||||
for _, point := range points {
|
||||
pt, err := pd.convertOne(point)
|
||||
if err != nil {
|
||||
logger.Errorf("[prome_convertOne_error][point: %+v][err:%s]", point, err)
|
||||
continue
|
||||
}
|
||||
ok := pd.PushQueue.PushFront(pt)
|
||||
if !ok {
|
||||
logger.Errorf("[prome_push_queue_error][point: %+v] ", point)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (pd *PromeDataSource) remoteWrite() {
|
||||
batch := pd.Section.Batch // 一次发送,最多batch条数据
|
||||
if batch <= 0 {
|
||||
batch = DefaultPopNum
|
||||
}
|
||||
for {
|
||||
items := pd.PushQueue.PopBackBy(batch)
|
||||
count := len(items)
|
||||
if count == 0 {
|
||||
time.Sleep(time.Millisecond * 100)
|
||||
continue
|
||||
}
|
||||
|
||||
pbItems := make([]prompb.TimeSeries, count)
|
||||
for i := 0; i < count; i++ {
|
||||
pbItems[i] = items[i].(prompb.TimeSeries)
|
||||
}
|
||||
payload, err := pd.buildWriteRequest(pbItems)
|
||||
if err != nil {
|
||||
logger.Errorf("[prome_remote_write_error][pb_marshal_error][items: %+v][pb.err: %v]: ", items, err)
|
||||
continue
|
||||
}
|
||||
pd.processWrite(payload)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func (pd *PromeDataSource) processWrite(payload []byte) {
|
||||
|
||||
retry := pd.Section.MaxRetry
|
||||
|
||||
for _, c := range pd.WriteTargets {
|
||||
newC := c
|
||||
go func(cc *HttpClient, payload []byte) {
|
||||
|
||||
sendOk := false
|
||||
var err error
|
||||
for i := 0; i < retry; i++ {
|
||||
err := remoteWritePost(cc, payload)
|
||||
if err == nil {
|
||||
sendOk = true
|
||||
break
|
||||
}
|
||||
err, ok := err.(RecoverableError)
|
||||
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
logger.Warningf("send prome fail: %v", err)
|
||||
time.Sleep(time.Millisecond * 100)
|
||||
}
|
||||
if !sendOk {
|
||||
logger.Warningf("send prome finally fail: %v", err)
|
||||
} else {
|
||||
logger.Infof("send to prome %s ok", cc.url.String())
|
||||
}
|
||||
}(newC, payload)
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,642 @@
|
|||
package backend
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/prometheus/prometheus/pkg/labels"
|
||||
"github.com/prometheus/prometheus/promql"
|
||||
"github.com/prometheus/prometheus/promql/parser"
|
||||
"github.com/prometheus/prometheus/storage"
|
||||
"github.com/toolkits/pkg/logger"
|
||||
|
||||
"github.com/didi/nightingale/v5/cache"
|
||||
"github.com/didi/nightingale/v5/models"
|
||||
"github.com/didi/nightingale/v5/vos"
|
||||
)
|
||||
|
||||
const (
|
||||
LABEL_IDENT = "ident"
|
||||
LABEL_NAME = "__name__"
|
||||
DEFAULT_QL = `{__name__=~".*a.*|.*e.*"}`
|
||||
DEFAULT_STEP = 14
|
||||
)
|
||||
|
||||
type commonQueryObj struct {
|
||||
Idents []string
|
||||
TagPairs []*vos.TagPair
|
||||
Metric string
|
||||
Start int64
|
||||
End int64
|
||||
MetricNameExact bool // metric_name精确匹配,在查询看图的时候为true
|
||||
From string // 调用的来源
|
||||
}
|
||||
|
||||
// 为查询索引或标签相关的转换,大部分都是正则匹配
|
||||
func convertToPromql(recv *commonQueryObj) string {
|
||||
|
||||
qlStr := ""
|
||||
qlStrFinal := ""
|
||||
metricName := ""
|
||||
labelIdent := ""
|
||||
labelStrSlice := make([]string, 0)
|
||||
// 匹配metric_name __name__=~"xx.*"
|
||||
if recv.Metric != "" {
|
||||
if recv.MetricNameExact {
|
||||
metricName = fmt.Sprintf(`__name__="%s"`, recv.Metric)
|
||||
} else {
|
||||
metricName = fmt.Sprintf(`__name__=~".*%s.*"`, recv.Metric)
|
||||
}
|
||||
|
||||
labelStrSlice = append(labelStrSlice, metricName)
|
||||
|
||||
}
|
||||
// 匹配ident=~"k1.*|k2.*"
|
||||
for _, i := range recv.Idents {
|
||||
if i != "" {
|
||||
labelIdent += fmt.Sprintf(`.*%s.*|`, i)
|
||||
}
|
||||
}
|
||||
labelIdent = strings.TrimRight(labelIdent, "|")
|
||||
if labelIdent != "" {
|
||||
labelStrSlice = append(labelStrSlice, fmt.Sprintf(`ident=~"%s"`, labelIdent))
|
||||
}
|
||||
// 匹配标签
|
||||
labelM := make(map[string]string)
|
||||
for _, i := range recv.TagPairs {
|
||||
if i.Key == "" {
|
||||
continue
|
||||
}
|
||||
lastStr, _ := labelM[i.Key]
|
||||
|
||||
lastStr += fmt.Sprintf(`.*%s.*|`, i.Value)
|
||||
labelM[i.Key] = lastStr
|
||||
}
|
||||
for k, v := range labelM {
|
||||
thisLabel := strings.TrimRight(v, "|")
|
||||
labelStrSlice = append(labelStrSlice, fmt.Sprintf(`%s=~"%s"`, k, thisLabel))
|
||||
|
||||
}
|
||||
|
||||
for _, s := range labelStrSlice {
|
||||
qlStr += fmt.Sprintf(`%s,`, s)
|
||||
}
|
||||
qlStr = strings.TrimRight(qlStr, ",")
|
||||
qlStrFinal = fmt.Sprintf(`{%s}`, qlStr)
|
||||
logger.Debugf("[convertToPromql][type=queryLabel][recv:%+v][qlStrFinal:%s]", recv, qlStrFinal)
|
||||
|
||||
return qlStrFinal
|
||||
}
|
||||
|
||||
// 查询数据的转换,metrics_name和标签都是精确匹配
|
||||
func convertToPromqlForQueryData(recv *commonQueryObj) string {
|
||||
|
||||
qlStr := ""
|
||||
qlStrFinal := ""
|
||||
metricName := ""
|
||||
labelIdent := ""
|
||||
labelStrSlice := make([]string, 0)
|
||||
// 匹配metric_name __name__=~"xx.*"
|
||||
if recv.Metric != "" {
|
||||
metricName = fmt.Sprintf(`__name__="%s"`, recv.Metric)
|
||||
|
||||
labelStrSlice = append(labelStrSlice, metricName)
|
||||
|
||||
}
|
||||
// 匹配ident=~"k1.*|k2.*"
|
||||
for _, i := range recv.Idents {
|
||||
if i != "" {
|
||||
labelIdent += fmt.Sprintf(`%s|`, i)
|
||||
}
|
||||
}
|
||||
labelIdent = strings.TrimRight(labelIdent, "|")
|
||||
if labelIdent != "" {
|
||||
labelStrSlice = append(labelStrSlice, fmt.Sprintf(`ident=~"%s"`, labelIdent))
|
||||
}
|
||||
// 匹配标签
|
||||
labelM := make(map[string]string)
|
||||
for _, i := range recv.TagPairs {
|
||||
if i.Key == "" {
|
||||
continue
|
||||
}
|
||||
lastStr, _ := labelM[i.Key]
|
||||
|
||||
lastStr += fmt.Sprintf(`%s|`, i.Value)
|
||||
labelM[i.Key] = lastStr
|
||||
}
|
||||
for k, v := range labelM {
|
||||
thisLabel := strings.TrimRight(v, "|")
|
||||
labelStrSlice = append(labelStrSlice, fmt.Sprintf(`%s=~"%s"`, k, thisLabel))
|
||||
|
||||
}
|
||||
|
||||
for _, s := range labelStrSlice {
|
||||
qlStr += fmt.Sprintf(`%s,`, s)
|
||||
}
|
||||
qlStr = strings.TrimRight(qlStr, ",")
|
||||
qlStrFinal = fmt.Sprintf(`{%s}`, qlStr)
|
||||
logger.Debugf("[convertToPromql][type=queryData][recv:%+v][qlStrFinal:%s]", recv, qlStrFinal)
|
||||
|
||||
return qlStrFinal
|
||||
}
|
||||
|
||||
func parseMatchersParam(matchers []string) ([][]*labels.Matcher, error) {
|
||||
var matcherSets [][]*labels.Matcher
|
||||
for _, s := range matchers {
|
||||
matchers, err := parser.ParseMetricSelector(s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
matcherSets = append(matcherSets, matchers)
|
||||
}
|
||||
|
||||
OUTER:
|
||||
for _, ms := range matcherSets {
|
||||
for _, lm := range ms {
|
||||
if lm != nil && !lm.Matches("") {
|
||||
continue OUTER
|
||||
}
|
||||
}
|
||||
return nil, errors.New("match[] must contain at least one non-empty matcher")
|
||||
}
|
||||
return matcherSets, nil
|
||||
}
|
||||
|
||||
func (pd *PromeDataSource) QueryData(inputs vos.DataQueryParam) []*vos.DataQueryResp {
|
||||
|
||||
respD := make([]*vos.DataQueryResp, 0)
|
||||
for _, input := range inputs.Params {
|
||||
var qlStrFinal string
|
||||
|
||||
if input.PromeQl != "" {
|
||||
qlStrFinal = input.PromeQl
|
||||
} else {
|
||||
if len(input.Idents) == 0 {
|
||||
for i := range input.TagPairs {
|
||||
if input.TagPairs[i].Key == "ident" {
|
||||
input.Idents = append(input.Idents, input.TagPairs[i].Value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(input.Idents) == 0 && input.ClasspathId != 0 {
|
||||
if input.ClasspathPrefix == 0 {
|
||||
classpathAndRes, exists := cache.ClasspathRes.Get(input.ClasspathId)
|
||||
if exists {
|
||||
input.Idents = classpathAndRes.Res
|
||||
}
|
||||
} else {
|
||||
classpath, err := models.ClasspathGet("id=?", input.ClasspathId)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
cps, _ := models.ClasspathGetsByPrefix(classpath.Path)
|
||||
for _, classpath := range cps {
|
||||
classpathAndRes, exists := cache.ClasspathRes.Get(classpath.Id)
|
||||
if exists {
|
||||
idents := classpathAndRes.Res
|
||||
input.Idents = append(input.Idents, idents...)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cj := &commonQueryObj{
|
||||
Idents: input.Idents,
|
||||
TagPairs: input.TagPairs,
|
||||
Metric: input.Metric,
|
||||
Start: inputs.Start,
|
||||
End: inputs.End,
|
||||
MetricNameExact: true,
|
||||
}
|
||||
qlStrFinal = convertToPromqlForQueryData(cj)
|
||||
|
||||
}
|
||||
|
||||
logger.Debugf("[input:%+v][qlStrFinal:%s]\n", input, qlStrFinal)
|
||||
// 转化为utc时间
|
||||
startT := tsToUtcTs(inputs.Start)
|
||||
endT := tsToUtcTs(inputs.End)
|
||||
|
||||
// TODO 前端传入分辨率还是后端计算,grafana和prometheus ui都是前端传入
|
||||
delta := (inputs.End - inputs.Start) / 3600
|
||||
if delta <= 0 {
|
||||
delta = 1
|
||||
}
|
||||
resolution := time.Second * time.Duration(delta*DEFAULT_STEP)
|
||||
|
||||
q, err := pd.QueryEngine.NewRangeQuery(pd.Queryable, qlStrFinal, startT, endT, resolution)
|
||||
if err != nil {
|
||||
logger.Errorf("[prome_query_error][QueryData_error_may_be_parse_ql_error][args:%+v][err:%+v]", input, err)
|
||||
continue
|
||||
}
|
||||
ctx, _ := context.WithTimeout(context.Background(), time.Second*30)
|
||||
res := q.Exec(ctx)
|
||||
// TODO 将err返回给前端
|
||||
if res.Err != nil {
|
||||
logger.Errorf("[prome_query_error][rangeQuery_exec_error][args:%+v][err:%+v]", input, res.Err)
|
||||
q.Close()
|
||||
continue
|
||||
}
|
||||
mat, ok := res.Value.(promql.Matrix)
|
||||
if !ok {
|
||||
logger.Errorf("[promql.Engine.exec: invalid expression type %q]", res.Value.Type())
|
||||
q.Close()
|
||||
continue
|
||||
}
|
||||
if res.Err != nil {
|
||||
logger.Errorf("[prome_query_error][res.Matrix_error][args:%+v][err:%+v]", input, res.Err)
|
||||
q.Close()
|
||||
continue
|
||||
}
|
||||
for index, m := range mat {
|
||||
if inputs.Limit > 0 && index+1 > inputs.Limit {
|
||||
continue
|
||||
}
|
||||
tagStr := ""
|
||||
oneResp := &vos.DataQueryResp{}
|
||||
|
||||
ident := m.Metric.Get(LABEL_IDENT)
|
||||
name := m.Metric.Get(LABEL_NAME)
|
||||
oneResp.Metric = name
|
||||
oneResp.Ident = ident
|
||||
// TODO 去掉point num
|
||||
pNum := len(m.Points)
|
||||
for _, p := range m.Points {
|
||||
tmpP := &vos.Point{
|
||||
Timestamp: p.T,
|
||||
Value: vos.JsonFloat(p.V),
|
||||
}
|
||||
oneResp.Values = append(oneResp.Values, tmpP)
|
||||
}
|
||||
for _, x := range m.Metric {
|
||||
if x.Name == LABEL_NAME {
|
||||
continue
|
||||
}
|
||||
tagStr += fmt.Sprintf("%s=%s,", x.Name, x.Value)
|
||||
}
|
||||
tagStr = strings.TrimRight(tagStr, ",")
|
||||
oneResp.Tags = tagStr
|
||||
oneResp.Resolution = delta * DEFAULT_STEP
|
||||
oneResp.PNum = pNum
|
||||
respD = append(respD, oneResp)
|
||||
|
||||
}
|
||||
q.Close()
|
||||
|
||||
}
|
||||
return respD
|
||||
}
|
||||
|
||||
func tsToUtcTs(s int64) time.Time {
|
||||
return time.Unix(s, 0).UTC()
|
||||
}
|
||||
func timeParse(ts int64) time.Time {
|
||||
t := float64(ts)
|
||||
s, ns := math.Modf(t)
|
||||
ns = math.Round(ns*1000) / 1000
|
||||
return time.Unix(int64(s), int64(ns*float64(time.Second))).UTC()
|
||||
}
|
||||
|
||||
func millisecondTs(t time.Time) int64 {
|
||||
return t.Unix()*1000 + int64(t.Nanosecond())/int64(time.Millisecond)
|
||||
}
|
||||
func tsToStr(timestamp int64) string {
|
||||
timeNow := time.Unix(timestamp, 0)
|
||||
return timeNow.Format("2006-01-02 15:04:05")
|
||||
}
|
||||
|
||||
func (pd *PromeDataSource) CommonQuerySeries(cj *commonQueryObj) storage.SeriesSet {
|
||||
qlStrFinal := convertToPromql(cj)
|
||||
|
||||
if qlStrFinal == "{}" {
|
||||
qlStrFinal = DEFAULT_QL
|
||||
reqMinute := (cj.End - cj.Start) / 60
|
||||
// 如果前端啥都没传,要限制下查询series的时间范围,防止高基础查询
|
||||
if reqMinute > pd.Section.MaxFetchAllSeriesLimitMinute {
|
||||
// 时间超长,用配置文件中的限制一下
|
||||
now := time.Now().Unix()
|
||||
cj.End = now
|
||||
cj.Start = now - pd.Section.MaxFetchAllSeriesLimitMinute*60
|
||||
logger.Debugf("[CommonQuerySeries.FetchAllSeries.LimitQueryTimeRange][start:%v][end:%v]", cj.Start, cj.End)
|
||||
}
|
||||
}
|
||||
|
||||
matcherSets, err := parseMatchersParam([]string{qlStrFinal})
|
||||
if err != nil {
|
||||
logger.Errorf("[prome_query_error][parse_label_match_error][err:%+v]", err)
|
||||
return nil
|
||||
}
|
||||
now := time.Now().Unix()
|
||||
if cj.Start == 0 {
|
||||
cj.Start = now - 60*pd.Section.MaxFetchAllSeriesLimitMinute
|
||||
}
|
||||
if cj.End == 0 {
|
||||
cj.End = now
|
||||
}
|
||||
|
||||
startT := millisecondTs(timeParse(cj.Start))
|
||||
endT := millisecondTs(timeParse(cj.End))
|
||||
|
||||
ctx, _ := context.WithTimeout(context.Background(), time.Second*30)
|
||||
q, err := pd.Queryable.Querier(ctx, startT, endT)
|
||||
if err != nil {
|
||||
|
||||
logger.Errorf("[prome_query_error][get_querier_errro]")
|
||||
return nil
|
||||
}
|
||||
logger.Debugf("[CommonQuerySeries.Result][from:%s][cj.start_ts:%+v cj.start_str:%+v SelectHints.startT:%+v][cj.end_ts:%+v cj.end_str:%+v SelectHints.endT:%+v][qlStrFinal:%s][cj:%+v]",
|
||||
cj.From,
|
||||
cj.Start,
|
||||
tsToStr(cj.Start),
|
||||
startT,
|
||||
cj.End,
|
||||
tsToStr(cj.End),
|
||||
endT,
|
||||
qlStrFinal,
|
||||
cj,
|
||||
)
|
||||
|
||||
defer q.Close()
|
||||
|
||||
hints := &storage.SelectHints{
|
||||
Start: startT,
|
||||
End: endT,
|
||||
Func: "series", // There is no series function, this token is used for lookups that don't need samples.
|
||||
}
|
||||
|
||||
// Get all series which match matchers.
|
||||
s := q.Select(true, hints, matcherSets[0]...)
|
||||
return s
|
||||
|
||||
}
|
||||
|
||||
// 全部转化为 {__name__="a",label_a!="b",label_b=~"d|c",label_c!~"d"}
|
||||
// 对应prometheus 中的 /api/v1/labels
|
||||
// TODO 等待prometheus官方对 remote_read label_values 的支持
|
||||
// Implement: https://github.com/prometheus/prometheus/issues/3351
|
||||
func (pd *PromeDataSource) QueryTagKeys(recv vos.CommonTagQueryParam) *vos.TagKeyQueryResp {
|
||||
// TODO 完成标签匹配模式
|
||||
respD := &vos.TagKeyQueryResp{
|
||||
Keys: make([]string, 0),
|
||||
}
|
||||
|
||||
labelNamesSet := make(map[string]struct{})
|
||||
for _, x := range recv.Params {
|
||||
|
||||
cj := &commonQueryObj{
|
||||
Idents: x.Idents,
|
||||
TagPairs: recv.TagPairs,
|
||||
Metric: x.Metric,
|
||||
Start: recv.Start,
|
||||
End: recv.End,
|
||||
From: "QueryTagKeys",
|
||||
}
|
||||
|
||||
s := pd.CommonQuerySeries(cj)
|
||||
if s.Warnings() != nil {
|
||||
logger.Warningf("[prome_query_error][series_set_iter_error][warning:%+v]", s.Warnings())
|
||||
|
||||
}
|
||||
|
||||
if err := s.Err(); err != nil {
|
||||
logger.Errorf("[prome_query_error][series_set_iter_error][err:%+v]", err)
|
||||
continue
|
||||
}
|
||||
for s.Next() {
|
||||
series := s.At()
|
||||
for _, lb := range series.Labels() {
|
||||
if lb.Name == LABEL_NAME {
|
||||
continue
|
||||
|
||||
}
|
||||
if recv.TagKey != "" {
|
||||
if !strings.Contains(lb.Name, recv.TagKey) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
labelNamesSet[lb.Name] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
names := make([]string, 0)
|
||||
for key := range labelNamesSet {
|
||||
|
||||
names = append(names, key)
|
||||
}
|
||||
sort.Strings(names)
|
||||
// 因为map中的key是无序的,必须这样才能稳定输出
|
||||
if recv.Limit > 0 && len(names) > recv.Limit {
|
||||
names = names[:recv.Limit]
|
||||
}
|
||||
|
||||
respD.Keys = names
|
||||
return respD
|
||||
|
||||
}
|
||||
|
||||
// 对应prometheus 中的 /api/v1/label/<label_name>/values
|
||||
func (pd *PromeDataSource) QueryTagValues(recv vos.CommonTagQueryParam) *vos.TagValueQueryResp {
|
||||
labelValuesSet := make(map[string]struct{})
|
||||
for _, x := range recv.Params {
|
||||
cj := &commonQueryObj{
|
||||
Idents: x.Idents,
|
||||
Metric: x.Metric,
|
||||
TagPairs: recv.TagPairs,
|
||||
Start: recv.Start,
|
||||
End: recv.End,
|
||||
From: "QueryTagValues",
|
||||
}
|
||||
|
||||
s := pd.CommonQuerySeries(cj)
|
||||
if s.Warnings() != nil {
|
||||
logger.Warningf("[prome_query_error][series_set_iter_error][warning:%+v]", s.Warnings())
|
||||
|
||||
}
|
||||
|
||||
if err := s.Err(); err != nil {
|
||||
logger.Errorf("[prome_query_error][series_set_iter_error][err:%+v]", err)
|
||||
continue
|
||||
}
|
||||
|
||||
for s.Next() {
|
||||
series := s.At()
|
||||
for _, lb := range series.Labels() {
|
||||
if lb.Name == recv.TagKey {
|
||||
if recv.TagValue != "" {
|
||||
if !strings.Contains(lb.Value, recv.TagValue) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
labelValuesSet[lb.Value] = struct{}{}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
vals := make([]string, 0)
|
||||
for val := range labelValuesSet {
|
||||
|
||||
vals = append(vals, val)
|
||||
}
|
||||
sort.Strings(vals)
|
||||
if recv.Limit > 0 && len(vals) > recv.Limit {
|
||||
vals = vals[:recv.Limit]
|
||||
}
|
||||
respD := &vos.TagValueQueryResp{}
|
||||
respD.Values = vals
|
||||
return respD
|
||||
|
||||
}
|
||||
|
||||
// 对应prometheus 中的 /api/v1/label/<label_name>/values label_name == __name__
|
||||
func (pd *PromeDataSource) QueryMetrics(recv vos.MetricQueryParam) *vos.MetricQueryResp {
|
||||
cj := &commonQueryObj{
|
||||
Idents: recv.Idents,
|
||||
Metric: recv.Metric,
|
||||
TagPairs: recv.TagPairs,
|
||||
Start: recv.Start,
|
||||
End: recv.End,
|
||||
From: "QueryMetrics",
|
||||
}
|
||||
|
||||
respD := &vos.MetricQueryResp{}
|
||||
respD.Metrics = make([]string, 0)
|
||||
s := pd.CommonQuerySeries(cj)
|
||||
for _, x := range s.Warnings() {
|
||||
logger.Warningf("[prome_query_error][series_set_iter_error][warning:%+v]\n", x.Error())
|
||||
|
||||
}
|
||||
|
||||
if err := s.Err(); err != nil {
|
||||
logger.Errorf("[prome_query_error][series_set_iter_error][err:%+v]", err)
|
||||
return respD
|
||||
}
|
||||
|
||||
var sets []storage.SeriesSet
|
||||
sets = append(sets, s)
|
||||
set := storage.NewMergeSeriesSet(sets, storage.ChainedSeriesMerge)
|
||||
labelValuesSet := make(map[string]struct{})
|
||||
//for s.Next() {
|
||||
for set.Next() {
|
||||
series := set.At()
|
||||
for _, lb := range series.Labels() {
|
||||
if lb.Name == LABEL_NAME {
|
||||
labelValuesSet[lb.Value] = struct{}{}
|
||||
}
|
||||
}
|
||||
}
|
||||
vals := make([]string, 0)
|
||||
for val := range labelValuesSet {
|
||||
vals = append(vals, val)
|
||||
}
|
||||
|
||||
sort.Strings(vals)
|
||||
|
||||
if recv.Limit > 0 && len(vals) > recv.Limit {
|
||||
vals = vals[:recv.Limit]
|
||||
}
|
||||
respD.Metrics = vals
|
||||
return respD
|
||||
}
|
||||
|
||||
// 对应prometheus 中的 /api/v1/series
|
||||
func (pd *PromeDataSource) QueryTagPairs(recv vos.CommonTagQueryParam) *vos.TagPairQueryResp {
|
||||
respD := &vos.TagPairQueryResp{
|
||||
TagPairs: make([]string, 0),
|
||||
Idents: make([]string, 0),
|
||||
}
|
||||
tps := make(map[string]struct{})
|
||||
for _, x := range recv.Params {
|
||||
cj := &commonQueryObj{
|
||||
Idents: x.Idents,
|
||||
TagPairs: recv.TagPairs,
|
||||
Metric: x.Metric,
|
||||
Start: recv.Start,
|
||||
End: recv.End,
|
||||
From: "QueryTagPairs",
|
||||
}
|
||||
|
||||
s := pd.CommonQuerySeries(cj)
|
||||
if s.Warnings() != nil {
|
||||
logger.Warningf("[prome_query_error][series_set_iter_error][warning:%+v]", s.Warnings())
|
||||
|
||||
}
|
||||
|
||||
if err := s.Err(); err != nil {
|
||||
logger.Errorf("[prome_query_error][series_set_iter_error][err:%+v]", err)
|
||||
continue
|
||||
}
|
||||
|
||||
var sets []storage.SeriesSet
|
||||
sets = append(sets, s)
|
||||
set := storage.NewMergeSeriesSet(sets, storage.ChainedSeriesMerge)
|
||||
|
||||
labelIdents := make([]string, 0)
|
||||
for set.Next() {
|
||||
series := s.At()
|
||||
labelsS := series.Labels()
|
||||
for _, i := range labelsS {
|
||||
|
||||
if i.Name == LABEL_NAME {
|
||||
continue
|
||||
}
|
||||
if i.Name == LABEL_IDENT {
|
||||
labelIdents = append(labelIdents, i.Value)
|
||||
}
|
||||
tps[fmt.Sprintf("%s=%s", i.Name, i.Value)] = struct{}{}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
newTags := make([]string, 0)
|
||||
for k := range tps {
|
||||
|
||||
newTags = append(newTags, k)
|
||||
}
|
||||
|
||||
sort.Strings(newTags)
|
||||
if recv.Limit > 0 && len(newTags) > recv.Limit {
|
||||
newTags = newTags[:recv.Limit]
|
||||
}
|
||||
|
||||
respD.TagPairs = newTags
|
||||
return respD
|
||||
}
|
||||
|
||||
func (pd *PromeDataSource) QueryVector(ql string) promql.Vector {
|
||||
t := time.Now()
|
||||
q, err := pd.QueryEngine.NewInstantQuery(pd.Queryable, ql, t)
|
||||
if err != nil {
|
||||
logger.Errorf("[prome_query_error][new_insQuery_error][err:%+v][ql:%+v]", err, ql)
|
||||
return nil
|
||||
}
|
||||
ctx := context.Background()
|
||||
res := q.Exec(ctx)
|
||||
if res.Err != nil {
|
||||
logger.Errorf("[prome_query_error][insQuery_exec_error][err:%+v][ql:%+v]", err, ql)
|
||||
return nil
|
||||
}
|
||||
defer q.Close()
|
||||
switch v := res.Value.(type) {
|
||||
case promql.Vector:
|
||||
return v
|
||||
case promql.Scalar:
|
||||
return promql.Vector{promql.Sample{
|
||||
Point: promql.Point(v),
|
||||
Metric: labels.Labels{},
|
||||
}}
|
||||
default:
|
||||
logger.Errorf("[prome_query_error][insQuery_res_error rule result is not a vector or scalar][err:%+v][ql:%+v]", err, ql)
|
||||
return nil
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
#!/bin/bash
|
||||
|
||||
# release version
|
||||
version=5.0.0-rc1
|
||||
|
||||
export GO111MODULE=on
|
||||
go build -ldflags "-X main.version=${version}" -o n9e-server main.go
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
package cache
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type AlertMuteMap struct {
|
||||
sync.RWMutex
|
||||
Data map[string][]Filter
|
||||
}
|
||||
type Filter struct {
|
||||
ResReg *regexp.Regexp
|
||||
TagsMap map[string]string
|
||||
}
|
||||
|
||||
var AlertMute = &AlertMuteMap{Data: make(map[string][]Filter)}
|
||||
|
||||
func (a *AlertMuteMap) SetAll(m map[string][]Filter) {
|
||||
a.Lock()
|
||||
defer a.Unlock()
|
||||
a.Data = m
|
||||
}
|
||||
|
||||
func (a *AlertMuteMap) GetByKey(key string) ([]Filter, bool) {
|
||||
a.RLock()
|
||||
defer a.RUnlock()
|
||||
|
||||
value, exists := a.Data[key]
|
||||
|
||||
return value, exists
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
package cache
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/didi/nightingale/v5/models"
|
||||
)
|
||||
|
||||
type AlertRulesByMetricCache struct {
|
||||
sync.RWMutex
|
||||
Data map[string][]*models.AlertRule // key是metric,便于后续检索
|
||||
MaxUpdateTs int64 // 从数据库拿到的最大update_at
|
||||
RuleNum int64 // 从数据库中统计到的行数
|
||||
LastSync int64 // 保存上次全量同步时间
|
||||
}
|
||||
|
||||
var (
|
||||
AlertRulesByMetric = &AlertRulesByMetricCache{Data: make(map[string][]*models.AlertRule)}
|
||||
)
|
||||
|
||||
func (a *AlertRulesByMetricCache) GetBy(instance string) []*models.AlertRule {
|
||||
a.RLock()
|
||||
defer a.RUnlock()
|
||||
|
||||
return a.Data[instance]
|
||||
}
|
||||
|
||||
func (a *AlertRulesByMetricCache) SetAll(alertRulesMap map[string][]*models.AlertRule, lastUpdateTs, ruleNum, lastSync int64) {
|
||||
a.Lock()
|
||||
defer a.Unlock()
|
||||
|
||||
a.Data = alertRulesMap
|
||||
a.MaxUpdateTs = lastUpdateTs
|
||||
a.RuleNum = ruleNum
|
||||
a.LastSync = lastSync
|
||||
}
|
||||
|
||||
type AlertRulesTotalCache struct {
|
||||
sync.RWMutex
|
||||
Data map[int64]*models.AlertRule
|
||||
}
|
||||
|
||||
var AlertRules = &AlertRulesTotalCache{Data: make(map[int64]*models.AlertRule)}
|
||||
|
||||
func (a *AlertRulesTotalCache) Get(id int64) (*models.AlertRule, bool) {
|
||||
a.RLock()
|
||||
defer a.RUnlock()
|
||||
|
||||
alertRule, exists := a.Data[id]
|
||||
return alertRule, exists
|
||||
}
|
||||
|
||||
func (a *AlertRulesTotalCache) SetAll(alertRulesMap map[int64]*models.AlertRule) {
|
||||
a.Lock()
|
||||
defer a.Unlock()
|
||||
|
||||
a.Data = alertRulesMap
|
||||
}
|
||||
|
||||
// 获取所有PULL型规则的列表
|
||||
func (a *AlertRulesTotalCache) Pulls() []*models.AlertRule {
|
||||
a.RLock()
|
||||
defer a.RUnlock()
|
||||
|
||||
cnt := len(a.Data)
|
||||
ret := make([]*models.AlertRule, 0, cnt)
|
||||
|
||||
for _, rule := range a.Data {
|
||||
if rule.Type == models.PULL {
|
||||
ret = append(ret, rule)
|
||||
}
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package cache
|
||||
|
||||
import (
|
||||
cmap "github.com/orcaman/concurrent-map"
|
||||
)
|
||||
|
||||
var MetricDescMapper = cmap.New()
|
|
@ -0,0 +1,27 @@
|
|||
package cache
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
type ClasspathPrefixMap struct {
|
||||
sync.RWMutex
|
||||
Data map[int64][]int64
|
||||
}
|
||||
|
||||
var ClasspathPrefix = &ClasspathPrefixMap{Data: make(map[int64][]int64)}
|
||||
|
||||
func (c *ClasspathPrefixMap) Get(id int64) ([]int64, bool) {
|
||||
c.RLock()
|
||||
defer c.RUnlock()
|
||||
ids, exists := c.Data[id]
|
||||
return ids, exists
|
||||
}
|
||||
|
||||
func (c *ClasspathPrefixMap) SetAll(data map[int64][]int64) {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
|
||||
c.Data = data
|
||||
return
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package cache
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/didi/nightingale/v5/models"
|
||||
)
|
||||
|
||||
type ClasspathResMap struct {
|
||||
sync.RWMutex
|
||||
Data map[int64]*ClasspathAndRes
|
||||
}
|
||||
|
||||
type ClasspathAndRes struct {
|
||||
Res []string
|
||||
Classpath *models.Classpath
|
||||
}
|
||||
|
||||
// classpath_id -> classpath & res_idents
|
||||
var ClasspathRes = &ClasspathResMap{Data: make(map[int64]*ClasspathAndRes)}
|
||||
|
||||
func (c *ClasspathResMap) Get(id int64) (*ClasspathAndRes, bool) {
|
||||
c.RLock()
|
||||
defer c.RUnlock()
|
||||
resources, exists := c.Data[id]
|
||||
return resources, exists
|
||||
}
|
||||
|
||||
func (c *ClasspathResMap) SetAll(collectRulesMap map[int64]*ClasspathAndRes) {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
c.Data = collectRulesMap
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package cache
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/didi/nightingale/v5/models"
|
||||
)
|
||||
|
||||
type CollectRuleOfIdentMap struct {
|
||||
sync.RWMutex
|
||||
Data map[string][]*models.CollectRule
|
||||
}
|
||||
|
||||
var CollectRulesOfIdent = &CollectRuleOfIdentMap{Data: make(map[string][]*models.CollectRule)}
|
||||
|
||||
func (c *CollectRuleOfIdentMap) GetBy(ident string) []*models.CollectRule {
|
||||
c.RLock()
|
||||
defer c.RUnlock()
|
||||
return c.Data[ident]
|
||||
}
|
||||
|
||||
func (c *CollectRuleOfIdentMap) Set(node string, collectRules []*models.CollectRule) {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
c.Data[node] = collectRules
|
||||
}
|
||||
|
||||
func (c *CollectRuleOfIdentMap) SetAll(collectRulesMap map[string][]*models.CollectRule) {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
c.Data = collectRulesMap
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
package cache
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
type SafeDoubleMap struct {
|
||||
sync.RWMutex
|
||||
M map[string]map[string]struct{}
|
||||
}
|
||||
|
||||
// res_ident -> classpath_path -> struct{}{}
|
||||
var ResClasspath = &SafeDoubleMap{M: make(map[string]map[string]struct{})}
|
||||
|
||||
func (s *SafeDoubleMap) GetKeys() []string {
|
||||
s.RLock()
|
||||
defer s.RUnlock()
|
||||
|
||||
keys := make([]string, 0, len(s.M))
|
||||
for key := range s.M {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
|
||||
return keys
|
||||
}
|
||||
|
||||
func (s *SafeDoubleMap) GetValues(key string) []string {
|
||||
s.RLock()
|
||||
defer s.RUnlock()
|
||||
|
||||
valueMap, exists := s.M[key]
|
||||
if !exists {
|
||||
return []string{}
|
||||
}
|
||||
|
||||
values := make([]string, 0, len(valueMap))
|
||||
|
||||
for value := range valueMap {
|
||||
values = append(values, value)
|
||||
}
|
||||
|
||||
return values
|
||||
}
|
||||
|
||||
func (s *SafeDoubleMap) Exists(key string, value string) bool {
|
||||
s.RLock()
|
||||
defer s.RUnlock()
|
||||
|
||||
if _, exists := s.M[key]; !exists {
|
||||
return false
|
||||
}
|
||||
|
||||
if _, exists := s.M[key][value]; !exists {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *SafeDoubleMap) Set(key string, value string) {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
|
||||
if _, exists := s.M[key]; !exists {
|
||||
s.M[key] = make(map[string]struct{})
|
||||
}
|
||||
|
||||
s.M[key][value] = struct{}{}
|
||||
}
|
||||
|
||||
func (s *SafeDoubleMap) SetAll(data map[string]map[string]struct{}) {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
|
||||
s.M = data
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package cache
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/didi/nightingale/v5/models"
|
||||
)
|
||||
|
||||
// resource_ident -> tags_map
|
||||
// 监控数据上报的时候,要把资源的tags附到指标数据上
|
||||
type ResTagsMap struct {
|
||||
sync.RWMutex
|
||||
Data map[string]ResourceAndTags
|
||||
}
|
||||
|
||||
type ResourceAndTags struct {
|
||||
Tags map[string]string
|
||||
Resource models.Resource
|
||||
}
|
||||
|
||||
var ResTags = &ResTagsMap{Data: make(map[string]ResourceAndTags)}
|
||||
|
||||
func (r *ResTagsMap) SetAll(m map[string]ResourceAndTags) {
|
||||
r.Lock()
|
||||
defer r.Unlock()
|
||||
r.Data = m
|
||||
}
|
||||
|
||||
func (r *ResTagsMap) Get(key string) (ResourceAndTags, bool) {
|
||||
r.RLock()
|
||||
defer r.RUnlock()
|
||||
|
||||
value, exists := r.Data[key]
|
||||
|
||||
return value, exists
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package cache
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/didi/nightingale/v5/models"
|
||||
)
|
||||
|
||||
type UserMap struct {
|
||||
sync.RWMutex
|
||||
Data map[int64]*models.User
|
||||
}
|
||||
|
||||
var UserCache = &UserMap{Data: make(map[int64]*models.User)}
|
||||
|
||||
func (s *UserMap) GetBy(id int64) *models.User {
|
||||
s.RLock()
|
||||
defer s.RUnlock()
|
||||
|
||||
return s.Data[id]
|
||||
}
|
||||
|
||||
func (s *UserMap) GetByIds(ids []int64) []*models.User {
|
||||
s.RLock()
|
||||
defer s.RUnlock()
|
||||
var users []*models.User
|
||||
for _, id := range ids {
|
||||
if s.Data[id] == nil {
|
||||
continue
|
||||
}
|
||||
users = append(users, s.Data[id])
|
||||
}
|
||||
|
||||
return users
|
||||
}
|
||||
|
||||
func (s *UserMap) SetAll(users map[int64]*models.User) {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
s.Data = users
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package cache
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
type UserGroupMemberMap struct {
|
||||
sync.RWMutex
|
||||
Data map[int64]map[int64]struct{}
|
||||
}
|
||||
|
||||
// groupid -> userid
|
||||
var UserGroupMember = &UserGroupMemberMap{Data: make(map[int64]map[int64]struct{})}
|
||||
|
||||
func (m *UserGroupMemberMap) Get(id int64) (map[int64]struct{}, bool) {
|
||||
m.RLock()
|
||||
defer m.RUnlock()
|
||||
ids, exists := m.Data[id]
|
||||
return ids, exists
|
||||
}
|
||||
|
||||
func (m *UserGroupMemberMap) Exists(gid, uid int64) bool {
|
||||
m.RLock()
|
||||
defer m.RUnlock()
|
||||
uidMap, exists := m.Data[gid]
|
||||
if !exists {
|
||||
return false
|
||||
}
|
||||
|
||||
_, exists = uidMap[uid]
|
||||
return exists
|
||||
}
|
||||
|
||||
func (m *UserGroupMemberMap) SetAll(data map[int64]map[int64]struct{}) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
m.Data = data
|
||||
}
|
15
changelog
15
changelog
|
@ -132,7 +132,7 @@
|
|||
- 服务端模块合并为一个模块
|
||||
- agentd和server的调用全部走rpc
|
||||
|
||||
重新安装:见 https://n9e.didiyun.com/docs/install/binary/
|
||||
重新安装:见 https://n9e.didiyun.com/v4/docs/install/
|
||||
|
||||
升级方法:
|
||||
- 使用新的etc替换掉原来的etc
|
||||
|
@ -145,7 +145,7 @@
|
|||
升级内容:
|
||||
- 修复消息通知的问题
|
||||
|
||||
重新安装:见 https://n9e.didiyun.com/docs/install/binary/
|
||||
重新安装:见 https://n9e.didiyun.com/v4/docs/install/
|
||||
|
||||
升级方法:
|
||||
- 将 *.tpl 文件放到 etc/tpl 下
|
||||
|
@ -157,7 +157,7 @@
|
|||
- 优化告警接收人补全逻辑
|
||||
- 增加pospostgresql监控插件
|
||||
|
||||
重新安装:见 https://n9e.didiyun.com/docs/install/binary/
|
||||
重新安装:见 https://n9e.didiyun.com/v4/docs/install/
|
||||
|
||||
升级方法:
|
||||
- 替换n9e-server n9e-prober
|
||||
|
@ -167,4 +167,11 @@
|
|||
- 修复nodata恢复告警重复问题
|
||||
|
||||
升级方法:
|
||||
- 替换n9e-server
|
||||
- 替换n9e-server
|
||||
|
||||
5.0.0-rc1
|
||||
升级内容:
|
||||
- 发布v5预览版
|
||||
|
||||
部署方式:
|
||||
- 见文档 https://n9e.didiyun.com/docs/install/
|
|
@ -0,0 +1,163 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
"github.com/toolkits/pkg/file"
|
||||
|
||||
"github.com/didi/nightingale/v5/backend"
|
||||
"github.com/didi/nightingale/v5/models"
|
||||
"github.com/didi/nightingale/v5/pkg/i18n"
|
||||
"github.com/didi/nightingale/v5/pkg/iconf"
|
||||
"github.com/didi/nightingale/v5/pkg/ilog"
|
||||
)
|
||||
|
||||
type ConfigStruct struct {
|
||||
Logger ilog.Config `yaml:"logger"`
|
||||
HTTP httpSection `yaml:"http"`
|
||||
RPC rpcSection `yaml:"rpc"`
|
||||
LDAP models.LdapSection `yaml:"ldap"`
|
||||
MySQL models.MysqlSection `yaml:"mysql"`
|
||||
Heartbeat heartbeatSection `yaml:"heartbeat"`
|
||||
I18N i18n.Config `yaml:"i18n"`
|
||||
Judge judgeSection `yaml:"judge"`
|
||||
Alert alertSection `yaml:"alert"`
|
||||
Trans transSection `yaml:"trans"`
|
||||
ContactKeys []contactKey `yaml:"contactKeys"`
|
||||
NotifyChannels []string `yaml:"notifyChannels"`
|
||||
}
|
||||
|
||||
type alertSection struct {
|
||||
NotifyScriptPath string `yaml:"notifyScriptPath"`
|
||||
NotifyConcurrency int `yaml:"notifyConcurrency"`
|
||||
MutedAlertPersist bool `yaml:"mutedAlertPersist"`
|
||||
}
|
||||
|
||||
type transSection struct {
|
||||
Enable bool `yaml:"enable"`
|
||||
Backend backend.BackendSection `yaml:"backend"`
|
||||
}
|
||||
|
||||
type judgeSection struct {
|
||||
ReadBatch int `yaml:"readBatch"`
|
||||
ConnTimeout int `yaml:"connTimeout"`
|
||||
CallTimeout int `yaml:"callTimeout"`
|
||||
WriterNum int `yaml:"writerNum"`
|
||||
ConnMax int `yaml:"connMax"`
|
||||
ConnIdle int `yaml:"connIdle"`
|
||||
}
|
||||
|
||||
type heartbeatSection struct {
|
||||
IP string `yaml:"ip"`
|
||||
LocalAddr string `yaml:"-"`
|
||||
Interval int64 `yaml:"interval"`
|
||||
}
|
||||
|
||||
type httpSection struct {
|
||||
Mode string `yaml:"mode"`
|
||||
Access bool `yaml:"access"`
|
||||
Listen string `yaml:"listen"`
|
||||
Pprof bool `yaml:"pprof"`
|
||||
CookieName string `yaml:"cookieName"`
|
||||
CookieDomain string `yaml:"cookieDomain"`
|
||||
CookieSecure bool `yaml:"cookieSecure"`
|
||||
CookieHttpOnly bool `yaml:"cookieHttpOnly"`
|
||||
CookieMaxAge int `yaml:"cookieMaxAge"`
|
||||
CookieSecret string `yaml:"cookieSecret"`
|
||||
CsrfSecret string `yaml:"csrfSecret"`
|
||||
}
|
||||
|
||||
type rpcSection struct {
|
||||
Listen string `yaml:"listen"`
|
||||
}
|
||||
|
||||
type contactKey struct {
|
||||
Label string `yaml:"label" json:"label"`
|
||||
Key string `yaml:"key" json:"key"`
|
||||
}
|
||||
|
||||
var Config *ConfigStruct
|
||||
|
||||
func Parse() error {
|
||||
ymlFile := iconf.GetYmlFile("server")
|
||||
if ymlFile == "" {
|
||||
return fmt.Errorf("configuration file of server not found")
|
||||
}
|
||||
|
||||
bs, err := file.ReadBytes(ymlFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot read yml[%s]: %v", ymlFile, err)
|
||||
}
|
||||
|
||||
viper.SetConfigType("yaml")
|
||||
err = viper.ReadConfig(bytes.NewBuffer(bs))
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot read yml[%s]: %v", ymlFile, err)
|
||||
}
|
||||
|
||||
// default value settings
|
||||
viper.SetDefault("i18n.lang", "zh")
|
||||
viper.SetDefault("heartbeat.interval", 1000)
|
||||
viper.SetDefault("judge.readBatch", 2000)
|
||||
viper.SetDefault("judge.connTimeout", 2000)
|
||||
viper.SetDefault("judge.callTimeout", 5000)
|
||||
viper.SetDefault("judge.writerNum", 256)
|
||||
viper.SetDefault("judge.connMax", 2560)
|
||||
viper.SetDefault("judge.connIdle", 256)
|
||||
viper.SetDefault("alert.notifyScriptPath", "./etc/script/notify.py")
|
||||
viper.SetDefault("alert.notifyScriptConcurrency", 200)
|
||||
viper.SetDefault("alert.mutedAlertPersist", true)
|
||||
viper.SetDefault("trans.backend.prometheus.lookbackDeltaMinute", 2)
|
||||
viper.SetDefault("trans.backend.prometheus.maxConcurrentQuery", 30)
|
||||
viper.SetDefault("trans.backend.prometheus.maxSamples", 50000000)
|
||||
viper.SetDefault("trans.backend.prometheus.maxFetchAllSeriesLimitMinute", 5)
|
||||
|
||||
err = viper.Unmarshal(&Config)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot read yml[%s]: %v", ymlFile, err)
|
||||
}
|
||||
|
||||
fmt.Println("config.file:", ymlFile)
|
||||
|
||||
if Config.Heartbeat.IP == "" {
|
||||
// auto detect
|
||||
Config.Heartbeat.IP = fmt.Sprint(GetOutboundIP())
|
||||
|
||||
if Config.Heartbeat.IP == "" {
|
||||
fmt.Println("heartbeat ip auto got is blank")
|
||||
os.Exit(1)
|
||||
}
|
||||
port := strings.Split(Config.RPC.Listen, ":")[1]
|
||||
endpoint := Config.Heartbeat.IP + ":" + port
|
||||
Config.Heartbeat.LocalAddr = endpoint
|
||||
}
|
||||
|
||||
// 正常情况肯定不是127.0.0.1,但是,如果就是单机部署,并且这个机器没有网络,比如本地调试并且本机没网的时候
|
||||
// if Config.Heartbeat.IP == "127.0.0.1" {
|
||||
// fmt.Println("heartbeat ip is 127.0.0.1 and it is useless, so, exit")
|
||||
// os.Exit(1)
|
||||
// }
|
||||
|
||||
fmt.Println("heartbeat.ip:", Config.Heartbeat.IP)
|
||||
fmt.Printf("heartbeat.interval: %dms\n", Config.Heartbeat.Interval)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get preferred outbound ip of this machine
|
||||
func GetOutboundIP() net.IP {
|
||||
conn, err := net.Dial("udp", "8.8.8.8:80")
|
||||
if err != nil {
|
||||
fmt.Println("auto get outbound ip fail:", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
localAddr := conn.LocalAddr().(*net.UDPAddr)
|
||||
|
||||
return localAddr.IP
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
package config
|
||||
|
||||
// Server周期性去数据库心跳,给自己起的名字
|
||||
const EndpointName = "server_rpc"
|
|
@ -0,0 +1,65 @@
|
|||
package config
|
||||
|
||||
import "github.com/didi/nightingale/v5/pkg/i18n"
|
||||
|
||||
var (
|
||||
dict = map[string]string{
|
||||
"Login fail, check your username and password": "登录失败,请检查您的用户名和密码",
|
||||
"Internal server error, try again later please": "系统内部错误,请稍后再试",
|
||||
"Each user has at most two tokens": "每个用户至多创建两个密钥",
|
||||
"No such token": "密钥不存在",
|
||||
"Username is blank": "用户名不能为空",
|
||||
"Username has invalid characters": "用户名含有非法字符",
|
||||
"Nickname has invalid characters": "用户昵称含有非法字符",
|
||||
"Phone invalid": "手机号格式有误",
|
||||
"Email invalid": "邮箱格式有误",
|
||||
"Incorrect old password": "旧密码错误",
|
||||
"Username %s already exists": "用户名(%s)已存在",
|
||||
"No such user": "用户不存在",
|
||||
"UserGroup %s already exists": "用户组(%s)已存在",
|
||||
"Group name has invalid characters": "分组名称含有非法字符",
|
||||
"Group note has invalid characters": "分组备注含有非法字符",
|
||||
"No such user group": "用户组不存在",
|
||||
"Classpath path has invalid characters": "机器分组路径含有非法字符",
|
||||
"Classpath note has invalid characters": "机器分组路径备注含有非法字符",
|
||||
"There are still resources under the classpath": "机器分组路径下仍然挂有资源",
|
||||
"There are still collect rules under the classpath": "机器分组路径下仍然存在采集策略",
|
||||
"No such classpath": "机器分组路径不存在",
|
||||
"Classpath %s already exists": "机器分组路径(%s)已存在",
|
||||
"Preset classpath %s cannot delete": "内置机器分组(%s)不允许删除",
|
||||
"No such mute config": "此屏蔽配置不存在",
|
||||
"DashboardGroup name has invalid characters": "大盘分组名称含有非法字符",
|
||||
"DashboardGroup name is blank": "大盘分组名称为空",
|
||||
"DashboardGroup %s already exists": "大盘分组(%s)已存在",
|
||||
"No such dashboard group": "大盘分组不存在",
|
||||
"Dashboard name has invalid characters": "大盘名称含有非法字符",
|
||||
"Dashboard %s already exists": "监控大盘(%s)已存在",
|
||||
"ChartGroup name has invalid characters": "图表分组名称含有非法字符",
|
||||
"No such dashboard": "监控大盘不存在",
|
||||
"No such chart group": "图表分组不存在",
|
||||
"No such chart": "图表不存在",
|
||||
"There are still dashboards under the group": "分组下面仍然存在监控大盘,请先从组内移出",
|
||||
"AlertRuleGroup name has invalid characters": "告警规则分组含有非法字符",
|
||||
"AlertRuleGroup %s already exists": "告警规则分组(%s)已存在",
|
||||
"There are still alert rules under the group": "分组下面仍然存在告警规则",
|
||||
"AlertRule name has invalid characters": "告警规则含有非法字符",
|
||||
"No such alert rule": "告警规则不存在",
|
||||
"No such alert rule group": "告警规则分组不存在",
|
||||
"No such alert event": "告警事件不存在",
|
||||
"No such collect rule": "采集规则不存在",
|
||||
"Decoded metric description empty": "导入的指标释义列表为空",
|
||||
"User disabled": "用户已被禁用",
|
||||
"Tags(%s) invalid": "标签(%s)格式不合法",
|
||||
"Resource filter(Func:%s)'s param invalid": "资源过滤条件(函数:%s)参数不合法(为空或包含空格都不合法)",
|
||||
"Tags filter(Func:%s)'s param invalid": "标签过滤条件(函数:%s)参数不合法(为空或包含空格都不合法)",
|
||||
"Regexp: %s cannot be compiled": "正则表达式(%s)不合法,无法编译",
|
||||
"AppendTags(%s) invalid": "附件标签(%s)格式不合法",
|
||||
}
|
||||
langDict = map[string]map[string]string{
|
||||
"zh": dict,
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
i18n.DictRegister(langDict)
|
||||
}
|
251
control
251
control
|
@ -1,251 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
# release version
|
||||
version=4.0.3
|
||||
|
||||
CWD=$(cd $(dirname $0)/; pwd)
|
||||
cd $CWD
|
||||
|
||||
usage()
|
||||
{
|
||||
echo $"Usage: $0 {start|stop|restart|status|build|build_local|pack} <module>"
|
||||
exit 0
|
||||
}
|
||||
|
||||
start_all()
|
||||
{
|
||||
test -x n9e-server && start server
|
||||
test -x n9e-agentd && start agentd
|
||||
test -x n9e-prober && start prober
|
||||
}
|
||||
|
||||
start()
|
||||
{
|
||||
mod=$1
|
||||
if [ "x${mod}" = "x" ]; then
|
||||
usage
|
||||
return
|
||||
fi
|
||||
|
||||
if [ "x${mod}" = "xall" ]; then
|
||||
start_all
|
||||
return
|
||||
fi
|
||||
|
||||
binfile=n9e-${mod}
|
||||
|
||||
if [ ! -f $binfile ]; then
|
||||
echo "file[$binfile] not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ $(ps aux|grep -v grep|grep -v control|grep "$binfile" -c) -gt 0 ]; then
|
||||
echo "${mod} already started"
|
||||
return
|
||||
fi
|
||||
|
||||
mkdir -p logs/$mod
|
||||
nohup $CWD/$binfile &> logs/${mod}/stdout.log &
|
||||
|
||||
for((i=1;i<=15;i++)); do
|
||||
if [ $(ps aux|grep -v grep|grep -v control|grep "$binfile" -c) -gt 0 ]; then
|
||||
echo "${mod} started"
|
||||
return
|
||||
fi
|
||||
sleep 0.2
|
||||
done
|
||||
|
||||
echo "cannot start ${mod}"
|
||||
exit 1
|
||||
}
|
||||
|
||||
stop_all()
|
||||
{
|
||||
test -x n9e-server && stop server
|
||||
test -x n9e-prober && stop prober
|
||||
test -x n9e-agentd && stop agentd
|
||||
}
|
||||
|
||||
stop()
|
||||
{
|
||||
mod=$1
|
||||
if [ "x${mod}" = "x" ]; then
|
||||
usage
|
||||
return
|
||||
fi
|
||||
|
||||
if [ "x${mod}" = "xall" ]; then
|
||||
stop_all
|
||||
return
|
||||
fi
|
||||
|
||||
binfile=n9e-${mod}
|
||||
|
||||
if [ $(ps aux|grep -v grep|grep -v control|grep "$binfile" -c) -eq 0 ]; then
|
||||
echo "${mod} already stopped"
|
||||
return
|
||||
fi
|
||||
|
||||
ps aux|grep -v grep|grep -v control|grep "$binfile"|awk '{print $2}'|xargs kill
|
||||
for((i=1;i<=15;i++)); do
|
||||
if [ $(ps aux|grep -v grep|grep -v control|grep "$binfile" -c) -eq 0 ]; then
|
||||
echo "${mod} stopped"
|
||||
return
|
||||
fi
|
||||
sleep 0.2
|
||||
done
|
||||
|
||||
echo "cannot stop $mod"
|
||||
exit 1
|
||||
}
|
||||
|
||||
restart()
|
||||
{
|
||||
mod=$1
|
||||
if [ "x${mod}" = "x" ]; then
|
||||
usage
|
||||
return
|
||||
fi
|
||||
|
||||
if [ "x${mod}" = "xall" ]; then
|
||||
stop_all
|
||||
start_all
|
||||
return
|
||||
fi
|
||||
|
||||
stop $mod
|
||||
start $mod
|
||||
|
||||
status
|
||||
}
|
||||
|
||||
status()
|
||||
{
|
||||
ps aux|grep -v grep|grep "n9e"
|
||||
}
|
||||
|
||||
build_one()
|
||||
{
|
||||
mod=$1
|
||||
echo -n "building ${mod} ... "
|
||||
go build -ldflags "-X main.version=${version}" -o n9e-${mod} src/modules/${mod}/${mod}.go
|
||||
echo "done"
|
||||
}
|
||||
|
||||
build_local_one()
|
||||
{
|
||||
mod=$1
|
||||
echo -n "building ${mod} ... "
|
||||
go build -mod=vendor -ldflags "-X main.version=${version}" -o n9e-${mod} src/modules/${mod}/${mod}.go
|
||||
echo "done"
|
||||
}
|
||||
|
||||
build()
|
||||
{
|
||||
export GO111MODULE=on
|
||||
|
||||
mod=$1
|
||||
if [ "x${mod}" = "x" ]; then
|
||||
build_one server
|
||||
build_one agentd
|
||||
build_one prober
|
||||
return
|
||||
fi
|
||||
|
||||
build_one $mod
|
||||
}
|
||||
|
||||
build_local()
|
||||
{
|
||||
export GO111MODULE=on
|
||||
|
||||
mod=$1
|
||||
if [ "x${mod}" = "x" ]; then
|
||||
build_local_one server
|
||||
build_local_one agentd
|
||||
build_local_one prober
|
||||
return
|
||||
fi
|
||||
|
||||
build_local_one $mod
|
||||
}
|
||||
|
||||
reload()
|
||||
{
|
||||
mod=$1
|
||||
if [ "x${mod}" = "x" ]; then
|
||||
echo "arg: <mod> is necessary"
|
||||
return
|
||||
fi
|
||||
|
||||
build_one $mod
|
||||
restart $mod
|
||||
}
|
||||
|
||||
pack()
|
||||
{
|
||||
clock=$(date +%s)
|
||||
mkdir -p ~/n9e.bak.$clock
|
||||
|
||||
if ls etc/*.local.yml &>/dev/null; then
|
||||
mv etc/*.local.yml ~/n9e.bak.$clock
|
||||
fi
|
||||
|
||||
tar zcvf n9e-${version}.tar.gz script control sql etc n9e-*
|
||||
|
||||
if ls ~/n9e.bak.$clock/*.local.yml &>/dev/null; then
|
||||
mv ~/n9e.bak.$clock/*.local.yml etc/
|
||||
fi
|
||||
|
||||
rm -rf ~/n9e.bak.$clock
|
||||
}
|
||||
|
||||
exec()
|
||||
{
|
||||
|
||||
params=${@:2}
|
||||
|
||||
if [ ${#2} -gt 0 ]; then
|
||||
for mod in $params
|
||||
do
|
||||
mod=${mod#n9e-}
|
||||
$1 $mod
|
||||
if [ "x${mod}" = "xall" ]; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
else
|
||||
echo "todo $1 at "$(date "+%Y-%m-%d %H:%M:%S")
|
||||
$1
|
||||
echo "done $1 at "$(date "+%Y-%m-%d %H:%M:%S")
|
||||
fi
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
exec start ${@:2}
|
||||
;;
|
||||
stop)
|
||||
exec stop ${@:2}
|
||||
;;
|
||||
restart)
|
||||
exec restart ${@:2}
|
||||
;;
|
||||
status)
|
||||
status
|
||||
;;
|
||||
build)
|
||||
exec build ${@:2}
|
||||
;;
|
||||
build_local)
|
||||
exec build_local ${@:2}
|
||||
;;
|
||||
reload)
|
||||
exec reload ${@:2}
|
||||
;;
|
||||
pack)
|
||||
exec pack ${@:2}
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
esac
|
|
@ -1,59 +0,0 @@
|
|||
version: '3.6'
|
||||
services:
|
||||
web:
|
||||
build:
|
||||
dockerfile: Dockerfile
|
||||
context: nginx
|
||||
container_name: nginx-n9e
|
||||
hostname: nginx-n9e
|
||||
ports:
|
||||
- 80:80
|
||||
restart: unless-stopped
|
||||
links:
|
||||
- n9e:n9e
|
||||
|
||||
mysql:
|
||||
image: mysql:5
|
||||
container_name: mysql
|
||||
hostname: mysql
|
||||
ports:
|
||||
- 3306:3306
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: 1234
|
||||
# volumes:
|
||||
# - /usr/local/docker/mysql/data:/var/lib/mysql
|
||||
|
||||
redis:
|
||||
image: redis
|
||||
container_name: redis
|
||||
hostname: redis
|
||||
ports:
|
||||
- 6379:6379
|
||||
|
||||
n9e:
|
||||
build:
|
||||
dockerfile: Dockerfile
|
||||
context: n9e
|
||||
container_name: n9e
|
||||
hostname: n9e
|
||||
ports:
|
||||
- 8000:8000
|
||||
- 8002:8002
|
||||
- 8004:8004
|
||||
- 8005:8005
|
||||
- 8006:8006
|
||||
- 8008:8008
|
||||
- 8009:8009
|
||||
- 8010:8010
|
||||
- 8011:8011
|
||||
- 8012:8012
|
||||
- 8013:8013
|
||||
- 8014:8014
|
||||
- 8015:8015
|
||||
- 2080:2080
|
||||
links:
|
||||
- mysql:mysql
|
||||
- redis:redis
|
||||
depends_on:
|
||||
- mysql
|
||||
- redis
|
|
@ -1,17 +0,0 @@
|
|||
FROM centos:7
|
||||
WORKDIR /home/n9e
|
||||
|
||||
RUN set -ex \
|
||||
&& yum install mysql net-tools wget -y \
|
||||
&& yum clean all \
|
||||
&& rm -rf /var/cache/yum
|
||||
|
||||
ADD http://116.85.64.82/n9e-3.8.0.tar.gz .
|
||||
|
||||
RUN tar xvf n9e-3.8.0.tar.gz \
|
||||
&& sed -i "s/127.0.0.1:6379/redis:6379/g" `grep -rl "127.0.0.1:6379" ./etc/` \
|
||||
&& sed -i 's/127.0.0.1/mysql/g' etc/mysql.yml
|
||||
|
||||
COPY entrpoint.sh .
|
||||
|
||||
ENTRYPOINT ./entrpoint.sh
|
|
@ -1,17 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
mysqlRootPassword=1234
|
||||
|
||||
until mysql -hmysql -u root -p$mysqlRootPassword -e ";" ; do
|
||||
echo "Can't connect mysql, retry"
|
||||
sleep 5
|
||||
done
|
||||
|
||||
mysql -hmysql -uroot -p$mysqlRootPassword < sql/n9e_ams.sql
|
||||
mysql -hmysql -uroot -p$mysqlRootPassword < sql/n9e_hbs.sql
|
||||
mysql -hmysql -uroot -p$mysqlRootPassword < sql/n9e_job.sql
|
||||
mysql -hmysql -uroot -p$mysqlRootPassword < sql/n9e_mon.sql
|
||||
mysql -hmysql -uroot -p$mysqlRootPassword < sql/n9e_rdb.sql
|
||||
|
||||
./control start all
|
||||
sleep infinity
|
|
@ -1,5 +0,0 @@
|
|||
FROM nginx
|
||||
WORKDIR /home/n9e
|
||||
COPY nginx.conf /etc/nginx
|
||||
ADD http://116.85.64.82/pub.tar.gz .
|
||||
RUN tar xvf pub.tar.gz
|
|
@ -1,139 +0,0 @@
|
|||
user root;
|
||||
|
||||
worker_processes auto;
|
||||
worker_cpu_affinity auto;
|
||||
worker_rlimit_nofile 204800;
|
||||
|
||||
error_log /var/log/nginx/error.log;
|
||||
pid /run/nginx.pid;
|
||||
|
||||
include /usr/share/nginx/modules/*.conf;
|
||||
|
||||
events {
|
||||
use epoll;
|
||||
worker_connections 204800;
|
||||
}
|
||||
|
||||
http {
|
||||
log_format main '$server_addr $host $remote_addr [$time_local] $scheme "$request" '
|
||||
'$status $upstream_status $body_bytes_sent $request_time $upstream_addr $upstream_response_time "$http_referer" '
|
||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||
|
||||
access_log /var/log/nginx/access.log main;
|
||||
|
||||
sendfile on;
|
||||
tcp_nopush on;
|
||||
tcp_nodelay on;
|
||||
keepalive_timeout 65;
|
||||
types_hash_max_size 2048;
|
||||
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
include /etc/nginx/conf.d/*.conf;
|
||||
|
||||
|
||||
proxy_connect_timeout 500ms;
|
||||
proxy_send_timeout 1000ms;
|
||||
proxy_read_timeout 3000ms;
|
||||
proxy_buffers 64 8k;
|
||||
proxy_busy_buffers_size 128k;
|
||||
proxy_temp_file_write_size 64k;
|
||||
proxy_redirect off;
|
||||
proxy_next_upstream error invalid_header timeout http_502 http_504;
|
||||
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Real-Port $remote_port;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
|
||||
client_max_body_size 100m;
|
||||
client_body_buffer_size 512k;
|
||||
client_body_timeout 180;
|
||||
client_header_timeout 10;
|
||||
send_timeout 240;
|
||||
|
||||
gzip on;
|
||||
gzip_min_length 1k;
|
||||
gzip_buffers 4 16k;
|
||||
gzip_comp_level 2;
|
||||
gzip_types application/javascript application/x-javascript text/css text/javascript image/jpeg image/gif image/png;
|
||||
gzip_vary off;
|
||||
gzip_disable "MSIE [1-6]\.";
|
||||
|
||||
upstream n9e.rdb {
|
||||
server n9e:8000;
|
||||
keepalive 60;
|
||||
}
|
||||
|
||||
upstream n9e.ams {
|
||||
server n9e:8002;
|
||||
keepalive 60;
|
||||
}
|
||||
|
||||
upstream n9e.job {
|
||||
server n9e:8004;
|
||||
keepalive 60;
|
||||
}
|
||||
|
||||
upstream n9e.monapi {
|
||||
server n9e:8006;
|
||||
keepalive 60;
|
||||
}
|
||||
|
||||
upstream n9e.transfer {
|
||||
server n9e:8008;
|
||||
keepalive 60;
|
||||
}
|
||||
|
||||
upstream n9e.index {
|
||||
server n9e:8012;
|
||||
keepalive 60;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80 default_server;
|
||||
server_name n9e.example.com;
|
||||
root /home/n9e/pub;
|
||||
|
||||
# Load configuration files for the default server block.
|
||||
include /etc/nginx/default.d/*.conf;
|
||||
|
||||
location =/ {
|
||||
rewrite / /mon;
|
||||
}
|
||||
|
||||
location / {
|
||||
try_files $uri /layout/index.html;
|
||||
}
|
||||
|
||||
location ~ .*(.htm|.html|manifest.json)$ {
|
||||
add_header Cache-Control "private, no-store, no-cache, must-revalidate, proxy-revalidate";
|
||||
}
|
||||
|
||||
location /api/rdb {
|
||||
proxy_pass http://n9e.rdb;
|
||||
}
|
||||
|
||||
location /api/ams {
|
||||
proxy_pass http://n9e.ams;
|
||||
}
|
||||
|
||||
location /api/job {
|
||||
proxy_pass http://n9e.job;
|
||||
}
|
||||
|
||||
location /api/mon {
|
||||
proxy_pass http://n9e.monapi;
|
||||
}
|
||||
|
||||
location /api/index {
|
||||
proxy_pass http://n9e.index;
|
||||
}
|
||||
|
||||
location /api/transfer {
|
||||
proxy_pass http://n9e.transfer;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
## 登陆相关
|
||||
|
||||
#### 来源地址限制
|
||||
|
||||
IP地址的获取顺序
|
||||
|
||||
- http header "X-Forwarded-For"
|
||||
- http header "X-Real-Ip"
|
||||
- http request RemoteAddr
|
||||
|
||||
nginx 代理配置客户端地址
|
||||
|
||||
```
|
||||
# https://www.nginx.com/resources/wiki/start/topics/examples/forwarded/
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
```
|
|
@ -1,11 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Nightingale</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>Hello, Nightingale</h1>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -1,50 +0,0 @@
|
|||
# 安装 M3db,ETCD
|
||||
|
||||
下载安装包 [m3db-install.tar.gz](https://s3-gz01.didistatic.com/n9e-pub/tarball/m3db-install.tar.gz)
|
||||
|
||||
|
||||
## 配置
|
||||
#### etcd证书
|
||||
```shell
|
||||
# 修改 ./etcd/certs/config/hosts-etcd
|
||||
# 填写etcd的机器列表
|
||||
|
||||
# 生成证书
|
||||
cd etcd/certs
|
||||
./reinit-root-ca.sh
|
||||
./update-etcd-client-certs.sh
|
||||
./update-etcd-server-certs.sh
|
||||
```
|
||||
|
||||
|
||||
#### m3db 配置
|
||||
```shell
|
||||
# 修改 ./m3db/etc/m3dbnode.yml
|
||||
db:
|
||||
config:
|
||||
service:
|
||||
etcdClusters:
|
||||
- zone: embedded
|
||||
endpoints:
|
||||
- 10.255.0.146:2379 # 这里需要修改 etcd 节点信息
|
||||
- 10.255.0.129:2379
|
||||
```
|
||||
|
||||
|
||||
## 安装部署
|
||||
```shell
|
||||
. ./functions.sh
|
||||
# 设置安装的机器节点,
|
||||
hosts="{node1} {node2} {node3}"
|
||||
# 设置好ssh Public key认证后,设置 publick key 用户名
|
||||
user="dc2-user"
|
||||
|
||||
# 同步文件
|
||||
sync
|
||||
|
||||
# 安装
|
||||
install
|
||||
|
||||
# 检查
|
||||
status
|
||||
```
|
|
@ -1,12 +0,0 @@
|
|||
---
|
||||
server:
|
||||
http: 0.0.0.0:8000
|
||||
rpc: 0.0.0.0:8001
|
||||
addresses:
|
||||
- 127.0.0.1
|
||||
|
||||
prober:
|
||||
http: 0.0.0.0:8023
|
||||
|
||||
agentd:
|
||||
http: 0.0.0.0:2080
|
|
@ -1,90 +0,0 @@
|
|||
logger:
|
||||
dir: logs/agentd
|
||||
level: INFO
|
||||
keepHours: 24
|
||||
|
||||
enable:
|
||||
mon: true
|
||||
job: true
|
||||
report: true
|
||||
metrics: true
|
||||
|
||||
defaultTags:
|
||||
enable: false
|
||||
tags:
|
||||
key1: value1
|
||||
key2: value2
|
||||
|
||||
udp:
|
||||
enable: false
|
||||
listen: :788
|
||||
|
||||
metrics:
|
||||
maxProcs: 1
|
||||
reportIntervalMs: 10
|
||||
reportTimeoutMs: 2000
|
||||
reportPacketSize: 100
|
||||
sendToInfoFile: false
|
||||
|
||||
job:
|
||||
metadir: ./meta
|
||||
interval: 2
|
||||
|
||||
report:
|
||||
# 调用ams的接口上报数据,需要ams的token
|
||||
token: ams-builtin-token
|
||||
|
||||
# 上报周期,单位是秒
|
||||
interval: 10
|
||||
|
||||
# physical:物理机,virtual:虚拟机,container:容器,switch:交换机
|
||||
cate: physical
|
||||
|
||||
# 使用哪个字段作为唯一KEY,即作为where条件更新对应记录,一般使用sn或ip
|
||||
uniqkey: ip
|
||||
|
||||
# 如果是虚拟机,应该是获取uuid
|
||||
# curl -s http://169.254.169.254/a/meta-data/instance-id
|
||||
sn: dmidecode -s system-serial-number | tail -n 1
|
||||
|
||||
fields:
|
||||
cpu: cat /proc/cpuinfo | grep processor | wc -l
|
||||
mem: cat /proc/meminfo | grep MemTotal | awk '{printf "%.1fGi", $2/1024/1024}'
|
||||
disk: df -m | grep '/dev/' | grep -v '/var/lib' | grep -v tmpfs | awk '{sum += $2};END{printf "%.1fGi", sum/1024}'
|
||||
|
||||
sys:
|
||||
# timeout in ms
|
||||
# interval in second
|
||||
timeout: 5000
|
||||
interval: 30
|
||||
ifacePrefix:
|
||||
- eth
|
||||
- em
|
||||
- ens
|
||||
|
||||
# 磁盘采集
|
||||
mountCollect:
|
||||
# 正则匹配需要采集的挂载卷类型
|
||||
typePrefix: "^(btrfs|ext2|ext3|ext4|jfs|reiser|xfs|ffs|ufs|jfs|jfs2|vxfs|hfs|ntfs|fat32|zfs|nfs)$"
|
||||
# 忽略采集以下面开头的挂载目录
|
||||
ignorePrefix:
|
||||
- /var/lib
|
||||
- /run
|
||||
- /boot
|
||||
# 仍然采集ignorePrefix中的例外的挂载目录(填写全路径)
|
||||
exclude: []
|
||||
|
||||
ignoreMetrics:
|
||||
- cpu.core.idle
|
||||
- cpu.core.util
|
||||
- cpu.core.sys
|
||||
- cpu.core.user
|
||||
- cpu.core.nice
|
||||
- cpu.core.guest
|
||||
- cpu.core.irq
|
||||
- cpu.core.softirq
|
||||
- cpu.core.iowait
|
||||
- cpu.core.steal
|
||||
|
||||
#ntpServers:
|
||||
# - ntp1.aliyun.com
|
|
@ -1,752 +0,0 @@
|
|||
[
|
||||
{
|
||||
"name": "timewait状态tcp连接超过2万",
|
||||
"category": 1,
|
||||
"alert_dur": 60,
|
||||
"recovery_dur": 0,
|
||||
"recovery_notify": 1,
|
||||
"enable_stime": "00:00",
|
||||
"enable_etime": "23:59",
|
||||
"priority": 3,
|
||||
"callback": "",
|
||||
"need_upgrade": 0,
|
||||
"runbook": "",
|
||||
"excl_nid": null,
|
||||
"nids": null,
|
||||
"exprs": [
|
||||
{
|
||||
"eopt": ">",
|
||||
"func": "all",
|
||||
"metric": "net.sockets.tcp.timewait",
|
||||
"params": [],
|
||||
"threshold": 20000
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"enable_days_of_week": [
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6
|
||||
],
|
||||
"converge": [
|
||||
36000,
|
||||
1
|
||||
],
|
||||
"notify_group": [],
|
||||
"notify_user": [],
|
||||
"leaf_nids": null,
|
||||
"endpoints": null,
|
||||
"alert_upgrade": {
|
||||
"users": [],
|
||||
"groups": [],
|
||||
"duration": 60,
|
||||
"level": 1
|
||||
},
|
||||
"judge_instance": "",
|
||||
"work_groups": null
|
||||
},
|
||||
{
|
||||
"name": "内存利用率大于75%",
|
||||
"category": 1,
|
||||
"alert_dur": 60,
|
||||
"recovery_dur": 0,
|
||||
"recovery_notify": 1,
|
||||
"enable_stime": "00:00",
|
||||
"enable_etime": "23:59",
|
||||
"priority": 2,
|
||||
"callback": "",
|
||||
"need_upgrade": 0,
|
||||
"runbook": "",
|
||||
"excl_nid": null,
|
||||
"nids": null,
|
||||
"exprs": [
|
||||
{
|
||||
"eopt": ">",
|
||||
"func": "all",
|
||||
"metric": "mem.bytes.used.percent",
|
||||
"params": [],
|
||||
"threshold": 75
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"enable_days_of_week": [
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6
|
||||
],
|
||||
"converge": [
|
||||
36000,
|
||||
1
|
||||
],
|
||||
"notify_group": null,
|
||||
"notify_user": null,
|
||||
"leaf_nids": null,
|
||||
"endpoints": null,
|
||||
"alert_upgrade": {
|
||||
"users": [],
|
||||
"groups": [],
|
||||
"duration": 60,
|
||||
"level": 1
|
||||
},
|
||||
"judge_instance": "",
|
||||
"work_groups": null
|
||||
},
|
||||
{
|
||||
"name": "机器loadavg大于16",
|
||||
"category": 1,
|
||||
"alert_dur": 60,
|
||||
"recovery_dur": 0,
|
||||
"recovery_notify": 1,
|
||||
"enable_stime": "00:00",
|
||||
"enable_etime": "23:59",
|
||||
"priority": 2,
|
||||
"callback": "",
|
||||
"need_upgrade": 0,
|
||||
"runbook": "",
|
||||
"excl_nid": null,
|
||||
"nids": null,
|
||||
"exprs": [
|
||||
{
|
||||
"eopt": ">",
|
||||
"func": "all",
|
||||
"metric": "cpu.loadavg.1",
|
||||
"params": [],
|
||||
"threshold": 16
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"enable_days_of_week": [
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6
|
||||
],
|
||||
"converge": [
|
||||
36000,
|
||||
1
|
||||
],
|
||||
"notify_group": null,
|
||||
"notify_user": null,
|
||||
"leaf_nids": null,
|
||||
"endpoints": null,
|
||||
"alert_upgrade": {
|
||||
"users": [],
|
||||
"groups": [],
|
||||
"duration": 60,
|
||||
"level": 1
|
||||
},
|
||||
"judge_instance": "",
|
||||
"work_groups": null
|
||||
},
|
||||
{
|
||||
"name": "某磁盘无法正常读写",
|
||||
"category": 1,
|
||||
"alert_dur": 60,
|
||||
"recovery_dur": 0,
|
||||
"recovery_notify": 1,
|
||||
"enable_stime": "00:00",
|
||||
"enable_etime": "23:59",
|
||||
"priority": 1,
|
||||
"callback": "",
|
||||
"need_upgrade": 0,
|
||||
"runbook": "",
|
||||
"excl_nid": null,
|
||||
"nids": null,
|
||||
"exprs": [
|
||||
{
|
||||
"eopt": ">",
|
||||
"func": "all",
|
||||
"metric": "disk.rw.error",
|
||||
"params": [],
|
||||
"threshold": 0
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"enable_days_of_week": [
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6
|
||||
],
|
||||
"converge": [
|
||||
36000,
|
||||
1
|
||||
],
|
||||
"notify_group": null,
|
||||
"notify_user": null,
|
||||
"leaf_nids": null,
|
||||
"endpoints": null,
|
||||
"alert_upgrade": {
|
||||
"users": [],
|
||||
"groups": [],
|
||||
"duration": 60,
|
||||
"level": 1
|
||||
},
|
||||
"judge_instance": "",
|
||||
"work_groups": null
|
||||
},
|
||||
{
|
||||
"name": "监控agent失联",
|
||||
"category": 1,
|
||||
"alert_dur": 60,
|
||||
"recovery_dur": 0,
|
||||
"recovery_notify": 1,
|
||||
"enable_stime": "00:00",
|
||||
"enable_etime": "23:59",
|
||||
"priority": 1,
|
||||
"callback": "",
|
||||
"need_upgrade": 0,
|
||||
"runbook": "",
|
||||
"excl_nid": null,
|
||||
"nids": null,
|
||||
"exprs": [
|
||||
{
|
||||
"eopt": "=",
|
||||
"func": "nodata",
|
||||
"metric": "proc.agent.alive",
|
||||
"params": [],
|
||||
"threshold": 0
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"enable_days_of_week": [
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6
|
||||
],
|
||||
"converge": [
|
||||
36000,
|
||||
1
|
||||
],
|
||||
"notify_group": null,
|
||||
"notify_user": null,
|
||||
"leaf_nids": null,
|
||||
"endpoints": null,
|
||||
"alert_upgrade": {
|
||||
"users": [],
|
||||
"groups": [],
|
||||
"duration": 60,
|
||||
"level": 1
|
||||
},
|
||||
"judge_instance": "",
|
||||
"work_groups": null
|
||||
},
|
||||
{
|
||||
"name": "磁盘利用率达到85%",
|
||||
"category": 1,
|
||||
"alert_dur": 60,
|
||||
"recovery_dur": 0,
|
||||
"recovery_notify": 1,
|
||||
"enable_stime": "00:00",
|
||||
"enable_etime": "23:59",
|
||||
"priority": 3,
|
||||
"callback": "",
|
||||
"need_upgrade": 0,
|
||||
"runbook": "",
|
||||
"excl_nid": null,
|
||||
"nids": null,
|
||||
"exprs": [
|
||||
{
|
||||
"eopt": ">",
|
||||
"func": "all",
|
||||
"metric": "disk.bytes.used.percent",
|
||||
"params": [],
|
||||
"threshold": 85
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"enable_days_of_week": [
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6
|
||||
],
|
||||
"converge": [
|
||||
36000,
|
||||
1
|
||||
],
|
||||
"notify_group": null,
|
||||
"notify_user": null,
|
||||
"leaf_nids": null,
|
||||
"endpoints": null,
|
||||
"alert_upgrade": {
|
||||
"users": [],
|
||||
"groups": [],
|
||||
"duration": 60,
|
||||
"level": 1
|
||||
},
|
||||
"judge_instance": "",
|
||||
"work_groups": null
|
||||
},
|
||||
{
|
||||
"name": "磁盘利用率达到88%",
|
||||
"category": 1,
|
||||
"alert_dur": 60,
|
||||
"recovery_dur": 0,
|
||||
"recovery_notify": 1,
|
||||
"enable_stime": "00:00",
|
||||
"enable_etime": "23:59",
|
||||
"priority": 2,
|
||||
"callback": "",
|
||||
"need_upgrade": 0,
|
||||
"runbook": "",
|
||||
"excl_nid": null,
|
||||
"nids": null,
|
||||
"exprs": [
|
||||
{
|
||||
"eopt": ">",
|
||||
"func": "all",
|
||||
"metric": "disk.bytes.used.percent",
|
||||
"params": [],
|
||||
"threshold": 88
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"enable_days_of_week": [
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6
|
||||
],
|
||||
"converge": [
|
||||
36000,
|
||||
1
|
||||
],
|
||||
"notify_group": null,
|
||||
"notify_user": null,
|
||||
"leaf_nids": null,
|
||||
"endpoints": null,
|
||||
"alert_upgrade": {
|
||||
"users": [],
|
||||
"groups": [],
|
||||
"duration": 60,
|
||||
"level": 1
|
||||
},
|
||||
"judge_instance": "",
|
||||
"work_groups": null
|
||||
},
|
||||
{
|
||||
"name": "磁盘利用率达到92%",
|
||||
"category": 1,
|
||||
"alert_dur": 60,
|
||||
"recovery_dur": 0,
|
||||
"recovery_notify": 1,
|
||||
"enable_stime": "00:00",
|
||||
"enable_etime": "23:59",
|
||||
"priority": 1,
|
||||
"callback": "",
|
||||
"need_upgrade": 0,
|
||||
"runbook": "",
|
||||
"excl_nid": null,
|
||||
"nids": null,
|
||||
"exprs": [
|
||||
{
|
||||
"eopt": ">",
|
||||
"func": "all",
|
||||
"metric": "disk.bytes.used.percent",
|
||||
"params": [],
|
||||
"threshold": 92
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"enable_days_of_week": [
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6
|
||||
],
|
||||
"converge": [
|
||||
36000,
|
||||
1
|
||||
],
|
||||
"notify_group": null,
|
||||
"notify_user": null,
|
||||
"leaf_nids": null,
|
||||
"endpoints": null,
|
||||
"alert_upgrade": {
|
||||
"users": [],
|
||||
"groups": [],
|
||||
"duration": 60,
|
||||
"level": 1
|
||||
},
|
||||
"judge_instance": "",
|
||||
"work_groups": null
|
||||
},
|
||||
{
|
||||
"name": "端口挂了",
|
||||
"category": 1,
|
||||
"alert_dur": 60,
|
||||
"recovery_dur": 0,
|
||||
"recovery_notify": 1,
|
||||
"enable_stime": "00:00",
|
||||
"enable_etime": "23:59",
|
||||
"priority": 2,
|
||||
"callback": "",
|
||||
"need_upgrade": 0,
|
||||
"runbook": "",
|
||||
"excl_nid": null,
|
||||
"nids": null,
|
||||
"exprs": [
|
||||
{
|
||||
"eopt": "!=",
|
||||
"func": "all",
|
||||
"metric": "proc.port.listen",
|
||||
"params": [],
|
||||
"threshold": 1
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"enable_days_of_week": [
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6
|
||||
],
|
||||
"converge": [
|
||||
36000,
|
||||
1
|
||||
],
|
||||
"notify_group": null,
|
||||
"notify_user": null,
|
||||
"leaf_nids": null,
|
||||
"endpoints": null,
|
||||
"alert_upgrade": {
|
||||
"users": [],
|
||||
"groups": [],
|
||||
"duration": 60,
|
||||
"level": 1
|
||||
},
|
||||
"judge_instance": "",
|
||||
"work_groups": null
|
||||
},
|
||||
{
|
||||
"name": "网卡入方向丢包",
|
||||
"category": 1,
|
||||
"alert_dur": 60,
|
||||
"recovery_dur": 0,
|
||||
"recovery_notify": 1,
|
||||
"enable_stime": "00:00",
|
||||
"enable_etime": "23:59",
|
||||
"priority": 2,
|
||||
"callback": "",
|
||||
"need_upgrade": 0,
|
||||
"runbook": "",
|
||||
"excl_nid": null,
|
||||
"nids": null,
|
||||
"exprs": [
|
||||
{
|
||||
"eopt": ">",
|
||||
"func": "all",
|
||||
"metric": "net.in.dropped",
|
||||
"params": [],
|
||||
"threshold": 3
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"enable_days_of_week": [
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6
|
||||
],
|
||||
"converge": [
|
||||
36000,
|
||||
1
|
||||
],
|
||||
"notify_group": null,
|
||||
"notify_user": null,
|
||||
"leaf_nids": null,
|
||||
"endpoints": null,
|
||||
"alert_upgrade": {
|
||||
"users": [],
|
||||
"groups": [],
|
||||
"duration": 60,
|
||||
"level": 1
|
||||
},
|
||||
"judge_instance": "",
|
||||
"work_groups": null
|
||||
},
|
||||
{
|
||||
"name": "网卡入方向错包",
|
||||
"category": 1,
|
||||
"alert_dur": 60,
|
||||
"recovery_dur": 0,
|
||||
"recovery_notify": 1,
|
||||
"enable_stime": "00:00",
|
||||
"enable_etime": "23:59",
|
||||
"priority": 2,
|
||||
"callback": "",
|
||||
"need_upgrade": 0,
|
||||
"runbook": "",
|
||||
"excl_nid": null,
|
||||
"nids": null,
|
||||
"exprs": [
|
||||
{
|
||||
"eopt": ">",
|
||||
"func": "all",
|
||||
"metric": "net.in.errs",
|
||||
"params": [],
|
||||
"threshold": 3
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"enable_days_of_week": [
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6
|
||||
],
|
||||
"converge": [
|
||||
36000,
|
||||
1
|
||||
],
|
||||
"notify_group": null,
|
||||
"notify_user": null,
|
||||
"leaf_nids": null,
|
||||
"endpoints": null,
|
||||
"alert_upgrade": {
|
||||
"users": [],
|
||||
"groups": [],
|
||||
"duration": 60,
|
||||
"level": 1
|
||||
},
|
||||
"judge_instance": "",
|
||||
"work_groups": null
|
||||
},
|
||||
{
|
||||
"name": "网卡出方向丢包",
|
||||
"category": 1,
|
||||
"alert_dur": 60,
|
||||
"recovery_dur": 0,
|
||||
"recovery_notify": 1,
|
||||
"enable_stime": "00:00",
|
||||
"enable_etime": "23:59",
|
||||
"priority": 2,
|
||||
"callback": "",
|
||||
"need_upgrade": 0,
|
||||
"runbook": "",
|
||||
"excl_nid": null,
|
||||
"nids": null,
|
||||
"exprs": [
|
||||
{
|
||||
"eopt": ">",
|
||||
"func": "all",
|
||||
"metric": "net.out.dropped",
|
||||
"params": [],
|
||||
"threshold": 3
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"enable_days_of_week": [
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6
|
||||
],
|
||||
"converge": [
|
||||
36000,
|
||||
1
|
||||
],
|
||||
"notify_group": null,
|
||||
"notify_user": null,
|
||||
"leaf_nids": null,
|
||||
"endpoints": null,
|
||||
"alert_upgrade": {
|
||||
"users": [],
|
||||
"groups": [],
|
||||
"duration": 60,
|
||||
"level": 1
|
||||
},
|
||||
"judge_instance": "",
|
||||
"work_groups": null
|
||||
},
|
||||
{
|
||||
"name": "网卡出方向错包",
|
||||
"category": 1,
|
||||
"alert_dur": 60,
|
||||
"recovery_dur": 0,
|
||||
"recovery_notify": 1,
|
||||
"enable_stime": "00:00",
|
||||
"enable_etime": "23:59",
|
||||
"priority": 2,
|
||||
"callback": "",
|
||||
"need_upgrade": 0,
|
||||
"runbook": "",
|
||||
"excl_nid": null,
|
||||
"nids": null,
|
||||
"exprs": [
|
||||
{
|
||||
"eopt": ">",
|
||||
"func": "all",
|
||||
"metric": "net.out.errs",
|
||||
"params": [],
|
||||
"threshold": 3
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"enable_days_of_week": [
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6
|
||||
],
|
||||
"converge": [
|
||||
36000,
|
||||
1
|
||||
],
|
||||
"notify_group": null,
|
||||
"notify_user": null,
|
||||
"leaf_nids": null,
|
||||
"endpoints": null,
|
||||
"alert_upgrade": {
|
||||
"users": [],
|
||||
"groups": [],
|
||||
"duration": 60,
|
||||
"level": 1
|
||||
},
|
||||
"judge_instance": "",
|
||||
"work_groups": null
|
||||
},
|
||||
{
|
||||
"name": "进程总数超过3000",
|
||||
"category": 1,
|
||||
"alert_dur": 60,
|
||||
"recovery_dur": 0,
|
||||
"recovery_notify": 1,
|
||||
"enable_stime": "00:00",
|
||||
"enable_etime": "23:59",
|
||||
"priority": 1,
|
||||
"callback": "",
|
||||
"need_upgrade": 0,
|
||||
"runbook": "",
|
||||
"excl_nid": null,
|
||||
"nids": null,
|
||||
"exprs": [
|
||||
{
|
||||
"eopt": ">",
|
||||
"func": "all",
|
||||
"metric": "sys.ps.process.total",
|
||||
"params": [],
|
||||
"threshold": 3000
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"enable_days_of_week": [
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6
|
||||
],
|
||||
"converge": [
|
||||
36000,
|
||||
1
|
||||
],
|
||||
"notify_group": null,
|
||||
"notify_user": null,
|
||||
"leaf_nids": null,
|
||||
"endpoints": null,
|
||||
"alert_upgrade": {
|
||||
"users": [],
|
||||
"groups": [],
|
||||
"duration": 60,
|
||||
"level": 1
|
||||
},
|
||||
"judge_instance": "",
|
||||
"work_groups": null
|
||||
},
|
||||
{
|
||||
"name": "进程挂了",
|
||||
"category": 1,
|
||||
"alert_dur": 60,
|
||||
"recovery_dur": 0,
|
||||
"recovery_notify": 1,
|
||||
"enable_stime": "00:00",
|
||||
"enable_etime": "23:59",
|
||||
"priority": 2,
|
||||
"callback": "",
|
||||
"need_upgrade": 0,
|
||||
"runbook": "",
|
||||
"excl_nid": null,
|
||||
"nids": null,
|
||||
"exprs": [
|
||||
{
|
||||
"eopt": "<",
|
||||
"func": "all",
|
||||
"metric": "proc.num",
|
||||
"params": [],
|
||||
"threshold": 1
|
||||
}
|
||||
],
|
||||
"tags": [],
|
||||
"enable_days_of_week": [
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6
|
||||
],
|
||||
"converge": [
|
||||
36000,
|
||||
1
|
||||
],
|
||||
"notify_group": null,
|
||||
"notify_user": null,
|
||||
"leaf_nids": null,
|
||||
"endpoints": null,
|
||||
"alert_upgrade": {
|
||||
"users": [],
|
||||
"groups": [],
|
||||
"duration": 60,
|
||||
"level": 1
|
||||
},
|
||||
"judge_instance": "",
|
||||
"work_groups": null
|
||||
}
|
||||
]
|
20
etc/gop.yml
20
etc/gop.yml
|
@ -1,20 +0,0 @@
|
|||
- system: 资产管理系统
|
||||
groups:
|
||||
- title: 主机设备
|
||||
ops:
|
||||
- en: ams_host_mgr_menu
|
||||
cn: 主机设备管理菜单展示
|
||||
- en: ams_host_delete
|
||||
cn: 主机设备删除
|
||||
- en: ams_host_modify
|
||||
cn: 主机设备信息修改
|
||||
- en: ams_host_field_mgr_menu
|
||||
cn: 主机设备扩展字段菜单展示
|
||||
- en: ams_host_field_mgr
|
||||
cn: 主机设备扩展字段管理
|
||||
# - title: 网络设备
|
||||
# ops:
|
||||
# - en: ams_netware_mgr_menu
|
||||
# cn: 网络设备管理菜单
|
||||
# - en: ams_netware_modify
|
||||
# cn: 网络设备信息修改
|
|
@ -1,9 +0,0 @@
|
|||
# for heartbeat, connected by other modules
|
||||
ip:
|
||||
specify: ""
|
||||
shell: ifconfig `route|grep '^default'|awk '{print $NF}'`|grep inet|awk '{print $2}'|head -n 1|awk -F':' '{print $NF}'
|
||||
|
||||
# as identity. equals to endpoint. used by agentd, prober, server
|
||||
ident:
|
||||
specify: ""
|
||||
shell: ifconfig `route|grep '^default'|awk '{print $NF}'`|grep inet|awk '{print $2}'|head -n 1|awk -F':' '{print $NF}'
|
86
etc/lop.yml
86
etc/lop.yml
|
@ -1,86 +0,0 @@
|
|||
- system: 用户资源库
|
||||
groups:
|
||||
- title: 人员授权
|
||||
ops:
|
||||
- en: rdb_perm_grant
|
||||
cn: 权限分配
|
||||
- title: 节点类操作
|
||||
ops:
|
||||
- en: rdb_node_create
|
||||
cn: 创建节点
|
||||
- en: rdb_node_modify
|
||||
cn: 修改节点
|
||||
- en: rdb_node_delete
|
||||
cn: 删除节点
|
||||
- title: 资源类操作
|
||||
ops:
|
||||
- en: rdb_resource_view
|
||||
cn: 资源信息查看
|
||||
- en: rdb_resource_bind
|
||||
cn: 资源挂载节点
|
||||
- en: rdb_resource_unbind
|
||||
cn: 资源解挂节点
|
||||
- en: rdb_resource_modify
|
||||
cn: 资源信息修改
|
||||
- system: 任务执行中心
|
||||
groups:
|
||||
- title: 任务模板相关
|
||||
ops:
|
||||
- en: job_tpl_view
|
||||
cn: 查看任务模板
|
||||
- en: job_tpl_create
|
||||
cn: 创建任务模板
|
||||
- en: job_tpl_modify
|
||||
cn: 修改任务模板
|
||||
- en: job_tpl_delete
|
||||
cn: 删除任务模板
|
||||
- title: 任务执行相关
|
||||
ops:
|
||||
- en: task_run_use_root_account
|
||||
cn: 使用root账号运行脚本
|
||||
- en: task_run_use_gene_account
|
||||
cn: 使用普通账号运行脚本
|
||||
- system: 监控告警系统
|
||||
groups:
|
||||
- title: 告警策略
|
||||
ops:
|
||||
- en: mon_stra_create
|
||||
cn: 创建告警策略
|
||||
- en: mon_stra_modify
|
||||
cn: 修改告警策略
|
||||
- en: mon_stra_delete
|
||||
cn: 删除告警策略
|
||||
- title: 告警屏蔽
|
||||
ops:
|
||||
- en: mon_maskconf_create
|
||||
cn: 创建告警屏蔽
|
||||
- en: mon_maskconf_modify
|
||||
cn: 修改告警屏蔽
|
||||
- en: mon_maskconf_delete
|
||||
cn: 删除告警屏蔽
|
||||
- title: 采集策略
|
||||
ops:
|
||||
- en: mon_collect_create
|
||||
cn: 创建采集策略
|
||||
- en: mon_collect_modify
|
||||
cn: 修改采集策略
|
||||
- en: mon_collect_delete
|
||||
cn: 删除采集策略
|
||||
- title: 大盘操作
|
||||
ops:
|
||||
- en: mon_screen_create
|
||||
cn: 创建监控大盘
|
||||
- en: mon_screen_modify
|
||||
cn: 修改监控大盘
|
||||
- en: mon_screen_delete
|
||||
cn: 删除监控大盘
|
||||
- en: mon_screen_view
|
||||
cn: 查看监控大盘
|
||||
# - title: 指标计算
|
||||
# ops:
|
||||
# - en: mon_aggr_write
|
||||
# cn: 指标计算配置权限
|
||||
- title: 告警历史
|
||||
ops:
|
||||
- en: mon_event_write
|
||||
cn: 告警历史认领、忽略
|
|
@ -1,26 +0,0 @@
|
|||
---
|
||||
rdb:
|
||||
addr: "root:1234@tcp(127.0.0.1:3306)/n9e_rdb?charset=utf8&parseTime=True&loc=Asia%2FShanghai"
|
||||
max: 128
|
||||
idle: 16
|
||||
debug: false
|
||||
ams:
|
||||
addr: "root:1234@tcp(127.0.0.1:3306)/n9e_ams?charset=utf8&parseTime=True&loc=Asia%2FShanghai"
|
||||
max: 128
|
||||
idle: 16
|
||||
debug: false
|
||||
job:
|
||||
addr: "root:1234@tcp(127.0.0.1:3306)/n9e_job?charset=utf8&parseTime=True&loc=Asia%2FShanghai"
|
||||
max: 128
|
||||
idle: 16
|
||||
debug: false
|
||||
mon:
|
||||
addr: "root:1234@tcp(127.0.0.1:3306)/n9e_mon?charset=utf8&parseTime=True&loc=Asia%2FShanghai"
|
||||
max: 128
|
||||
idle: 16
|
||||
debug: false
|
||||
hbs:
|
||||
addr: "root:1234@tcp(127.0.0.1:3306)/n9e_hbs?charset=utf8&parseTime=True&loc=Asia%2FShanghai"
|
||||
max: 128
|
||||
idle: 16
|
||||
debug: false
|
119
etc/nginx.conf
119
etc/nginx.conf
|
@ -1,119 +0,0 @@
|
|||
user root;
|
||||
|
||||
worker_processes auto;
|
||||
worker_cpu_affinity auto;
|
||||
worker_rlimit_nofile 204800;
|
||||
|
||||
error_log /var/log/nginx/error.log;
|
||||
pid /run/nginx.pid;
|
||||
|
||||
include /usr/share/nginx/modules/*.conf;
|
||||
|
||||
events {
|
||||
use epoll;
|
||||
worker_connections 204800;
|
||||
}
|
||||
|
||||
http {
|
||||
log_format main '$server_addr $host $remote_addr [$time_local] $scheme "$request" '
|
||||
'$status $upstream_status $body_bytes_sent $request_time $upstream_addr $upstream_response_time "$http_referer" '
|
||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||
|
||||
access_log /var/log/nginx/access.log main;
|
||||
|
||||
sendfile on;
|
||||
tcp_nopush on;
|
||||
tcp_nodelay on;
|
||||
keepalive_timeout 65;
|
||||
types_hash_max_size 2048;
|
||||
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
include /etc/nginx/conf.d/*.conf;
|
||||
|
||||
|
||||
proxy_connect_timeout 500ms;
|
||||
proxy_send_timeout 1000ms;
|
||||
proxy_read_timeout 3000ms;
|
||||
proxy_buffers 64 8k;
|
||||
proxy_busy_buffers_size 128k;
|
||||
proxy_temp_file_write_size 64k;
|
||||
proxy_redirect off;
|
||||
proxy_next_upstream error invalid_header timeout http_502 http_504;
|
||||
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Real-Port $remote_port;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
|
||||
client_max_body_size 100m;
|
||||
client_body_buffer_size 512k;
|
||||
client_body_timeout 180;
|
||||
client_header_timeout 10;
|
||||
send_timeout 240;
|
||||
|
||||
gzip on;
|
||||
gzip_min_length 1k;
|
||||
gzip_buffers 4 16k;
|
||||
gzip_comp_level 2;
|
||||
gzip_types application/javascript application/x-javascript text/css text/javascript image/jpeg image/gif image/png;
|
||||
gzip_vary off;
|
||||
gzip_disable "MSIE [1-6]\.";
|
||||
|
||||
upstream n9e.server {
|
||||
server 127.0.0.1:8000;
|
||||
keepalive 60;
|
||||
}
|
||||
|
||||
upstream n9e.index {
|
||||
server 127.0.0.1:8012;
|
||||
keepalive 60;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80 default_server;
|
||||
server_name localhost;
|
||||
root /home/n9e/pub;
|
||||
|
||||
# Load configuration files for the default server block.
|
||||
include /etc/nginx/default.d/*.conf;
|
||||
|
||||
location =/ {
|
||||
rewrite / /mon;
|
||||
}
|
||||
|
||||
location / {
|
||||
try_files $uri /layout/index.html;
|
||||
}
|
||||
|
||||
location ~ .*(.htm|.html|.json)$ {
|
||||
add_header Cache-Control "private, no-store, no-cache, must-revalidate, proxy-revalidate";
|
||||
}
|
||||
|
||||
location /api/rdb {
|
||||
proxy_pass http://n9e.server;
|
||||
}
|
||||
|
||||
location /api/ams {
|
||||
proxy_pass http://n9e.server;
|
||||
}
|
||||
|
||||
location /api/job {
|
||||
proxy_pass http://n9e.server;
|
||||
}
|
||||
|
||||
location /api/mon {
|
||||
proxy_pass http://n9e.server;
|
||||
}
|
||||
|
||||
location /api/index {
|
||||
proxy_pass http://n9e.server;
|
||||
}
|
||||
|
||||
location /api/transfer {
|
||||
proxy_pass http://n9e.server;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
mode: whitelist # whitelist(default),all
|
||||
metrics:
|
||||
- name: dns_query_query_time_ms
|
||||
- name: dns_query_result_code
|
||||
- name: dns_query_rcode_value
|
|
@ -1 +0,0 @@
|
|||
mode: all # whitelist(default),all
|
|
@ -1,9 +0,0 @@
|
|||
mode: whitelist # whitelist(default),all
|
||||
metrics:
|
||||
- name: github_repository_forks
|
||||
- name: github_repository_networks
|
||||
- name: github_repository_open_issues
|
||||
- name: github_repository_size
|
||||
- name: github_repository_stars
|
||||
- name: github_repository_subscribers
|
||||
- name: github_repository_watchers
|
|
@ -1,8 +0,0 @@
|
|||
mode: whitelist # whitelist(default),all
|
||||
metrics:
|
||||
- name: http_response_http_response_code
|
||||
- name: http_response_content_length
|
||||
- name: http_response_response_string_match
|
||||
- name: http_response_response_status_code_match
|
||||
- name: http_response_result_code
|
||||
- name: http_response_response_time
|
|
@ -1,183 +0,0 @@
|
|||
mode: whitelist # whitelist(default),all
|
||||
|
||||
metrics:
|
||||
- name: mongodb_assert_msg
|
||||
type: COUNTER
|
||||
- name: mongodb_assert_regular
|
||||
type: COUNTER
|
||||
- name: mongodb_assert_rollovers
|
||||
type: COUNTER
|
||||
- name: mongodb_assert_user
|
||||
type: COUNTER
|
||||
- name: mongodb_assert_warning
|
||||
type: COUNTER
|
||||
- name: mongodb_commands
|
||||
type: COUNTER
|
||||
- name: mongodb_count_command_failed
|
||||
type: COUNTER
|
||||
- name: mongodb_count_command_total
|
||||
type: COUNTER
|
||||
- name: mongodb_connections_available
|
||||
- name: mongodb_connections_current
|
||||
- name: mongodb_connections_total_created
|
||||
type: COUNTER
|
||||
|
||||
trash:
|
||||
- name: mongodb_active_reads
|
||||
type: COUNTER
|
||||
- name: mongodb_active_writes
|
||||
type: COUNTER
|
||||
- name: mongodb_aggregate_command_failed
|
||||
type: COUNTER
|
||||
- name: mongodb_aggregate_command_total
|
||||
type: COUNTER
|
||||
- name: mongodb_available_reads
|
||||
- name: mongodb_available_writes
|
||||
- name: mongodb_col_stats_avg_obj_size
|
||||
- name: mongodb_col_stats_count
|
||||
- name: mongodb_col_stats_ok
|
||||
- name: mongodb_col_stats_size
|
||||
- name: mongodb_col_stats_storage_size
|
||||
- name: mongodb_col_stats_total_index_size
|
||||
- name: mongodb_commands_per_sec
|
||||
- name: mongodb_cursor_no_timeout
|
||||
- name: mongodb_cursor_no_timeout_count
|
||||
- name: mongodb_cursor_pinned
|
||||
- name: mongodb_cursor_pinned_count
|
||||
- name: mongodb_cursor_timed_out
|
||||
- name: mongodb_cursor_timed_out_count
|
||||
- name: mongodb_cursor_total
|
||||
- name: mongodb_cursor_total_count
|
||||
- name: mongodb_db_stats_avg_obj_size
|
||||
- name: mongodb_db_stats_collections
|
||||
- name: mongodb_db_stats_data_size
|
||||
- name: mongodb_db_stats_index_size
|
||||
- name: mongodb_db_stats_indexes
|
||||
- name: mongodb_db_stats_num_extents
|
||||
- name: mongodb_db_stats_objects
|
||||
- name: mongodb_db_stats_ok
|
||||
- name: mongodb_db_stats_storage_size
|
||||
- name: mongodb_delete_command_failed
|
||||
type: COUNTER
|
||||
- name: mongodb_delete_command_total
|
||||
type: COUNTER
|
||||
- name: mongodb_deletes
|
||||
- name: mongodb_deletes_per_sec
|
||||
- name: mongodb_distinct_command_failed
|
||||
type: COUNTER
|
||||
- name: mongodb_distinct_command_total
|
||||
type: COUNTER
|
||||
- name: mongodb_document_deleted
|
||||
- name: mongodb_document_inserted
|
||||
- name: mongodb_document_returned
|
||||
- name: mongodb_document_updated
|
||||
- name: mongodb_find_and_modify_command_failed
|
||||
type: COUNTER
|
||||
- name: mongodb_find_and_modify_command_total
|
||||
type: COUNTER
|
||||
- name: mongodb_find_command_failed
|
||||
type: COUNTER
|
||||
- name: mongodb_find_command_total
|
||||
type: COUNTER
|
||||
- name: mongodb_flushes
|
||||
type: COUNTER
|
||||
- name: mongodb_flushes_per_sec
|
||||
- name: mongodb_flushes_total_time_ns
|
||||
type: COUNTER
|
||||
- name: mongodb_get_more_command_failed
|
||||
type: COUNTER
|
||||
- name: mongodb_get_more_command_total
|
||||
type: COUNTER
|
||||
- name: mongodb_getmores
|
||||
- name: mongodb_getmores_per_sec
|
||||
- name: mongodb_insert_command_failed
|
||||
type: COUNTER
|
||||
- name: mongodb_insert_command_total
|
||||
type: COUNTER
|
||||
- name: mongodb_inserts
|
||||
- name: mongodb_inserts_per_sec
|
||||
- name: mongodb_jumbo_chunks
|
||||
- name: mongodb_latency_commands
|
||||
type: COUNTER
|
||||
- name: mongodb_latency_commands_count
|
||||
type: COUNTER
|
||||
- name: mongodb_latency_reads
|
||||
- name: mongodb_latency_reads_count
|
||||
- name: mongodb_latency_writes
|
||||
- name: mongodb_latency_writes_count
|
||||
- name: mongodb_net_in_bytes
|
||||
- name: mongodb_net_in_bytes_count
|
||||
- name: mongodb_net_out_bytes
|
||||
- name: mongodb_net_out_bytes_count
|
||||
- name: mongodb_open_connections
|
||||
- name: mongodb_operation_scan_and_order
|
||||
- name: mongodb_operation_write_conflicts
|
||||
- name: mongodb_page_faults
|
||||
type: COUNTER
|
||||
- name: mongodb_percent_cache_dirty
|
||||
- name: mongodb_percent_cache_used
|
||||
- name: mongodb_resident_megabytes
|
||||
- name: mongodb_storage_freelist_search_bucket_exhausted
|
||||
- name: mongodb_storage_freelist_search_requests
|
||||
- name: mongodb_storage_freelist_search_scanned
|
||||
- name: mongodb_tcmalloc_central_cache_free_bytes
|
||||
- name: mongodb_tcmalloc_current_allocated_bytes
|
||||
- name: mongodb_tcmalloc_current_total_thread_cache_bytes
|
||||
- name: mongodb_tcmalloc_heap_size
|
||||
- name: mongodb_tcmalloc_max_total_thread_cache_bytes
|
||||
- name: mongodb_tcmalloc_pageheap_commit_count
|
||||
- name: mongodb_tcmalloc_pageheap_committed_bytes
|
||||
- name: mongodb_tcmalloc_pageheap_decommit_count
|
||||
- name: mongodb_tcmalloc_pageheap_free_bytes
|
||||
- name: mongodb_tcmalloc_pageheap_reserve_count
|
||||
- name: mongodb_tcmalloc_pageheap_scavenge_count
|
||||
- name: mongodb_tcmalloc_pageheap_total_commit_bytes
|
||||
- name: mongodb_tcmalloc_pageheap_total_decommit_bytes
|
||||
- name: mongodb_tcmalloc_pageheap_total_reserve_bytes
|
||||
- name: mongodb_tcmalloc_pageheap_unmapped_bytes
|
||||
- name: mongodb_tcmalloc_spinlock_total_delay_ns
|
||||
- name: mongodb_tcmalloc_thread_cache_free_bytes
|
||||
- name: mongodb_tcmalloc_total_free_bytes
|
||||
- name: mongodb_tcmalloc_transfer_cache_free_bytes
|
||||
- name: mongodb_total_available
|
||||
- name: mongodb_total_created
|
||||
type: COUNTER
|
||||
- name: mongodb_total_docs_scanned
|
||||
- name: mongodb_total_in_use
|
||||
- name: mongodb_total_keys_scanned
|
||||
- name: mongodb_total_refreshing
|
||||
- name: mongodb_total_tickets_reads
|
||||
- name: mongodb_total_tickets_writes
|
||||
- name: mongodb_ttl_deletes
|
||||
- name: mongodb_ttl_deletes_per_sec
|
||||
- name: mongodb_ttl_passes
|
||||
- name: mongodb_ttl_passes_per_sec
|
||||
- name: mongodb_update_command_failed
|
||||
type: COUNTER
|
||||
- name: mongodb_update_command_total
|
||||
type: COUNTER
|
||||
- name: mongodb_updates
|
||||
- name: mongodb_updates_per_sec
|
||||
- name: mongodb_uptime_ns
|
||||
- name: mongodb_vsize_megabytes
|
||||
- name: mongodb_wtcache_app_threads_page_read_count
|
||||
type: COUNTER
|
||||
- name: mongodb_wtcache_app_threads_page_read_time
|
||||
type: COUNTER
|
||||
- name: mongodb_wtcache_app_threads_page_write_count
|
||||
type: COUNTER
|
||||
- name: mongodb_wtcache_bytes_read_into
|
||||
- name: mongodb_wtcache_bytes_written_from
|
||||
- name: mongodb_wtcache_current_bytes
|
||||
- name: mongodb_wtcache_internal_pages_evicted
|
||||
- name: mongodb_wtcache_max_bytes_configured
|
||||
- name: mongodb_wtcache_modified_pages_evicted
|
||||
- name: mongodb_wtcache_pages_evicted_by_app_thread
|
||||
- name: mongodb_wtcache_pages_queued_for_eviction
|
||||
- name: mongodb_wtcache_pages_read_into
|
||||
- name: mongodb_wtcache_pages_requested_from
|
||||
- name: mongodb_wtcache_pages_written_from
|
||||
- name: mongodb_wtcache_server_evicting_pages
|
||||
- name: mongodb_wtcache_tracked_dirty_bytes
|
||||
- name: mongodb_wtcache_unmodified_pages_evicted
|
||||
- name: mongodb_wtcache_worker_thread_evictingpages
|
|
@ -1,849 +0,0 @@
|
|||
mode: whitelist # whitelist(default),all
|
||||
metrics:
|
||||
- name: mysql_queries
|
||||
type: COUNTER
|
||||
- name: mysql_transactions
|
||||
type: COUNTER
|
||||
expr: mysql_com_commit + mysql_com_rollback
|
||||
- name: mysql_threads_running
|
||||
type: GAUGE
|
||||
comment: "并发数"
|
||||
- name: mysql_threads_connected
|
||||
type: GAUGE
|
||||
comment: "当前连接数"
|
||||
- name: mysql_variables_max_connections
|
||||
type: GAUGE
|
||||
comment: "最大连接数"
|
||||
- name: mysql_innodb_buffer_pool_read_requests
|
||||
type: COUNTER
|
||||
comment: "innodb缓冲池查询总数"
|
||||
- name: mysql_innodb_buffer_pool_reads
|
||||
type: COUNTER
|
||||
comment: "innodb从磁盘查询数"
|
||||
- name: mysql_binary_files_count
|
||||
type: COUNTER
|
||||
- name: mysql_binary_size_bytes
|
||||
type: COUNTER
|
||||
- name: mysql_binlog_bytes_written
|
||||
type: COUNTER
|
||||
- name: mysql_binlog_cache_disk_use
|
||||
type: COUNTER
|
||||
- name: mysql_binlog_cache_use
|
||||
type: COUNTER
|
||||
- name: mysql_binlog_commits
|
||||
type: COUNTER
|
||||
- name: mysql_com_begin
|
||||
type: COUNTER
|
||||
- name: mysql_com_binlog
|
||||
type: COUNTER
|
||||
- name: mysql_com_commit
|
||||
type: COUNTER
|
||||
- name: mysql_com_create_table
|
||||
type: COUNTER
|
||||
- name: mysql_com_delete
|
||||
type: COUNTER
|
||||
- name: mysql_com_delete_multi
|
||||
type: COUNTER
|
||||
- name: mysql_com_drop_table
|
||||
type: COUNTER
|
||||
- name: mysql_com_empty_query
|
||||
type: COUNTER
|
||||
- name: mysql_com_execute_sql
|
||||
type: COUNTER
|
||||
- name: mysql_com_flush
|
||||
type: COUNTER
|
||||
- name: mysql_com_insert
|
||||
type: COUNTER
|
||||
- name: mysql_com_lock_tables
|
||||
type: COUNTER
|
||||
- name: mysql_com_rollback
|
||||
type: COUNTER
|
||||
- name: mysql_com_stmt_close
|
||||
type: COUNTER
|
||||
- name: mysql_com_stmt_execute
|
||||
type: COUNTER
|
||||
- name: mysql_com_stmt_prepare
|
||||
type: COUNTER
|
||||
- name: mysql_com_stmt_reprepare
|
||||
type: COUNTER
|
||||
- name: mysql_com_stmt_reset
|
||||
type: COUNTER
|
||||
- name: mysql_com_stmt_fetch
|
||||
type: COUNTER
|
||||
- name: mysql_com_update
|
||||
type: COUNTER
|
||||
- name: mysql_com_update_multi
|
||||
type: COUNTER
|
||||
- name: mysql_compression
|
||||
type: COUNTER
|
||||
- name: mysql_connections
|
||||
type: GAUGE
|
||||
- name: mysql_max_used_connections
|
||||
type: COUNTER
|
||||
- name: mysql_open_files
|
||||
type: GAUGE
|
||||
- name: mysql_open_streams
|
||||
type: GAUGE
|
||||
- name: mysql_open_tables
|
||||
type: GAUGE
|
||||
- name: mysql_opened_files
|
||||
type: COUNTER
|
||||
- name: mysql_opened_table_definitions
|
||||
type: COUNTER
|
||||
- name: mysql_opened_tables
|
||||
type: COUNTER
|
||||
- name: mysql_opened_views
|
||||
type: COUNTER
|
||||
- name: mysql_rows_read
|
||||
type: COUNTER
|
||||
- name: mysql_rows_sent
|
||||
type: COUNTER
|
||||
- name: mysql_sort_rows
|
||||
type: COUNTER
|
||||
|
||||
trash:
|
||||
- name: mysql_aborted_clients
|
||||
type: COUNTER
|
||||
comment: "mysql aborted clients number"
|
||||
- name: mysql_aborted_connects
|
||||
type: COUNTER
|
||||
- name: mysql_access_denied_errors
|
||||
type: COUNTER
|
||||
- name: mysql_aria_pagecache_blocks_not_flushed
|
||||
type: COUNTER
|
||||
- name: mysql_aria_pagecache_blocks_unused
|
||||
type: COUNTER
|
||||
- name: mysql_aria_pagecache_blocks_used
|
||||
type: COUNTER
|
||||
- name: mysql_aria_pagecache_read_requests
|
||||
type: COUNTER
|
||||
- name: mysql_aria_pagecache_reads
|
||||
type: COUNTER
|
||||
- name: mysql_aria_pagecache_write_requests
|
||||
type: COUNTER
|
||||
- name: mysql_aria_pagecache_writes
|
||||
type: COUNTER
|
||||
- name: mysql_aria_transaction_log_syncs
|
||||
type: COUNTER
|
||||
- name: mysql_binlog_group_commits
|
||||
- name: mysql_binlog_snapshot_position
|
||||
- name: mysql_binlog_stmt_cache_disk_use
|
||||
- name: mysql_binlog_stmt_cache_use
|
||||
- name: mysql_busy_time
|
||||
- name: mysql_bytes_received
|
||||
- name: mysql_bytes_sent
|
||||
- name: mysql_com_admin_commands
|
||||
- name: mysql_com_alter_db
|
||||
- name: mysql_com_alter_db_upgrade
|
||||
- name: mysql_com_alter_event
|
||||
- name: mysql_com_alter_function
|
||||
- name: mysql_com_alter_procedure
|
||||
- name: mysql_com_alter_server
|
||||
- name: mysql_com_alter_table
|
||||
- name: mysql_com_alter_tablespace
|
||||
- name: mysql_com_analyze
|
||||
- name: mysql_com_assign_to_keycache
|
||||
- name: mysql_com_call_procedure
|
||||
- name: mysql_com_change_db
|
||||
- name: mysql_com_change_master
|
||||
- name: mysql_com_check
|
||||
- name: mysql_com_checksum
|
||||
- name: mysql_com_create_db
|
||||
- name: mysql_com_create_event
|
||||
- name: mysql_com_create_function
|
||||
- name: mysql_com_create_index
|
||||
- name: mysql_com_create_procedure
|
||||
- name: mysql_com_create_server
|
||||
- name: mysql_com_create_trigger
|
||||
- name: mysql_com_create_udf
|
||||
- name: mysql_com_create_user
|
||||
- name: mysql_com_create_view
|
||||
- name: mysql_com_dealloc_sql
|
||||
- name: mysql_com_do
|
||||
- name: mysql_com_drop_db
|
||||
- name: mysql_com_drop_event
|
||||
- name: mysql_com_drop_function
|
||||
- name: mysql_com_drop_index
|
||||
- name: mysql_com_drop_procedure
|
||||
- name: mysql_com_drop_server
|
||||
- name: mysql_com_drop_trigger
|
||||
- name: mysql_com_drop_user
|
||||
- name: mysql_com_drop_view
|
||||
- name: mysql_com_grant
|
||||
- name: mysql_com_ha_close
|
||||
- name: mysql_com_ha_open
|
||||
- name: mysql_com_ha_read
|
||||
- name: mysql_com_help
|
||||
- name: mysql_com_insert_select
|
||||
- name: mysql_com_install_plugin
|
||||
- name: mysql_com_kill
|
||||
- name: mysql_com_load
|
||||
- name: mysql_com_optimize
|
||||
- name: mysql_com_preload_keys
|
||||
- name: mysql_com_prepare_sql
|
||||
- name: mysql_com_purge
|
||||
- name: mysql_com_purge_before_date
|
||||
- name: mysql_com_release_savepoint
|
||||
- name: mysql_com_rename_table
|
||||
- name: mysql_com_rename_user
|
||||
- name: mysql_com_repair
|
||||
- name: mysql_com_replace
|
||||
- name: mysql_com_replace_select
|
||||
- name: mysql_com_reset
|
||||
- name: mysql_com_resignal
|
||||
- name: mysql_com_revoke
|
||||
- name: mysql_com_revoke_all
|
||||
- name: mysql_com_rollback_to_savepoint
|
||||
- name: mysql_com_savepoint
|
||||
- name: mysql_com_select
|
||||
- name: mysql_com_set_option
|
||||
- name: mysql_com_show_authors
|
||||
- name: mysql_com_show_binlog_events
|
||||
- name: mysql_com_show_binlogs
|
||||
- name: mysql_com_show_charsets
|
||||
- name: mysql_com_show_client_statistics
|
||||
- name: mysql_com_show_collations
|
||||
- name: mysql_com_show_contributors
|
||||
- name: mysql_com_show_create_db
|
||||
- name: mysql_com_show_create_event
|
||||
- name: mysql_com_show_create_func
|
||||
- name: mysql_com_show_create_proc
|
||||
- name: mysql_com_show_create_table
|
||||
- name: mysql_com_show_create_trigger
|
||||
- name: mysql_com_show_databases
|
||||
- name: mysql_com_show_engine_logs
|
||||
- name: mysql_com_show_engine_mutex
|
||||
- name: mysql_com_show_engine_status
|
||||
- name: mysql_com_show_errors
|
||||
- name: mysql_com_show_events
|
||||
- name: mysql_com_show_fields
|
||||
- name: mysql_com_show_function_status
|
||||
- name: mysql_com_show_grants
|
||||
- name: mysql_com_show_index_statistics
|
||||
- name: mysql_com_show_keys
|
||||
- name: mysql_com_show_master_status
|
||||
- name: mysql_com_show_open_tables
|
||||
- name: mysql_com_show_plugins
|
||||
- name: mysql_com_show_privileges
|
||||
- name: mysql_com_show_procedure_status
|
||||
- name: mysql_com_show_processlist
|
||||
- name: mysql_com_show_profile
|
||||
- name: mysql_com_show_profiles
|
||||
- name: mysql_com_show_relaylog_events
|
||||
- name: mysql_com_show_slave_hosts
|
||||
- name: mysql_com_show_slave_status
|
||||
- name: mysql_com_show_status
|
||||
- name: mysql_com_show_storage_engines
|
||||
- name: mysql_com_show_table_statistics
|
||||
- name: mysql_com_show_table_status
|
||||
- name: mysql_com_show_tables
|
||||
- name: mysql_com_show_triggers
|
||||
- name: mysql_com_show_user_statistics
|
||||
- name: mysql_com_show_variables
|
||||
- name: mysql_com_show_warnings
|
||||
- name: mysql_com_signal
|
||||
- name: mysql_com_slave_start
|
||||
- name: mysql_com_slave_stop
|
||||
- name: mysql_com_stmt_send_long_data
|
||||
- name: mysql_com_truncate
|
||||
- name: mysql_com_uninstall_plugin
|
||||
- name: mysql_com_unlock_tables
|
||||
- name: mysql_com_xa_commit
|
||||
- name: mysql_com_xa_end
|
||||
- name: mysql_com_xa_prepare
|
||||
- name: mysql_com_xa_recover
|
||||
- name: mysql_com_xa_rollback
|
||||
- name: mysql_com_xa_start
|
||||
- name: mysql_cpu_time
|
||||
- name: mysql_created_tmp_disk_tables
|
||||
- name: mysql_created_tmp_files
|
||||
- name: mysql_created_tmp_tables
|
||||
- name: mysql_delayed_errors
|
||||
- name: mysql_delayed_insert_threads
|
||||
- name: mysql_delayed_writes
|
||||
- name: mysql_empty_queries
|
||||
- name: mysql_executed_events
|
||||
- name: mysql_executed_triggers
|
||||
- name: mysql_feature_dynamic_columns
|
||||
- name: mysql_feature_fulltext
|
||||
- name: mysql_feature_gis
|
||||
- name: mysql_feature_locale
|
||||
- name: mysql_feature_subquery
|
||||
- name: mysql_feature_timezone
|
||||
- name: mysql_feature_trigger
|
||||
- name: mysql_feature_xml
|
||||
- name: mysql_flush_commands
|
||||
- name: mysql_handler_commit
|
||||
- name: mysql_handler_delete
|
||||
- name: mysql_handler_discover
|
||||
- name: mysql_handler_icp_attempts
|
||||
- name: mysql_handler_icp_match
|
||||
- name: mysql_handler_mrr_init
|
||||
- name: mysql_handler_mrr_key_refills
|
||||
- name: mysql_handler_mrr_rowid_refills
|
||||
- name: mysql_handler_prepare
|
||||
- name: mysql_handler_read_first
|
||||
- name: mysql_handler_read_key
|
||||
- name: mysql_handler_read_last
|
||||
- name: mysql_handler_read_next
|
||||
- name: mysql_handler_read_prev
|
||||
- name: mysql_handler_read_rnd
|
||||
- name: mysql_handler_read_rnd_deleted
|
||||
- name: mysql_handler_read_rnd_next
|
||||
- name: mysql_handler_rollback
|
||||
- name: mysql_handler_savepoint
|
||||
- name: mysql_handler_savepoint_rollback
|
||||
- name: mysql_handler_tmp_update
|
||||
- name: mysql_handler_tmp_write
|
||||
- name: mysql_handler_update
|
||||
- name: mysql_handler_write
|
||||
- name: mysql_innodb_adaptive_hash_cells
|
||||
- name: mysql_innodb_adaptive_hash_hash_searches
|
||||
- name: mysql_innodb_adaptive_hash_heap_buffers
|
||||
- name: mysql_innodb_adaptive_hash_non_hash_searches
|
||||
- name: mysql_innodb_background_log_sync
|
||||
- name: mysql_innodb_buffer_pool_bytes_data
|
||||
- name: mysql_innodb_buffer_pool_bytes_dirty
|
||||
- name: mysql_innodb_buffer_pool_pages_data
|
||||
- name: mysql_innodb_buffer_pool_pages_dirty
|
||||
- name: mysql_innodb_buffer_pool_pages_flushed
|
||||
- name: mysql_innodb_buffer_pool_pages_free
|
||||
- name: mysql_innodb_buffer_pool_pages_lru_flushed
|
||||
- name: mysql_innodb_buffer_pool_pages_made_not_young
|
||||
- name: mysql_innodb_buffer_pool_pages_made_young
|
||||
- name: mysql_innodb_buffer_pool_pages_misc
|
||||
- name: mysql_innodb_buffer_pool_pages_old
|
||||
- name: mysql_innodb_buffer_pool_pages_total
|
||||
- name: mysql_innodb_buffer_pool_read_ahead
|
||||
- name: mysql_innodb_buffer_pool_read_ahead_evicted
|
||||
- name: mysql_innodb_buffer_pool_read_ahead_rnd
|
||||
- name: mysql_innodb_buffer_pool_wait_free
|
||||
- name: mysql_innodb_buffer_pool_write_requests
|
||||
- name: mysql_innodb_checkpoint_age
|
||||
- name: mysql_innodb_checkpoint_max_age
|
||||
- name: mysql_innodb_checkpoint_target_age
|
||||
- name: mysql_innodb_current_row_locks
|
||||
- name: mysql_innodb_data_fsyncs
|
||||
- name: mysql_innodb_data_pending_fsyncs
|
||||
- name: mysql_innodb_data_pending_reads
|
||||
- name: mysql_innodb_data_pending_writes
|
||||
- name: mysql_innodb_data_read
|
||||
- name: mysql_innodb_data_reads
|
||||
- name: mysql_innodb_data_writes
|
||||
- name: mysql_innodb_data_written
|
||||
- name: mysql_innodb_dblwr_pages_written
|
||||
- name: mysql_innodb_dblwr_writes
|
||||
- name: mysql_innodb_deadlocks
|
||||
- name: mysql_innodb_descriptors_memory
|
||||
- name: mysql_innodb_dict_tables
|
||||
- name: mysql_innodb_have_atomic_builtins
|
||||
- name: mysql_innodb_history_list_length
|
||||
- name: mysql_innodb_ibuf_discarded_delete_marks
|
||||
- name: mysql_innodb_ibuf_discarded_deletes
|
||||
- name: mysql_innodb_ibuf_discarded_inserts
|
||||
- name: mysql_innodb_ibuf_free_list
|
||||
- name: mysql_innodb_ibuf_merged_delete_marks
|
||||
- name: mysql_innodb_ibuf_merged_deletes
|
||||
- name: mysql_innodb_ibuf_merged_inserts
|
||||
- name: mysql_innodb_ibuf_merges
|
||||
- name: mysql_innodb_ibuf_segment_size
|
||||
- name: mysql_innodb_ibuf_size
|
||||
- name: mysql_innodb_log_waits
|
||||
- name: mysql_innodb_log_write_requests
|
||||
- name: mysql_innodb_log_writes
|
||||
- name: mysql_innodb_lsn_current
|
||||
- name: mysql_innodb_lsn_flushed
|
||||
- name: mysql_innodb_lsn_last_checkpoint
|
||||
- name: mysql_innodb_master_thread_10_second_loops
|
||||
- name: mysql_innodb_master_thread_1_second_loops
|
||||
- name: mysql_innodb_master_thread_background_loops
|
||||
- name: mysql_innodb_master_thread_main_flush_loops
|
||||
- name: mysql_innodb_master_thread_sleeps
|
||||
- name: mysql_innodb_max_trx_id
|
||||
- name: mysql_innodb_mem_adaptive_hash
|
||||
- name: mysql_innodb_mem_dictionary
|
||||
- name: mysql_innodb_mem_total
|
||||
- name: mysql_innodb_mutex_os_waits
|
||||
- name: mysql_innodb_mutex_spin_rounds
|
||||
- name: mysql_innodb_mutex_spin_waits
|
||||
- name: mysql_innodb_oldest_view_low_limit_trx_id
|
||||
- name: mysql_innodb_os_log_fsyncs
|
||||
- name: mysql_innodb_os_log_pending_fsyncs
|
||||
- name: mysql_innodb_os_log_pending_writes
|
||||
- name: mysql_innodb_os_log_written
|
||||
- name: mysql_innodb_page_size
|
||||
- name: mysql_innodb_pages_created
|
||||
- name: mysql_innodb_pages_read
|
||||
- name: mysql_innodb_pages_written
|
||||
- name: mysql_innodb_purge_trx_id
|
||||
- name: mysql_innodb_purge_undo_no
|
||||
- name: mysql_innodb_read_views_memory
|
||||
- name: mysql_innodb_row_lock_current_waits
|
||||
- name: mysql_innodb_row_lock_time
|
||||
- name: mysql_innodb_row_lock_time_avg
|
||||
- name: mysql_innodb_row_lock_time_max
|
||||
- name: mysql_innodb_row_lock_waits
|
||||
- name: mysql_innodb_rows_deleted
|
||||
- name: mysql_innodb_rows_inserted
|
||||
- name: mysql_innodb_rows_read
|
||||
- name: mysql_innodb_rows_updated
|
||||
- name: mysql_innodb_s_lock_os_waits
|
||||
- name: mysql_innodb_s_lock_spin_rounds
|
||||
- name: mysql_innodb_s_lock_spin_waits
|
||||
- name: mysql_innodb_truncated_status_writes
|
||||
- name: mysql_innodb_x_lock_os_waits
|
||||
- name: mysql_innodb_x_lock_spin_rounds
|
||||
- name: mysql_innodb_x_lock_spin_waits
|
||||
- name: mysql_key_blocks_not_flushed
|
||||
- name: mysql_key_blocks_unused
|
||||
- name: mysql_key_blocks_used
|
||||
- name: mysql_key_blocks_warm
|
||||
- name: mysql_key_read_requests
|
||||
- name: mysql_key_reads
|
||||
- name: mysql_key_write_requests
|
||||
- name: mysql_key_writes
|
||||
- name: mysql_last_query_cost
|
||||
- name: mysql_not_flushed_delayed_rows
|
||||
- name: mysql_open_table_definitions
|
||||
- name: mysql_performance_schema_cond_classes_lost
|
||||
- name: mysql_performance_schema_cond_instances_lost
|
||||
- name: mysql_performance_schema_file_classes_lost
|
||||
- name: mysql_performance_schema_file_handles_lost
|
||||
- name: mysql_performance_schema_file_instances_lost
|
||||
- name: mysql_performance_schema_locker_lost
|
||||
- name: mysql_performance_schema_mutex_classes_lost
|
||||
- name: mysql_performance_schema_mutex_instances_lost
|
||||
- name: mysql_performance_schema_rwlock_classes_lost
|
||||
- name: mysql_performance_schema_rwlock_instances_lost
|
||||
- name: mysql_performance_schema_table_handles_lost
|
||||
- name: mysql_performance_schema_table_instances_lost
|
||||
- name: mysql_performance_schema_thread_classes_lost
|
||||
- name: mysql_performance_schema_thread_instances_lost
|
||||
- name: mysql_prepared_stmt_count
|
||||
- name: mysql_process_list_threads_after_create
|
||||
- name: mysql_process_list_threads_altering_table
|
||||
- name: mysql_process_list_threads_analyzing
|
||||
- name: mysql_process_list_threads_checking_permissions
|
||||
- name: mysql_process_list_threads_checking_table
|
||||
- name: mysql_process_list_threads_cleaning_up
|
||||
- name: mysql_process_list_threads_closing_tables
|
||||
- name: mysql_process_list_threads_converting_heap_to_myisam
|
||||
- name: mysql_process_list_threads_copying_to_tmp_table
|
||||
- name: mysql_process_list_threads_creating_sort_index
|
||||
- name: mysql_process_list_threads_creating_table
|
||||
- name: mysql_process_list_threads_creating_tmp_table
|
||||
- name: mysql_process_list_threads_deleting
|
||||
- name: mysql_process_list_threads_end
|
||||
- name: mysql_process_list_threads_executing
|
||||
- name: mysql_process_list_threads_execution_of_init_command
|
||||
- name: mysql_process_list_threads_flushing_tables
|
||||
- name: mysql_process_list_threads_freeing_items
|
||||
- name: mysql_process_list_threads_fulltext_initialization
|
||||
- name: mysql_process_list_threads_idle
|
||||
- name: mysql_process_list_threads_init
|
||||
- name: mysql_process_list_threads_killed
|
||||
- name: mysql_process_list_threads_logging_slow_query
|
||||
- name: mysql_process_list_threads_login
|
||||
- name: mysql_process_list_threads_manage_keys
|
||||
- name: mysql_process_list_threads_opening_tables
|
||||
- name: mysql_process_list_threads_optimizing
|
||||
- name: mysql_process_list_threads_other
|
||||
- name: mysql_process_list_threads_preparing
|
||||
- name: mysql_process_list_threads_reading_from_net
|
||||
- name: mysql_process_list_threads_removing_duplicates
|
||||
- name: mysql_process_list_threads_removing_tmp_table
|
||||
- name: mysql_process_list_threads_reopen_tables
|
||||
- name: mysql_process_list_threads_repair_by_sorting
|
||||
- name: mysql_process_list_threads_repair_done
|
||||
- name: mysql_process_list_threads_repair_with_keycache
|
||||
- name: mysql_process_list_threads_replication_master
|
||||
- name: mysql_process_list_threads_rolling_back
|
||||
- name: mysql_process_list_threads_searching_rows_for_update
|
||||
- name: mysql_process_list_threads_sending_data
|
||||
- name: mysql_process_list_threads_sorting_for_group
|
||||
- name: mysql_process_list_threads_sorting_for_order
|
||||
- name: mysql_process_list_threads_sorting_index
|
||||
- name: mysql_process_list_threads_sorting_result
|
||||
- name: mysql_process_list_threads_statistics
|
||||
- name: mysql_process_list_threads_updating
|
||||
- name: mysql_process_list_threads_waiting_for_lock
|
||||
- name: mysql_process_list_threads_waiting_for_table_flush
|
||||
- name: mysql_process_list_threads_waiting_for_tables
|
||||
- name: mysql_process_list_threads_waiting_on_cond
|
||||
- name: mysql_process_list_threads_writing_to_net
|
||||
- name: mysql_qcache_free_blocks
|
||||
- name: mysql_qcache_free_memory
|
||||
- name: mysql_qcache_hits
|
||||
- name: mysql_qcache_inserts
|
||||
- name: mysql_qcache_lowmem_prunes
|
||||
- name: mysql_qcache_not_cached
|
||||
- name: mysql_qcache_queries_in_cache
|
||||
- name: mysql_qcache_total_blocks
|
||||
- name: mysql_questions
|
||||
- name: mysql_rows_tmp_read
|
||||
- name: mysql_select_full_join
|
||||
- name: mysql_select_full_range_join
|
||||
- name: mysql_select_range
|
||||
- name: mysql_select_range_check
|
||||
- name: mysql_select_scan
|
||||
- name: mysql_slave_heartbeat_period
|
||||
- name: mysql_slave_open_temp_tables
|
||||
- name: mysql_slave_received_heartbeats
|
||||
- name: mysql_slave_retried_transactions
|
||||
- name: mysql_slave_running
|
||||
- name: mysql_slow_launch_threads
|
||||
- name: mysql_slow_queries
|
||||
- name: mysql_sort_merge_passes
|
||||
- name: mysql_sort_range
|
||||
- name: mysql_sort_scan
|
||||
- name: mysql_ssl_accept_renegotiates
|
||||
- name: mysql_ssl_accepts
|
||||
- name: mysql_ssl_callback_cache_hits
|
||||
- name: mysql_ssl_client_connects
|
||||
- name: mysql_ssl_connect_renegotiates
|
||||
- name: mysql_ssl_ctx_verify_depth
|
||||
- name: mysql_ssl_ctx_verify_mode
|
||||
- name: mysql_ssl_default_timeout
|
||||
- name: mysql_ssl_finished_accepts
|
||||
- name: mysql_ssl_finished_connects
|
||||
- name: mysql_ssl_session_cache_hits
|
||||
- name: mysql_ssl_session_cache_misses
|
||||
- name: mysql_ssl_session_cache_overflows
|
||||
- name: mysql_ssl_session_cache_size
|
||||
- name: mysql_ssl_session_cache_timeouts
|
||||
- name: mysql_ssl_sessions_reused
|
||||
- name: mysql_ssl_used_session_cache_entries
|
||||
- name: mysql_ssl_verify_depth
|
||||
- name: mysql_ssl_verify_mode
|
||||
- name: mysql_subquery_cache_hit
|
||||
- name: mysql_subquery_cache_miss
|
||||
- name: mysql_syncs
|
||||
- name: mysql_table_locks_immediate
|
||||
- name: mysql_table_locks_waited
|
||||
- name: mysql_tc_log_max_pages_used
|
||||
- name: mysql_tc_log_page_size
|
||||
- name: mysql_tc_log_page_waits
|
||||
- name: mysql_threadpool_idle_threads
|
||||
- name: mysql_threadpool_threads
|
||||
- name: mysql_threads_cached
|
||||
- name: mysql_threads_created
|
||||
- name: mysql_uptime
|
||||
- name: mysql_uptime_since_flush_status
|
||||
- name: mysql_users_connections
|
||||
- name: mysql_variables_aria_block_size
|
||||
- name: mysql_variables_aria_checkpoint_interval
|
||||
- name: mysql_variables_aria_checkpoint_log_activity
|
||||
- name: mysql_variables_aria_force_start_after_recovery_failures
|
||||
- name: mysql_variables_aria_group_commit_interval
|
||||
- name: mysql_variables_aria_log_file_size
|
||||
- name: mysql_variables_aria_max_sort_file_size
|
||||
- name: mysql_variables_aria_page_checksum
|
||||
- name: mysql_variables_aria_pagecache_age_threshold
|
||||
- name: mysql_variables_aria_pagecache_buffer_size
|
||||
- name: mysql_variables_aria_pagecache_division_limit
|
||||
- name: mysql_variables_aria_repair_threads
|
||||
- name: mysql_variables_aria_sort_buffer_size
|
||||
- name: mysql_variables_aria_used_for_temp_tables
|
||||
- name: mysql_variables_auto_increment_increment
|
||||
- name: mysql_variables_auto_increment_offset
|
||||
- name: mysql_variables_autocommit
|
||||
- name: mysql_variables_automatic_sp_privileges
|
||||
- name: mysql_variables_back_log
|
||||
- name: mysql_variables_big_tables
|
||||
- name: mysql_variables_binlog_annotate_row_events
|
||||
- name: mysql_variables_binlog_cache_size
|
||||
- name: mysql_variables_binlog_direct_non_transactional_updates
|
||||
- name: mysql_variables_binlog_optimize_thread_scheduling
|
||||
- name: mysql_variables_binlog_stmt_cache_size
|
||||
- name: mysql_variables_bulk_insert_buffer_size
|
||||
- name: mysql_variables_connect_timeout
|
||||
- name: mysql_variables_deadlock_search_depth_long
|
||||
- name: mysql_variables_deadlock_search_depth_short
|
||||
- name: mysql_variables_deadlock_timeout_long
|
||||
- name: mysql_variables_deadlock_timeout_short
|
||||
- name: mysql_variables_debug_no_thread_alarm
|
||||
- name: mysql_variables_default_week_format
|
||||
- name: mysql_variables_delay_key_write
|
||||
- name: mysql_variables_delayed_insert_limit
|
||||
- name: mysql_variables_delayed_insert_timeout
|
||||
- name: mysql_variables_delayed_queue_size
|
||||
- name: mysql_variables_div_precision_increment
|
||||
- name: mysql_variables_engine_condition_pushdown
|
||||
- name: mysql_variables_event_scheduler
|
||||
- name: mysql_variables_expensive_subquery_limit
|
||||
- name: mysql_variables_expire_logs_days
|
||||
- name: mysql_variables_extra_max_connections
|
||||
- name: mysql_variables_extra_port
|
||||
- name: mysql_variables_flush
|
||||
- name: mysql_variables_flush_time
|
||||
- name: mysql_variables_foreign_key_checks
|
||||
- name: mysql_variables_ft_max_word_len
|
||||
- name: mysql_variables_ft_min_word_len
|
||||
- name: mysql_variables_ft_query_expansion_limit
|
||||
- name: mysql_variables_general_log
|
||||
- name: mysql_variables_group_concat_max_len
|
||||
- name: mysql_variables_have_compress
|
||||
- name: mysql_variables_have_crypt
|
||||
- name: mysql_variables_have_csv
|
||||
- name: mysql_variables_have_dynamic_loading
|
||||
- name: mysql_variables_have_geometry
|
||||
- name: mysql_variables_have_innodb
|
||||
- name: mysql_variables_have_ndbcluster
|
||||
- name: mysql_variables_have_partitioning
|
||||
- name: mysql_variables_have_profiling
|
||||
- name: mysql_variables_have_query_cache
|
||||
- name: mysql_variables_have_rtree_keys
|
||||
- name: mysql_variables_ignore_builtin_innodb
|
||||
- name: mysql_variables_innodb_adaptive_flushing
|
||||
- name: mysql_variables_innodb_adaptive_hash_index
|
||||
- name: mysql_variables_innodb_adaptive_hash_index_partitions
|
||||
- name: mysql_variables_innodb_additional_mem_pool_size
|
||||
- name: mysql_variables_innodb_autoextend_increment
|
||||
- name: mysql_variables_innodb_autoinc_lock_mode
|
||||
- name: mysql_variables_innodb_blocking_buffer_pool_restore
|
||||
- name: mysql_variables_innodb_buffer_pool_instances
|
||||
- name: mysql_variables_innodb_buffer_pool_populate
|
||||
- name: mysql_variables_innodb_buffer_pool_restore_at_startup
|
||||
- name: mysql_variables_innodb_buffer_pool_shm_checksum
|
||||
- name: mysql_variables_innodb_buffer_pool_shm_key
|
||||
- name: mysql_variables_innodb_buffer_pool_size
|
||||
- name: mysql_variables_innodb_checkpoint_age_target
|
||||
- name: mysql_variables_innodb_checksums
|
||||
- name: mysql_variables_innodb_commit_concurrency
|
||||
- name: mysql_variables_innodb_concurrency_tickets
|
||||
- name: mysql_variables_innodb_dict_size_limit
|
||||
- name: mysql_variables_innodb_doublewrite
|
||||
- name: mysql_variables_innodb_fake_changes
|
||||
- name: mysql_variables_innodb_fast_checksum
|
||||
- name: mysql_variables_innodb_fast_shutdown
|
||||
- name: mysql_variables_innodb_file_format_check
|
||||
- name: mysql_variables_innodb_file_per_table
|
||||
- name: mysql_variables_innodb_flush_log_at_trx_commit
|
||||
- name: mysql_variables_innodb_force_load_corrupted
|
||||
- name: mysql_variables_innodb_force_recovery
|
||||
- name: mysql_variables_innodb_ibuf_accel_rate
|
||||
- name: mysql_variables_innodb_ibuf_active_contract
|
||||
- name: mysql_variables_innodb_ibuf_max_size
|
||||
- name: mysql_variables_innodb_import_table_from_xtrabackup
|
||||
- name: mysql_variables_innodb_io_capacity
|
||||
- name: mysql_variables_innodb_kill_idle_transaction
|
||||
- name: mysql_variables_innodb_large_prefix
|
||||
- name: mysql_variables_innodb_lazy_drop_table
|
||||
- name: mysql_variables_innodb_lock_wait_timeout
|
||||
- name: mysql_variables_innodb_locking_fake_changes
|
||||
- name: mysql_variables_innodb_locks_unsafe_for_binlog
|
||||
- name: mysql_variables_innodb_log_block_size
|
||||
- name: mysql_variables_innodb_log_buffer_size
|
||||
- name: mysql_variables_innodb_log_file_size
|
||||
- name: mysql_variables_innodb_log_files_in_group
|
||||
- name: mysql_variables_innodb_max_bitmap_file_size
|
||||
- name: mysql_variables_innodb_max_changed_pages
|
||||
- name: mysql_variables_innodb_max_dirty_pages_pct
|
||||
- name: mysql_variables_innodb_max_purge_lag
|
||||
- name: mysql_variables_innodb_merge_sort_block_size
|
||||
- name: mysql_variables_innodb_mirrored_log_groups
|
||||
- name: mysql_variables_innodb_old_blocks_pct
|
||||
- name: mysql_variables_innodb_old_blocks_time
|
||||
- name: mysql_variables_innodb_open_files
|
||||
- name: mysql_variables_innodb_page_size
|
||||
- name: mysql_variables_innodb_print_all_deadlocks
|
||||
- name: mysql_variables_innodb_purge_batch_size
|
||||
- name: mysql_variables_innodb_purge_threads
|
||||
- name: mysql_variables_innodb_random_read_ahead
|
||||
- name: mysql_variables_innodb_read_ahead_threshold
|
||||
- name: mysql_variables_innodb_read_io_threads
|
||||
- name: mysql_variables_innodb_recovery_stats
|
||||
- name: mysql_variables_innodb_recovery_update_relay_log
|
||||
- name: mysql_variables_innodb_replication_delay
|
||||
- name: mysql_variables_innodb_rollback_on_timeout
|
||||
- name: mysql_variables_innodb_rollback_segments
|
||||
- name: mysql_variables_innodb_show_locks_held
|
||||
- name: mysql_variables_innodb_show_verbose_locks
|
||||
- name: mysql_variables_innodb_simulate_comp_failures
|
||||
- name: mysql_variables_innodb_spin_wait_delay
|
||||
- name: mysql_variables_innodb_stats_auto_update
|
||||
- name: mysql_variables_innodb_stats_modified_counter
|
||||
- name: mysql_variables_innodb_stats_on_metadata
|
||||
- name: mysql_variables_innodb_stats_sample_pages
|
||||
- name: mysql_variables_innodb_stats_traditional
|
||||
- name: mysql_variables_innodb_stats_update_need_lock
|
||||
- name: mysql_variables_innodb_strict_mode
|
||||
- name: mysql_variables_innodb_support_xa
|
||||
- name: mysql_variables_innodb_sync_spin_loops
|
||||
- name: mysql_variables_innodb_table_locks
|
||||
- name: mysql_variables_innodb_thread_concurrency
|
||||
- name: mysql_variables_innodb_thread_concurrency_timer_based
|
||||
- name: mysql_variables_innodb_thread_sleep_delay
|
||||
- name: mysql_variables_innodb_track_changed_pages
|
||||
- name: mysql_variables_innodb_use_atomic_writes
|
||||
- name: mysql_variables_innodb_use_fallocate
|
||||
- name: mysql_variables_innodb_use_global_flush_log_at_trx_commit
|
||||
- name: mysql_variables_innodb_use_native_aio
|
||||
- name: mysql_variables_innodb_use_stacktrace
|
||||
- name: mysql_variables_innodb_use_sys_malloc
|
||||
- name: mysql_variables_innodb_use_sys_stats_table
|
||||
- name: mysql_variables_innodb_write_io_threads
|
||||
- name: mysql_variables_interactive_timeout
|
||||
- name: mysql_variables_join_buffer_size
|
||||
- name: mysql_variables_join_buffer_space_limit
|
||||
- name: mysql_variables_join_cache_level
|
||||
- name: mysql_variables_keep_files_on_create
|
||||
- name: mysql_variables_key_buffer_size
|
||||
- name: mysql_variables_key_cache_age_threshold
|
||||
- name: mysql_variables_key_cache_block_size
|
||||
- name: mysql_variables_key_cache_division_limit
|
||||
- name: mysql_variables_key_cache_segments
|
||||
- name: mysql_variables_large_files_support
|
||||
- name: mysql_variables_large_page_size
|
||||
- name: mysql_variables_large_pages
|
||||
- name: mysql_variables_local_infile
|
||||
- name: mysql_variables_lock_wait_timeout
|
||||
- name: mysql_variables_locked_in_memory
|
||||
- name: mysql_variables_log
|
||||
- name: mysql_variables_log_bin
|
||||
- name: mysql_variables_log_bin_trust_function_creators
|
||||
- name: mysql_variables_log_queries_not_using_indexes
|
||||
- name: mysql_variables_log_slave_updates
|
||||
- name: mysql_variables_log_slow_queries
|
||||
- name: mysql_variables_log_slow_rate_limit
|
||||
- name: mysql_variables_log_warnings
|
||||
- name: mysql_variables_long_query_time
|
||||
- name: mysql_variables_low_priority_updates
|
||||
- name: mysql_variables_lower_case_file_system
|
||||
- name: mysql_variables_lower_case_table_names
|
||||
- name: mysql_variables_master_verify_checksum
|
||||
- name: mysql_variables_max_allowed_packet
|
||||
- name: mysql_variables_max_binlog_cache_size
|
||||
- name: mysql_variables_max_binlog_size
|
||||
- name: mysql_variables_max_binlog_stmt_cache_size
|
||||
- name: mysql_variables_max_connect_errors
|
||||
- name: mysql_variables_max_delayed_threads
|
||||
- name: mysql_variables_max_error_count
|
||||
- name: mysql_variables_max_heap_table_size
|
||||
- name: mysql_variables_max_insert_delayed_threads
|
||||
- name: mysql_variables_max_join_size
|
||||
- name: mysql_variables_max_length_for_sort_data
|
||||
- name: mysql_variables_max_long_data_size
|
||||
- name: mysql_variables_max_prepared_stmt_count
|
||||
- name: mysql_variables_max_relay_log_size
|
||||
- name: mysql_variables_max_seeks_for_key
|
||||
- name: mysql_variables_max_sort_length
|
||||
- name: mysql_variables_max_sp_recursion_depth
|
||||
- name: mysql_variables_max_tmp_tables
|
||||
- name: mysql_variables_max_user_connections
|
||||
- name: mysql_variables_max_write_lock_count
|
||||
- name: mysql_variables_metadata_locks_cache_size
|
||||
- name: mysql_variables_min_examined_row_limit
|
||||
- name: mysql_variables_mrr_buffer_size
|
||||
- name: mysql_variables_multi_range_count
|
||||
- name: mysql_variables_myisam_block_size
|
||||
- name: mysql_variables_myisam_data_pointer_size
|
||||
- name: mysql_variables_myisam_max_sort_file_size
|
||||
- name: mysql_variables_myisam_mmap_size
|
||||
- name: mysql_variables_myisam_repair_threads
|
||||
- name: mysql_variables_myisam_sort_buffer_size
|
||||
- name: mysql_variables_myisam_use_mmap
|
||||
- name: mysql_variables_net_buffer_length
|
||||
- name: mysql_variables_net_read_timeout
|
||||
- name: mysql_variables_net_retry_count
|
||||
- name: mysql_variables_net_write_timeout
|
||||
- name: mysql_variables_old
|
||||
- name: mysql_variables_old_alter_table
|
||||
- name: mysql_variables_old_passwords
|
||||
- name: mysql_variables_open_files_limit
|
||||
- name: mysql_variables_optimizer_prune_level
|
||||
- name: mysql_variables_optimizer_search_depth
|
||||
- name: mysql_variables_performance_schema
|
||||
- name: mysql_variables_performance_schema_events_waits_history_long_size
|
||||
- name: mysql_variables_performance_schema_events_waits_history_size
|
||||
- name: mysql_variables_performance_schema_max_cond_classes
|
||||
- name: mysql_variables_performance_schema_max_cond_instances
|
||||
- name: mysql_variables_performance_schema_max_file_classes
|
||||
- name: mysql_variables_performance_schema_max_file_handles
|
||||
- name: mysql_variables_performance_schema_max_file_instances
|
||||
- name: mysql_variables_performance_schema_max_mutex_classes
|
||||
- name: mysql_variables_performance_schema_max_mutex_instances
|
||||
- name: mysql_variables_performance_schema_max_rwlock_classes
|
||||
- name: mysql_variables_performance_schema_max_rwlock_instances
|
||||
- name: mysql_variables_performance_schema_max_table_handles
|
||||
- name: mysql_variables_performance_schema_max_table_instances
|
||||
- name: mysql_variables_performance_schema_max_thread_classes
|
||||
- name: mysql_variables_performance_schema_max_thread_instances
|
||||
- name: mysql_variables_port
|
||||
- name: mysql_variables_preload_buffer_size
|
||||
- name: mysql_variables_profiling
|
||||
- name: mysql_variables_profiling_history_size
|
||||
- name: mysql_variables_progress_report_time
|
||||
- name: mysql_variables_protocol_version
|
||||
- name: mysql_variables_query_alloc_block_size
|
||||
- name: mysql_variables_query_cache_limit
|
||||
- name: mysql_variables_query_cache_min_res_unit
|
||||
- name: mysql_variables_query_cache_size
|
||||
- name: mysql_variables_query_cache_strip_comments
|
||||
- name: mysql_variables_query_cache_type
|
||||
- name: mysql_variables_query_cache_wlock_invalidate
|
||||
- name: mysql_variables_query_prealloc_size
|
||||
- name: mysql_variables_range_alloc_block_size
|
||||
- name: mysql_variables_read_buffer_size
|
||||
- name: mysql_variables_read_only
|
||||
- name: mysql_variables_read_rnd_buffer_size
|
||||
- name: mysql_variables_relay_log_purge
|
||||
- name: mysql_variables_relay_log_recovery
|
||||
- name: mysql_variables_relay_log_space_limit
|
||||
- name: mysql_variables_replicate_annotate_row_events
|
||||
- name: mysql_variables_report_port
|
||||
- name: mysql_variables_rowid_merge_buff_size
|
||||
- name: mysql_variables_rpl_recovery_rank
|
||||
- name: mysql_variables_secure_auth
|
||||
- name: mysql_variables_server_id
|
||||
- name: mysql_variables_skip_external_locking
|
||||
- name: mysql_variables_skip_name_resolve
|
||||
- name: mysql_variables_skip_networking
|
||||
- name: mysql_variables_skip_show_database
|
||||
- name: mysql_variables_slave_compressed_protocol
|
||||
- name: mysql_variables_slave_max_allowed_packet
|
||||
- name: mysql_variables_slave_net_timeout
|
||||
- name: mysql_variables_slave_skip_errors
|
||||
- name: mysql_variables_slave_sql_verify_checksum
|
||||
- name: mysql_variables_slave_transaction_retries
|
||||
- name: mysql_variables_slow_launch_time
|
||||
- name: mysql_variables_slow_query_log
|
||||
- name: mysql_variables_sort_buffer_size
|
||||
- name: mysql_variables_sql_auto_is_null
|
||||
- name: mysql_variables_sql_big_selects
|
||||
- name: mysql_variables_sql_big_tables
|
||||
- name: mysql_variables_sql_buffer_result
|
||||
- name: mysql_variables_sql_log_bin
|
||||
- name: mysql_variables_sql_log_off
|
||||
- name: mysql_variables_sql_low_priority_updates
|
||||
- name: mysql_variables_sql_max_join_size
|
||||
- name: mysql_variables_sql_notes
|
||||
- name: mysql_variables_sql_quote_show_create
|
||||
- name: mysql_variables_sql_safe_updates
|
||||
- name: mysql_variables_sql_select_limit
|
||||
- name: mysql_variables_sql_slave_skip_counter
|
||||
- name: mysql_variables_sql_warnings
|
||||
- name: mysql_variables_stored_program_cache
|
||||
- name: mysql_variables_sync_binlog
|
||||
- name: mysql_variables_sync_frm
|
||||
- name: mysql_variables_sync_master_info
|
||||
- name: mysql_variables_sync_relay_log
|
||||
- name: mysql_variables_sync_relay_log_info
|
||||
- name: mysql_variables_table_definition_cache
|
||||
- name: mysql_variables_table_open_cache
|
||||
- name: mysql_variables_thread_cache_size
|
||||
- name: mysql_variables_thread_concurrency
|
||||
- name: mysql_variables_thread_pool_idle_timeout
|
||||
- name: mysql_variables_thread_pool_max_threads
|
||||
- name: mysql_variables_thread_pool_oversubscribe
|
||||
- name: mysql_variables_thread_pool_size
|
||||
- name: mysql_variables_thread_pool_stall_limit
|
||||
- name: mysql_variables_thread_stack
|
||||
- name: mysql_variables_timed_mutexes
|
||||
- name: mysql_variables_tmp_table_size
|
||||
- name: mysql_variables_transaction_alloc_block_size
|
||||
- name: mysql_variables_transaction_prealloc_size
|
||||
- name: mysql_variables_unique_checks
|
||||
- name: mysql_variables_updatable_views_with_limit
|
||||
- name: mysql_variables_userstat
|
||||
- name: mysql_variables_wait_timeout
|
|
@ -1,5 +0,0 @@
|
|||
mode: whitelist # whitelist(default),all
|
||||
metrics:
|
||||
- name: net_response_result_code
|
||||
- name: net_response_response_time
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
mode: whitelist # whitelist(default),all
|
||||
metrics:
|
||||
- name: nginx_accepts
|
||||
- name: nginx_active
|
||||
- name: nginx_handled
|
||||
- name: nginx_reading
|
||||
- name: nginx_requests
|
||||
- name: nginx_waiting
|
||||
- name: nginx_writing
|
|
@ -1,15 +0,0 @@
|
|||
mode: whitelist # whitelist(default),all
|
||||
metrics:
|
||||
- name: ping_percentile95_ms
|
||||
- name: ping_percentile99_ms
|
||||
- name: ping_percentile50_ms
|
||||
- name: ping_percent_packet_loss
|
||||
- name: ping_ttl
|
||||
- name: ping_maximum_response_ms
|
||||
- name: ping_standard_deviation_ms
|
||||
- name: ping_packets_received
|
||||
- name: ping_packets_transmitted
|
||||
- name: ping_minimum_response_ms
|
||||
- name: ping_result_code
|
||||
- name: ping_average_response_ms
|
||||
|
|
@ -1 +0,0 @@
|
|||
mode: all
|
|
@ -1,82 +0,0 @@
|
|||
mode: whitelist # whitelist(default),all
|
||||
|
||||
metrics:
|
||||
- name: redis_maxmemory
|
||||
- name: redis_used_memory
|
||||
- name: redis_used_memory_peak
|
||||
- name: redis_used_memory_rss
|
||||
- name: redis_mem_fragmentation_ratio
|
||||
- name: redis_total_commands_processed
|
||||
type: COUNTER
|
||||
- name: redis_total_connections_received
|
||||
type: COUNTER
|
||||
- name: redis_expired_keys
|
||||
- name: mongodb_queries
|
||||
- name: mongodb_queries_per_sec
|
||||
- name: mongodb_queued_reads
|
||||
- name: mongodb_queued_writes
|
||||
|
||||
trash:
|
||||
- name: redis_aof_current_rewrite_time_sec
|
||||
- name: redis_aof_enabled
|
||||
- name: redis_aof_last_rewrite_time_sec
|
||||
- name: redis_aof_rewrite_in_progress
|
||||
- name: redis_aof_rewrite_scheduled
|
||||
- name: redis_blocked_clients
|
||||
- name: redis_client_biggest_input_buf
|
||||
- name: redis_client_longest_output_list
|
||||
- name: redis_clients
|
||||
- name: redis_cluster_enabled
|
||||
- name: redis_cmdstat_calls
|
||||
- name: redis_cmdstat_usec
|
||||
- name: redis_cmdstat_usec_per_call
|
||||
- name: redis_connected_slaves
|
||||
- name: redis_evicted_keys
|
||||
- name: redis_instantaneous_input_kbps
|
||||
- name: redis_instantaneous_ops_per_sec
|
||||
- name: redis_instantaneous_output_kbps
|
||||
- name: redis_keyspace_avg_ttl
|
||||
- name: redis_keyspace_expires
|
||||
- name: redis_keyspace_hitrate
|
||||
- name: redis_keyspace_hits
|
||||
type: COUNTER
|
||||
- name: redis_keyspace_keys
|
||||
- name: redis_keyspace_misses
|
||||
type: COUNTER
|
||||
- name: redis_latest_fork_usec
|
||||
- name: redis_loading
|
||||
- name: redis_lru_clock
|
||||
type: COUNTER
|
||||
- name: redis_master_repl_offset
|
||||
- name: redis_migrate_cached_sockets
|
||||
- name: redis_pubsub_channels
|
||||
- name: redis_pubsub_patterns
|
||||
- name: redis_rdb_bgsave_in_progress
|
||||
- name: redis_rdb_changes_since_last_save
|
||||
- name: redis_rdb_current_bgsave_time_sec
|
||||
- name: redis_rdb_last_bgsave_time_sec
|
||||
- name: redis_rdb_last_save_time
|
||||
type: COUNTER
|
||||
- name: redis_rdb_last_save_time_elapsed
|
||||
- name: redis_rejected_connections
|
||||
- name: redis_repl_backlog_active
|
||||
- name: redis_repl_backlog_first_byte_offset
|
||||
- name: redis_repl_backlog_histlen
|
||||
- name: redis_repl_backlog_size
|
||||
- name: redis_sync_full
|
||||
- name: redis_sync_partial_err
|
||||
- name: redis_sync_partial_ok
|
||||
- name: redis_total_net_input_bytes
|
||||
type: COUNTER
|
||||
- name: redis_total_net_output_bytes
|
||||
type: COUNTER
|
||||
- name: redis_total_system_memory
|
||||
type: COUNTER
|
||||
- name: redis_uptime
|
||||
type: COUNTER
|
||||
- name: redis_used_cpu_sys
|
||||
- name: redis_used_cpu_sys_children
|
||||
- name: redis_used_cpu_user
|
||||
- name: redis_used_cpu_user_children
|
||||
- name: redis_used_memory_lua
|
||||
|
|
@ -1 +0,0 @@
|
|||
mode: all # whitelist(default),all
|
|
@ -1 +0,0 @@
|
|||
mode: all # whitelist(default),all
|
|
@ -1,13 +0,0 @@
|
|||
workerProcesses: 5
|
||||
|
||||
logger:
|
||||
dir: logs/prober
|
||||
level: INFO
|
||||
keepHours: 24
|
||||
pluginsConfig: etc/plugins
|
||||
|
||||
report:
|
||||
region: default
|
||||
|
||||
collectRule:
|
||||
token: monapi-internal-third-module-pass-fjsdi
|
|
@ -1,120 +0,0 @@
|
|||
[
|
||||
{
|
||||
"name": "容器资源监控",
|
||||
"node_path": "",
|
||||
"tags": [
|
||||
{
|
||||
"name": "cpu",
|
||||
"weight": 0,
|
||||
"charts": [
|
||||
{
|
||||
"configs": "{\"title\":\"容器cpu使用率\",\"type\":\"chart\",\"now\":\"1610679026228\",\"start\":\"1610675426228\",\"end\":\"1610679026228\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":5,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"5\"],\"selectedMetric\":\"cpu.util\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"5\"]},{\"tagk\":\"container\",\"tagv\":[\"=all\"]},{\"tagk\":\"cpu\",\"tagv\":[\"=all\"]},{\"tagk\":\"namespace\",\"tagv\":[\"=all\"]},{\"tagk\":\"pod\",\"tagv\":[\"=all\"]}],\"counterListCount\":8}]}",
|
||||
"weight": 0
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"容器cpu 用户态使用率\",\"type\":\"chart\",\"now\":\"1610679026228\",\"start\":\"1610675426228\",\"end\":\"1610679026228\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":5,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"5\"],\"selectedMetric\":\"cpu.user\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"5\"]},{\"tagk\":\"container\",\"tagv\":[\"=all\"]},{\"tagk\":\"namespace\",\"tagv\":[\"=all\"]},{\"tagk\":\"pod\",\"tagv\":[\"=all\"]}],\"counterListCount\":6}]}",
|
||||
"weight": 1
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"容器cpu 内核态使用率\",\"type\":\"chart\",\"now\":\"1610679026228\",\"start\":\"1610675426228\",\"end\":\"1610679026228\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":5,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"5\"],\"selectedMetric\":\"cpu.sys\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"5\"]},{\"tagk\":\"container\",\"tagv\":[\"=all\"]},{\"tagk\":\"namespace\",\"tagv\":[\"=all\"]},{\"tagk\":\"pod\",\"tagv\":[\"=all\"]}],\"counterListCount\":6}]}",
|
||||
"weight": 2
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"容器cpu idle\",\"type\":\"chart\",\"now\":\"1610679026228\",\"start\":\"1610675426228\",\"end\":\"1610679026228\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":5,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"5\"],\"selectedMetric\":\"cpu.idle\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"5\"]},{\"tagk\":\"container\",\"tagv\":[\"=all\"]},{\"tagk\":\"cpu\",\"tagv\":[\"=all\"]},{\"tagk\":\"namespace\",\"tagv\":[\"=all\"]},{\"tagk\":\"pod\",\"tagv\":[\"=all\"]}],\"counterListCount\":6}]}",
|
||||
"weight": 3
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"容器cpu占用核数(=1代表占用1个核)\",\"type\":\"chart\",\"now\":\"1611720899999\",\"start\":\"1611717299999\",\"end\":\"1611720899999\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":5,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"5\"],\"selectedMetric\":\"cpu.cores.occupy\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"5\"]},{\"tagk\":\"container\",\"tagv\":[\"=all\"]},{\"tagk\":\"cpu\",\"tagv\":[\"=all\"]},{\"tagk\":\"namespace\",\"tagv\":[\"=all\"]},{\"tagk\":\"pod\",\"tagv\":[\"=all\"]}],\"counterListCount\":5}],\"id\":5}",
|
||||
"weight": 4
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"容器cpu 节流率\",\"type\":\"chart\",\"now\":\"1610679026228\",\"start\":\"1610675426228\",\"end\":\"1610679026228\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":5,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"5\"],\"selectedMetric\":\"cpu.throttled.util\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"5\"]},{\"tagk\":\"container\",\"tagv\":[\"=all\"]},{\"tagk\":\"namespace\",\"tagv\":[\"=all\"]},{\"tagk\":\"pod\",\"tagv\":[\"=all\"]}],\"counterListCount\":6}]}",
|
||||
"weight": 5
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "mem(单位为byte)",
|
||||
"weight": 1,
|
||||
"charts": [
|
||||
{
|
||||
"configs": "{\"title\":\"容器总内存大小\",\"type\":\"chart\",\"now\":\"1610679026228\",\"start\":\"1610675426228\",\"end\":\"1610679026228\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":5,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"5\"],\"selectedMetric\":\"mem.bytes.total\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"5\"]},{\"tagk\":\"container\",\"tagv\":[\"=all\"]},{\"tagk\":\"namespace\",\"tagv\":[\"=all\"]},{\"tagk\":\"pod\",\"tagv\":[\"=all\"]}],\"counterListCount\":8}]}",
|
||||
"weight": 0
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"容器已用内存大小\",\"type\":\"chart\",\"now\":\"1610679026228\",\"start\":\"1610675426228\",\"end\":\"1610679026228\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":5,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"5\"],\"selectedMetric\":\"mem.bytes.used\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"5\"]},{\"tagk\":\"container\",\"tagv\":[\"=all\"]},{\"tagk\":\"namespace\",\"tagv\":[\"=all\"]},{\"tagk\":\"pod\",\"tagv\":[\"=all\"]}],\"counterListCount\":8}]}",
|
||||
"weight": 1
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"容器内存工作集大小\",\"type\":\"chart\",\"now\":\"1610679026228\",\"start\":\"1610675426228\",\"end\":\"1610679026228\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":5,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"5\"],\"selectedMetric\":\"mem.bytes.workingset\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"5\"]},{\"tagk\":\"container\",\"tagv\":[\"=all\"]},{\"tagk\":\"namespace\",\"tagv\":[\"=all\"]},{\"tagk\":\"pod\",\"tagv\":[\"=all\"]}],\"counterListCount\":8}]}",
|
||||
"weight": 2
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"容器内存使用率\",\"type\":\"chart\",\"now\":\"1610679026228\",\"start\":\"1610675426228\",\"end\":\"1610679026228\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":5,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"5\"],\"selectedMetric\":\"mem.bytes.used.percent\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"5\"]},{\"tagk\":\"container\",\"tagv\":[\"=all\"]},{\"tagk\":\"namespace\",\"tagv\":[\"=all\"]},{\"tagk\":\"pod\",\"tagv\":[\"=all\"]}],\"counterListCount\":8}]}",
|
||||
"weight": 3
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"容器内存工作集占用率(此为判定容器oom的依据)\",\"type\":\"chart\",\"now\":\"1611904149511\",\"start\":\"1611900549511\",\"end\":\"1611904149511\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"threshold\":null,\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":5,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"5\"],\"selectedMetric\":\"mem.bytes.workingset.percent\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"5\"]},{\"tagk\":\"container\",\"tagv\":[\"=all\"]},{\"tagk\":\"namespace\",\"tagv\":[\"=all\"]},{\"tagk\":\"pod\",\"tagv\":[\"=all\"]}],\"counterListCount\":5}],\"id\":717}",
|
||||
"weight": 4
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "文件系统和diskio(单位为byte)",
|
||||
"weight": 2,
|
||||
"charts": [
|
||||
{
|
||||
"configs": "{\"title\":\"容器文件系统总大小\",\"type\":\"chart\",\"now\":\"1610679026228\",\"start\":\"1610675426228\",\"end\":\"1610679026228\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":5,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"5\"],\"selectedMetric\":\"disk.bytes.total\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"5\"]},{\"tagk\":\"container\",\"tagv\":[\"=all\"]},{\"tagk\":\"device\",\"tagv\":[\"=all\"]},{\"tagk\":\"namespace\",\"tagv\":[\"=all\"]},{\"tagk\":\"pod\",\"tagv\":[\"=all\"]}],\"counterListCount\":8}]}",
|
||||
"weight": 0
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"容器文件系统已用大小\",\"type\":\"chart\",\"now\":\"1610679026228\",\"start\":\"1610675426228\",\"end\":\"1610679026228\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":5,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"5\"],\"selectedMetric\":\"disk.bytes.used\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"5\"]},{\"tagk\":\"container\",\"tagv\":[\"=all\"]},{\"tagk\":\"device\",\"tagv\":[\"=all\"]},{\"tagk\":\"namespace\",\"tagv\":[\"=all\"]},{\"tagk\":\"pod\",\"tagv\":[\"=all\"]}],\"counterListCount\":8}]}",
|
||||
"weight": 1
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"容器文件系统使用率\",\"type\":\"chart\",\"now\":\"1610679026228\",\"start\":\"1610675426228\",\"end\":\"1610679026228\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":5,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"5\"],\"selectedMetric\":\"disk.bytes.used.percent\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"5\"]},{\"tagk\":\"container\",\"tagv\":[\"=all\"]},{\"tagk\":\"device\",\"tagv\":[\"=all\"]},{\"tagk\":\"namespace\",\"tagv\":[\"=all\"]},{\"tagk\":\"pod\",\"tagv\":[\"=all\"]}],\"counterListCount\":8}]}",
|
||||
"weight": 2
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"容器分区读取速率\",\"type\":\"chart\",\"now\":\"1610679026228\",\"start\":\"1610675426228\",\"end\":\"1610679026228\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":5,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"5\"],\"selectedMetric\":\"disk.io.read.bytes\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"5\"]},{\"tagk\":\"container\",\"tagv\":[\"=all\"]},{\"tagk\":\"device\",\"tagv\":[\"=all\"]},{\"tagk\":\"namespace\",\"tagv\":[\"=all\"]},{\"tagk\":\"pod\",\"tagv\":[\"=all\"]}],\"counterListCount\":3}],\"id\":15}",
|
||||
"weight": 3
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"容器分区写入速率\",\"type\":\"chart\",\"now\":\"1610679026228\",\"start\":\"1610675426228\",\"end\":\"1610679026228\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":5,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"5\"],\"selectedMetric\":\"disk.io.write.bytes\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"5\"]},{\"tagk\":\"container\",\"tagv\":[\"=all\"]},{\"tagk\":\"device\",\"tagv\":[\"=all\"]},{\"tagk\":\"namespace\",\"tagv\":[\"=all\"]},{\"tagk\":\"pod\",\"tagv\":[\"=all\"]}],\"counterListCount\":3}]}",
|
||||
"weight": 4
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "系统",
|
||||
"weight": 4,
|
||||
"charts": [
|
||||
{
|
||||
"configs": "{\"title\":\"容器已用fd数\",\"type\":\"chart\",\"now\":\"1610679026228\",\"start\":\"1610675426228\",\"end\":\"1610679026228\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":5,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"5\"],\"selectedMetric\":\"sys.fd.count.used\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"5\"]},{\"tagk\":\"container\",\"tagv\":[\"=all\"]},{\"tagk\":\"namespace\",\"tagv\":[\"=all\"]},{\"tagk\":\"pod\",\"tagv\":[\"=all\"]}],\"counterListCount\":8}]}",
|
||||
"weight": 0
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"容器fd数上限数\",\"type\":\"chart\",\"now\":\"1611727764407\",\"start\":\"1611724164407\",\"end\":\"1611727764407\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":5,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"5\"],\"selectedMetric\":\"sys.fd.soft.ulimits\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"5\"]},{\"tagk\":\"container\",\"tagv\":[\"=all\"]},{\"tagk\":\"namespace\",\"tagv\":[\"=all\"]},{\"tagk\":\"node_ip\",\"tagv\":[\"=all\"]},{\"tagk\":\"node_name\",\"tagv\":[\"=all\"]},{\"tagk\":\"pod\",\"tagv\":[\"=all\"]}],\"counterListCount\":5}],\"id\":24}",
|
||||
"weight": 1
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"容器进程数\",\"type\":\"chart\",\"now\":\"1610679026228\",\"start\":\"1610675426228\",\"end\":\"1610679026228\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":5,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"5\"],\"selectedMetric\":\"sys.ps.process.count\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"5\"]},{\"tagk\":\"container\",\"tagv\":[\"=all\"]},{\"tagk\":\"namespace\",\"tagv\":[\"=all\"]},{\"tagk\":\"pod\",\"tagv\":[\"=all\"]}],\"counterListCount\":8}]}",
|
||||
"weight": 2
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"容器线程数\",\"type\":\"chart\",\"now\":\"1610679026228\",\"start\":\"1610675426228\",\"end\":\"1610679026228\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":5,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"5\"],\"selectedMetric\":\"sys.ps.thread.count\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"5\"]},{\"tagk\":\"container\",\"tagv\":[\"=all\"]},{\"tagk\":\"namespace\",\"tagv\":[\"=all\"]},{\"tagk\":\"pod\",\"tagv\":[\"=all\"]}],\"counterListCount\":8}]}",
|
||||
"weight": 3
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"容器socket数\",\"type\":\"chart\",\"now\":\"1610679026228\",\"start\":\"1610675426228\",\"end\":\"1610679026228\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":5,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"5\"],\"selectedMetric\":\"sys.socket.count.used\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"5\"]},{\"tagk\":\"container\",\"tagv\":[\"=all\"]},{\"tagk\":\"namespace\",\"tagv\":[\"=all\"]},{\"tagk\":\"pod\",\"tagv\":[\"=all\"]}],\"counterListCount\":8}]}",
|
||||
"weight": 4
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"容器状态=sleeping\",\"type\":\"chart\",\"now\":\"1611727764407\",\"start\":\"1611724164407\",\"end\":\"1611727764407\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":5,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"5\"],\"selectedMetric\":\"sys.task.state\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"5\"]},{\"tagk\":\"container\",\"tagv\":[\"=all\"]},{\"tagk\":\"namespace\",\"tagv\":[\"=all\"]},{\"tagk\":\"pod\",\"tagv\":[\"=all\"]},{\"tagk\":\"state\",\"tagv\":[\"sleeping\"]}],\"counterListCount\":5}],\"id\":28}",
|
||||
"weight": 5
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
|
@ -1,240 +0,0 @@
|
|||
[
|
||||
{
|
||||
"name": "k8s控制平面大盘",
|
||||
"node_path": "",
|
||||
"tags": [
|
||||
{
|
||||
"name": "apiserver (延迟单位为秒)",
|
||||
"weight": 0,
|
||||
"charts": [
|
||||
{
|
||||
"configs": "{\"title\":\"请求总qps\",\"type\":\"chart\",\"now\":\"1611729986666\",\"start\":\"1611726386666\",\"end\":\"1611729986666\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":[6],\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"apiserver_request_total_rate\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"code\",\"tagv\":[\"=all\"]},{\"tagk\":\"component\",\"tagv\":[\"=all\"]},{\"tagk\":\"contentType\",\"tagv\":[\"=all\"]},{\"tagk\":\"func_name\",\"tagv\":[\"=all\"]},{\"tagk\":\"group\",\"tagv\":[\"=all\"]},{\"tagk\":\"resource\",\"tagv\":[\"=all\"]},{\"tagk\":\"scope\",\"tagv\":[\"=all\"]},{\"tagk\":\"server_addr\",\"tagv\":[\"=all\"]},{\"tagk\":\"subresource\",\"tagv\":[\"=all\"]},{\"tagk\":\"verb\",\"tagv\":[\"=all\"]},{\"tagk\":\"version\",\"tagv\":[\"=all\"]}],\"counterListCount\":11,\"aggrFunc\":\"sum\",\"aggrGroup\":[]}],\"id\":29}",
|
||||
"weight": 0
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"请求成功率(code=2xx|3xx /code=all)\",\"type\":\"chart\",\"now\":\"1611729986666\",\"start\":\"1611726386666\",\"end\":\"1611729986666\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":[6],\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"apiserver_request_successful_rate\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"func_name\",\"tagv\":[\"=all\"]}],\"counterListCount\":1,\"aggrFunc\":\"sum\",\"aggrGroup\":[\"code\"]}],\"id\":76}",
|
||||
"weight": 1
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"wq 入队总qps\",\"type\":\"chart\",\"now\":\"1611729986666\",\"start\":\"1611726386666\",\"end\":\"1611729986666\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":[6],\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"workqueue_adds_total_rate\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"func_name\",\"tagv\":[\"api-server\"]},{\"tagk\":\"name\",\"tagv\":[\"=all\"]},{\"tagk\":\"server_addr\",\"tagv\":[\"=all\"]}],\"counterListCount\":20,\"aggrGroup\":[],\"aggrFunc\":\"sum\"}],\"id\":35}",
|
||||
"weight": 2
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"apiserver延迟平均值\",\"type\":\"chart\",\"now\":\"1611658938170\",\"start\":\"1611655338170\",\"end\":\"1611658938170\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":[6],\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"apiserver_request_duration_seconds_avg\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"func_name\",\"tagv\":[\"=all\"]}],\"counterListCount\":1,\"aggrGroup\":[\"code\"]}],\"id\":77}",
|
||||
"weight": 3
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\" apiserver延迟分位值\",\"type\":\"chart\",\"now\":\"1611658938170\",\"start\":\"1611655338170\",\"end\":\"1611658938170\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":[6],\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"apiserver_request_duration_seconds_all_quantile\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"func_name\",\"tagv\":[\"=all\"]},{\"tagk\":\"quantile\",\"tagv\":[\"=all\"]}],\"counterListCount\":4,\"aggrGroup\":[\"code\"]}],\"id\":77}",
|
||||
"weight": 4
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"apiserver verb=list的延迟分位值(其余verb自行配置)\",\"type\":\"chart\",\"now\":\"1611729986666\",\"start\":\"1611726386666\",\"end\":\"1611729986666\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":[6],\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"apiserver_request_duration_seconds_verb_list_quantile\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"func_name\",\"tagv\":[\"=all\"]},{\"tagk\":\"quantile\",\"tagv\":[\"=all\"]}],\"counterListCount\":4,\"aggrGroup\":[\"code\"]}],\"id\":78}",
|
||||
"weight": 5
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"apiserver响应大小分位值(单位byte)\",\"type\":\"chart\",\"now\":\"1611729986666\",\"start\":\"1611726386666\",\"end\":\"1611729986666\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":[6],\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"apiserver_response_sizes_quantile\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"func_name\",\"tagv\":[\"=all\"]},{\"tagk\":\"quantile\",\"tagv\":[\"=all\"]}],\"counterListCount\":4,\"aggrGroup\":[\"code\"]}],\"id\":80}",
|
||||
"weight": 6
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"apiserver workqueue 项目在队列中等待延迟分位值\",\"type\":\"chart\",\"now\":\"1611658938170\",\"start\":\"1611655338170\",\"end\":\"1611658938170\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":[6],\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"apiserver_workqueue_queue_duration_seconds_quantile\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"func_name\",\"tagv\":[\"=all\"]},{\"tagk\":\"quantile\",\"tagv\":[\"=all\"]}],\"counterListCount\":4,\"aggrGroup\":[\"code\"]}],\"id\":77}",
|
||||
"weight": 7
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"请求qps按code分布\",\"type\":\"chart\",\"now\":\"1611309504049\",\"start\":\"1611305904049\",\"end\":\"1611309504049\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":[6],\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"apiserver_request_total_rate\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"code\",\"tagv\":[\"=all\"]},{\"tagk\":\"component\",\"tagv\":[\"=all\"]},{\"tagk\":\"contentType\",\"tagv\":[\"=all\"]},{\"tagk\":\"func_name\",\"tagv\":[\"=all\"]},{\"tagk\":\"group\",\"tagv\":[\"=all\"]},{\"tagk\":\"resource\",\"tagv\":[\"=all\"]},{\"tagk\":\"scope\",\"tagv\":[\"=all\"]},{\"tagk\":\"server_addr\",\"tagv\":[\"=all\"]},{\"tagk\":\"subresource\",\"tagv\":[\"=all\"]},{\"tagk\":\"verb\",\"tagv\":[\"=all\"]},{\"tagk\":\"version\",\"tagv\":[\"=all\"]}],\"counterListCount\":9,\"aggrFunc\":\"sum\",\"aggrGroup\":[\"code\"]}],\"id\":29}",
|
||||
"weight": 8
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"请求qps按verb分布\",\"type\":\"chart\",\"now\":\"1611658938170\",\"start\":\"1611655338170\",\"end\":\"1611658938170\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":[6],\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"apiserver_request_total_rate\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"code\",\"tagv\":[\"=all\"]},{\"tagk\":\"component\",\"tagv\":[\"=all\"]},{\"tagk\":\"contentType\",\"tagv\":[\"=all\"]},{\"tagk\":\"func_name\",\"tagv\":[\"=all\"]},{\"tagk\":\"group\",\"tagv\":[\"=all\"]},{\"tagk\":\"resource\",\"tagv\":[\"=all\"]},{\"tagk\":\"scope\",\"tagv\":[\"=all\"]},{\"tagk\":\"server_addr\",\"tagv\":[\"=all\"]},{\"tagk\":\"subresource\",\"tagv\":[\"=all\"]},{\"tagk\":\"verb\",\"tagv\":[\"=all\"]},{\"tagk\":\"version\",\"tagv\":[\"=all\"]}],\"counterListCount\":11,\"aggrFunc\":\"sum\",\"aggrGroup\":[\"verb\"]}],\"id\":30}",
|
||||
"weight": 9
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"认证尝试数\",\"type\":\"chart\",\"now\":\"1611658938170\",\"start\":\"1611655338170\",\"end\":\"1611658938170\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":[6],\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"authentication_attempts_rate\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"func_name\",\"tagv\":[\"=all\"]},{\"tagk\":\"result\",\"tagv\":[\"=all\"]},{\"tagk\":\"server_addr\",\"tagv\":[\"=all\"]}],\"counterListCount\":2,\"aggrGroup\":[]}],\"id\":31}",
|
||||
"weight": 10
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"tls握手失败数\",\"type\":\"chart\",\"now\":\"1611658938170\",\"start\":\"1611655338170\",\"end\":\"1611658938170\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":[6],\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"apiserver_tls_handshake_errors_total_rate\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"func_name\",\"tagv\":[\"=all\"]},{\"tagk\":\"server_addr\",\"tagv\":[\"=all\"]}],\"counterListCount\":1,\"aggrGroup\":[]}],\"id\":32}",
|
||||
"weight": 11
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"正在处理的请求数量的高水位线\",\"type\":\"chart\",\"now\":\"1610681549046\",\"start\":\"1610677949046\",\"end\":\"1610681549046\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":[6],\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"apiserver_current_inflight_requests\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"request_kind\",\"tagv\":[\"=all\"]},{\"tagk\":\"server_addr\",\"tagv\":[\"=all\"]}],\"counterListCount\":2,\"aggrGroup\":[]}],\"id\":29}",
|
||||
"weight": 12
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"最近排队请求数量的高水位线\",\"type\":\"chart\",\"now\":\"1610681549046\",\"start\":\"1610677949046\",\"end\":\"1610681549046\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":[6],\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"apiserver_current_inqueue_requests\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"request_kind\",\"tagv\":[\"=all\"]},{\"tagk\":\"server_addr\",\"tagv\":[\"=all\"]}],\"counterListCount\":2,\"aggrGroup\":[]}],\"id\":29}",
|
||||
"weight": 13
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"wq retry数\",\"type\":\"chart\",\"now\":\"1611658938170\",\"start\":\"1611655338170\",\"end\":\"1611658938170\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":[6],\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"workqueue_retries_total_rate\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"func_name\",\"tagv\":[\"=all\"]},{\"tagk\":\"name\",\"tagv\":[\"=all\"]},{\"tagk\":\"server_addr\",\"tagv\":[\"=all\"]}],\"counterListCount\":19,\"aggrGroup\":[]}],\"id\":36}",
|
||||
"weight": 14
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"wq中最长运行时间\",\"type\":\"chart\",\"now\":\"1610681549046\",\"start\":\"1610677949046\",\"end\":\"1610681549046\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":[6],\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"workqueue_longest_running_processor_seconds\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"name\",\"tagv\":[\"=all\"]},{\"tagk\":\"server_addr\",\"tagv\":[\"=all\"]}],\"counterListCount\":20,\"aggrGroup\":[]}],\"id\":29}",
|
||||
"weight": 15
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "etcd",
|
||||
"weight": 1,
|
||||
"charts": [
|
||||
{
|
||||
"configs": "{\"title\":\"grpc qps\",\"type\":\"chart\",\"now\":\"1611729986666\",\"start\":\"1611726386666\",\"end\":\"1611729986666\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":[6],\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"grpc_server_handled_total_rate\",\"selectedTagkv\":[{\"tagk\":\"endpoint\",\"tagv\":[\"__nid__6__\"]},{\"tagk\":\"func_name\",\"tagv\":[\"=all\"]},{\"tagk\":\"grpc_code\",\"tagv\":[\"=all\"]},{\"tagk\":\"grpc_method\",\"tagv\":[\"=all\"]},{\"tagk\":\"grpc_service\",\"tagv\":[\"=all\"]},{\"tagk\":\"grpc_type\",\"tagv\":[\"=all\"]},{\"tagk\":\"server_addr\",\"tagv\":[\"=all\"]}],\"counterListCount\":697,\"aggrFunc\":\"sum\",\"aggrGroup\":[]}],\"id\":93}",
|
||||
"weight": 0
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"db 文件总大小\",\"type\":\"chart\",\"now\":\"1611727764211\",\"start\":\"1611724164211\",\"end\":\"1611727764211\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":[6],\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"etcd_server_quota_backend_bytes\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"func_name\",\"tagv\":[\"=all\"]},{\"tagk\":\"server_addr\",\"tagv\":[\"=all\"]}],\"counterListCount\":1,\"aggrFunc\":\"sum\"}],\"chartTypeOptions\":{\"chartType\":\"singleValue\",\"targetValue\":\"avg\",\"subType\":\"normal\",\"valueMap\":\"range\",\"mapConf\":[{}]},\"id\":134}",
|
||||
"weight": 1
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"当前db文件大小\",\"type\":\"chart\",\"now\":\"1611720851130\",\"start\":\"1611717251130\",\"end\":\"1611720851130\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":[6],\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"etcd_mvcc_db_total_size_in_bytes\",\"selectedTagkv\":[{\"tagk\":\"endpoint\",\"tagv\":[\"__nid__6__\"]},{\"tagk\":\"func_name\",\"tagv\":[\"=all\"]},{\"tagk\":\"server_addr\",\"tagv\":[\"=all\"]}],\"counterListCount\":1}],\"id\":39}",
|
||||
"weight": 2
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"etcd入流量\",\"type\":\"chart\",\"now\":\"1611729986666\",\"start\":\"1611726386666\",\"end\":\"1611729986666\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":[6],\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"etcd_network_client_grpc_received_bytes_total_rate\",\"selectedTagkv\":[{\"tagk\":\"endpoint\",\"tagv\":[\"__nid__6__\"]},{\"tagk\":\"func_name\",\"tagv\":[\"=all\"]},{\"tagk\":\"server_addr\",\"tagv\":[\"=all\"]}],\"counterListCount\":1}],\"id\":91}",
|
||||
"weight": 3
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"etcd出流量\",\"type\":\"chart\",\"now\":\"1611729986666\",\"start\":\"1611726386666\",\"end\":\"1611729986666\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":[6],\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"etcd_network_client_grpc_sent_bytes_total_rate\",\"selectedTagkv\":[{\"tagk\":\"endpoint\",\"tagv\":[\"__nid__6__\"]},{\"tagk\":\"func_name\",\"tagv\":[\"=all\"]},{\"tagk\":\"server_addr\",\"tagv\":[\"=all\"]}],\"counterListCount\":1}],\"id\":92}",
|
||||
"weight": 4
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"总key数\",\"type\":\"chart\",\"now\":\"1611727764211\",\"start\":\"1611724164211\",\"end\":\"1611727764211\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":[6],\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"etcd_debugging_mvcc_keys_total\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"func_name\",\"tagv\":[\"=all\"]},{\"tagk\":\"server_addr\",\"tagv\":[\"=all\"]}],\"counterListCount\":1,\"aggrFunc\":\"sum\"}],\"chartTypeOptions\":{\"chartType\":\"singleValue\",\"targetValue\":\"avg\",\"subType\":\"normal\",\"valueMap\":\"range\",\"mapConf\":[{}]},\"id\":135}",
|
||||
"weight": 5
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"逻辑db文件大小\",\"type\":\"chart\",\"now\":\"1611729986666\",\"start\":\"1611726386666\",\"end\":\"1611729986666\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":[6],\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"etcd_mvcc_db_total_size_in_use_in_bytes\",\"selectedTagkv\":[{\"tagk\":\"endpoint\",\"tagv\":[\"__nid__6__\"]},{\"tagk\":\"func_name\",\"tagv\":[\"=all\"]},{\"tagk\":\"server_addr\",\"tagv\":[\"=all\"]}],\"counterListCount\":1}],\"id\":86}",
|
||||
"weight": 6
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"wal fsync延迟分位值\",\"type\":\"chart\",\"now\":\"1611729986666\",\"start\":\"1611726386666\",\"end\":\"1611729986666\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":[6],\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"etcd_disk_wal_fsync_duration_seconds_quantile\",\"selectedTagkv\":[{\"tagk\":\"endpoint\",\"tagv\":[\"__nid__6__\"]},{\"tagk\":\"func_name\",\"tagv\":[\"=all\"]},{\"tagk\":\"quantile\",\"tagv\":[\"=all\"]}],\"counterListCount\":4}],\"id\":89}",
|
||||
"weight": 7
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"db sync延迟分位值\",\"type\":\"chart\",\"now\":\"1611729986666\",\"start\":\"1611726386666\",\"end\":\"1611729986666\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":[6],\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"etcd_disk_backend_commit_duration_seconds_quantile\",\"selectedTagkv\":[{\"tagk\":\"endpoint\",\"tagv\":[\"__nid__6__\"]},{\"tagk\":\"func_name\",\"tagv\":[\"=all\"]},{\"tagk\":\"quantile\",\"tagv\":[\"=all\"]}],\"counterListCount\":4}],\"id\":90}",
|
||||
"weight": 8
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "scheduler指标",
|
||||
"weight": 2,
|
||||
"charts": [
|
||||
{
|
||||
"configs": "{\"title\":\"调度队列pending pod数\",\"type\":\"chart\",\"now\":\"1610681549046\",\"start\":\"1610677949046\",\"end\":\"1610681549046\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":[6],\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"scheduler_pending_pods\",\"selectedTagkv\":[{\"tagk\":\"endpoint\",\"tagv\":[\"__nid__6__\"]},{\"tagk\":\"queue\",\"tagv\":[\"=all\"]},{\"tagk\":\"server_addr\",\"tagv\":[\"=all\"]}],\"counterListCount\":3}],\"id\":41}",
|
||||
"weight": 0
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\" scheduler 端到端调度平均延迟\",\"type\":\"chart\",\"now\":\"1611658938170\",\"start\":\"1611655338170\",\"end\":\"1611658938170\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":[6],\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"scheduler_e2e_scheduling_duration_seconds_avg\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"func_name\",\"tagv\":[\"=all\"]}],\"counterListCount\":1}],\"id\":41}",
|
||||
"weight": 1
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"scheduler 成功调度一个pod 的平均尝试次数\",\"type\":\"chart\",\"now\":\"1611658938170\",\"start\":\"1611655338170\",\"end\":\"1611658938170\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":[6],\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"scheduler_pod_scheduling_attempts_avg\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"func_name\",\"tagv\":[\"=all\"]}],\"counterListCount\":1}],\"id\":41}",
|
||||
"weight": 2
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"请求apiserver速率\",\"type\":\"chart\",\"now\":\"1611661026507\",\"start\":\"1611657426507\",\"end\":\"1611661026507\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":[6],\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"rest_client_requests_total_rate\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"code\",\"tagv\":[\"=all\"]},{\"tagk\":\"func_name\",\"tagv\":[\"kube-scheduler\"]},{\"tagk\":\"host\",\"tagv\":[\"=all\"]},{\"tagk\":\"method\",\"tagv\":[\"=all\"]},{\"tagk\":\"server_addr\",\"tagv\":[\"=all\"]}],\"counterListCount\":3}],\"id\":106}",
|
||||
"weight": 3
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"请求apiserver延迟\",\"type\":\"chart\",\"now\":\"1611661026507\",\"start\":\"1611657426507\",\"end\":\"1611661026507\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":[6],\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"scheduler_rest_client_request_duration_seconds_quantile\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"func_name\",\"tagv\":[\"=all\"]},{\"tagk\":\"quantile\",\"tagv\":[\"=all\"]}],\"counterListCount\":4}],\"id\":108}",
|
||||
"weight": 4
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"workqueue 项目在队列中等待延迟分位值\",\"type\":\"chart\",\"now\":\"1611730820804\",\"start\":\"1611727220804\",\"end\":\"1611730820804\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":[6],\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"scheduler_workqueue_queue_duration_seconds_quantile\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"func_name\",\"tagv\":[\"=all\"]},{\"tagk\":\"quantile\",\"tagv\":[\"=all\"]}],\"counterListCount\":4}],\"id\":136}",
|
||||
"weight": 5
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "controller-manager",
|
||||
"weight": 3,
|
||||
"charts": [
|
||||
{
|
||||
"configs": "{\"title\":\"工作队列新增速率\",\"type\":\"chart\",\"now\":\"1611658938170\",\"start\":\"1611655338170\",\"end\":\"1611658938170\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":[6],\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"workqueue_adds_total_rate\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"func_name\",\"tagv\":[\"kube-controller-manager\"]},{\"tagk\":\"name\",\"tagv\":[\"=all\"]},{\"tagk\":\"server_addr\",\"tagv\":[\"=all\"]}],\"counterListCount\":44,\"aggrFunc\":\"sum\",\"aggrGroup\":[\"func_name\",\"server_addr\"]}],\"id\":42}",
|
||||
"weight": 0
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"当前工作队列深度\",\"type\":\"chart\",\"now\":\"1610682325050\",\"start\":\"1610678725050\",\"end\":\"1610682325050\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":[6],\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"workqueue_depth\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"name\",\"tagv\":[\"=all\"]},{\"tagk\":\"server_addr\",\"tagv\":[\"=all\"]}],\"counterListCount\":44}]}",
|
||||
"weight": 1
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"kube-api请求速率\",\"type\":\"chart\",\"now\":\"1611658938170\",\"start\":\"1611655338170\",\"end\":\"1611658938170\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":[6],\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"rest_client_requests_total_rate\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"code\",\"tagv\":[\"=all\"]},{\"tagk\":\"func_name\",\"tagv\":[\"kube-controller-manager\"]},{\"tagk\":\"host\",\"tagv\":[\"=all\"]},{\"tagk\":\"method\",\"tagv\":[\"=all\"]},{\"tagk\":\"server_addr\",\"tagv\":[\"=all\"]}],\"counterListCount\":12,\"aggrFunc\":\"sum\",\"aggrGroup\":[\"func_name\",\"server_addr\"]}],\"id\":44}",
|
||||
"weight": 2
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"controller_manager workqueue 项目在队列中等待延迟分位值\",\"type\":\"chart\",\"now\":\"1611658938170\",\"start\":\"1611655338170\",\"end\":\"1611658938170\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":[6],\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"controller_manager_workqueue_queue_duration_seconds_quantile\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"func_name\",\"tagv\":[\"=all\"]},{\"tagk\":\"quantile\",\"tagv\":[\"=all\"]}],\"counterListCount\":4}]}",
|
||||
"weight": 3
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"controller_manager请求apiserver 的延迟分位值 \",\"type\":\"chart\",\"now\":\"1611658938170\",\"start\":\"1611655338170\",\"end\":\"1611658938170\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":[6],\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"controller_manager_rest_client_request_duration_seconds_quantile\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"func_name\",\"tagv\":[\"=all\"]},{\"tagk\":\"quantile\",\"tagv\":[\"=all\"]}],\"counterListCount\":4}]}",
|
||||
"weight": 4
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"请求apiserver延迟\",\"type\":\"chart\",\"now\":\"1611730899017\",\"start\":\"1611727299017\",\"end\":\"1611730899017\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":[6],\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"controller_manager_rest_client_request_duration_seconds_quantile\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"func_name\",\"tagv\":[\"=all\"]},{\"tagk\":\"quantile\",\"tagv\":[\"=all\"]}],\"counterListCount\":4}],\"id\":137}",
|
||||
"weight": 6
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "coredns",
|
||||
"weight": 4,
|
||||
"charts": [
|
||||
{
|
||||
"configs": "{\"title\":\"解析请求数\",\"type\":\"chart\",\"now\":\"1611658255494\",\"start\":\"1611654655494\",\"end\":\"1611658255494\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":[6],\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"coredns_dns_requests_total_rate\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"family\",\"tagv\":[\"=all\"]},{\"tagk\":\"func_name\",\"tagv\":[\"=all\"]},{\"tagk\":\"proto\",\"tagv\":[\"=all\"]},{\"tagk\":\"server\",\"tagv\":[\"=all\"]},{\"tagk\":\"server_addr\",\"tagv\":[\"=all\"]},{\"tagk\":\"type\",\"tagv\":[\"=all\"]},{\"tagk\":\"zone\",\"tagv\":[\"=all\"]}],\"counterListCount\":6,\"aggrFunc\":\"sum\",\"aggrGroup\":[]}],\"id\":94}",
|
||||
"weight": 0
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"解析响应数\",\"type\":\"chart\",\"now\":\"1611658255494\",\"start\":\"1611654655494\",\"end\":\"1611658255494\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":[6],\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"coredns_dns_responses_total_rate\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"func_name\",\"tagv\":[\"=all\"]},{\"tagk\":\"rcode\",\"tagv\":[\"=all\"]},{\"tagk\":\"server\",\"tagv\":[\"=all\"]},{\"tagk\":\"server_addr\",\"tagv\":[\"=all\"]},{\"tagk\":\"zone\",\"tagv\":[\"=all\"]}],\"counterListCount\":6,\"aggrFunc\":\"sum\",\"aggrGroup\":[]}],\"id\":95}",
|
||||
"weight": 1
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"缓存记录数\",\"type\":\"chart\",\"now\":\"1611658255494\",\"start\":\"1611654655494\",\"end\":\"1611658255494\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":[6],\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"coredns_cache_entries\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"func_name\",\"tagv\":[\"=all\"]},{\"tagk\":\"server\",\"tagv\":[\"=all\"]},{\"tagk\":\"server_addr\",\"tagv\":[\"=all\"]},{\"tagk\":\"type\",\"tagv\":[\"=all\"]}],\"counterListCount\":4,\"aggrGroup\":[]}],\"id\":96}",
|
||||
"weight": 2
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"缓存命中数\",\"type\":\"chart\",\"now\":\"1611658255494\",\"start\":\"1611654655494\",\"end\":\"1611658255494\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":[6],\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"coredns_cache_hits_total_rate\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"func_name\",\"tagv\":[\"=all\"]},{\"tagk\":\"server\",\"tagv\":[\"=all\"]},{\"tagk\":\"server_addr\",\"tagv\":[\"=all\"]},{\"tagk\":\"type\",\"tagv\":[\"=all\"]}],\"counterListCount\":4,\"aggrFunc\":\"sum\",\"aggrGroup\":[]}],\"id\":94}",
|
||||
"weight": 3
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"解析延迟记录分位值\",\"type\":\"chart\",\"now\":\"1611658255494\",\"start\":\"1611654655494\",\"end\":\"1611658255494\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":[6],\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"coredns_dns_request_duration_seconds_quantile\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"func_name\",\"tagv\":[\"=all\"]},{\"tagk\":\"quantile\",\"tagv\":[\"=all\"]}],\"counterListCount\":4,\"aggrGroup\":[]}],\"id\":98}",
|
||||
"weight": 4
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"解析响应大小分位值\",\"type\":\"chart\",\"now\":\"1611658255494\",\"start\":\"1611654655494\",\"end\":\"1611658255494\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":[6],\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"coredns_dns_response_size_bytes_quantile\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"func_name\",\"tagv\":[\"=all\"]},{\"tagk\":\"quantile\",\"tagv\":[\"=all\"]}],\"counterListCount\":4,\"aggrGroup\":[]}],\"id\":98}",
|
||||
"weight": 5
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "进程监控",
|
||||
"weight": 5,
|
||||
"charts": [
|
||||
{
|
||||
"configs": "{\"title\":\"进程常驻内存大小(单位byte)\",\"type\":\"chart\",\"now\":\"1611730899017\",\"start\":\"1611727299017\",\"end\":\"1611730899017\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":[6],\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"process_resident_memory_bytes\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"func_name\",\"tagv\":[\"=all\"]},{\"tagk\":\"server_addr\",\"tagv\":[\"=all\"]}],\"counterListCount\":6}],\"id\":100}",
|
||||
"weight": 0
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"进程打开fd数\",\"type\":\"chart\",\"now\":\"1611658255494\",\"start\":\"1611654655494\",\"end\":\"1611658255494\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":[6],\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"process_open_fds\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"func_name\",\"tagv\":[\"=all\"]},{\"tagk\":\"server_addr\",\"tagv\":[\"=all\"]}],\"counterListCount\":8}]}",
|
||||
"weight": 1
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"进程cpu核数\",\"type\":\"chart\",\"now\":\"1611658255494\",\"start\":\"1611654655494\",\"end\":\"1611658255494\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":[6],\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"process_cpu_seconds_total_rate\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"func_name\",\"tagv\":[\"=all\"]},{\"tagk\":\"server_addr\",\"tagv\":[\"=all\"]}],\"counterListCount\":8}]}",
|
||||
"weight": 2
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"goroutine数量\",\"type\":\"chart\",\"now\":\"1611658255494\",\"start\":\"1611654655494\",\"end\":\"1611658255494\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":[6],\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"go_goroutines\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"func_name\",\"tagv\":[\"=all\"]},{\"tagk\":\"server_addr\",\"tagv\":[\"=all\"]}],\"counterListCount\":8}]}",
|
||||
"weight": 3
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"最长gc耗时(单位秒)\",\"type\":\"chart\",\"now\":\"1611730899017\",\"start\":\"1611727299017\",\"end\":\"1611730899017\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":[6],\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"go_gc_duration_seconds\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"func_name\",\"tagv\":[\"=all\"]},{\"tagk\":\"quantile\",\"tagv\":[\"1\"]},{\"tagk\":\"server_addr\",\"tagv\":[\"=all\"]}],\"counterListCount\":6}],\"id\":104}",
|
||||
"weight": 4
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"alloc 内存\",\"type\":\"chart\",\"now\":\"1611658255494\",\"start\":\"1611654655494\",\"end\":\"1611658255494\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":[6],\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"go_memstats_alloc_bytes\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"func_name\",\"tagv\":[\"=all\"]},{\"tagk\":\"server_addr\",\"tagv\":[\"=all\"]}],\"counterListCount\":8}],\"id\":104}",
|
||||
"weight": 5
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
|
@ -1,216 +0,0 @@
|
|||
[
|
||||
{
|
||||
"name": "k8s资源使用情况",
|
||||
"node_path": "",
|
||||
"tags": [
|
||||
{
|
||||
"name": "资源数总览",
|
||||
"weight": 0,
|
||||
"charts": [
|
||||
{
|
||||
"configs": "{\"title\":\"pod总数\",\"type\":\"chart\",\"now\":\"1611727764211\",\"start\":\"1611724164211\",\"end\":\"1611727764211\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":6,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"kube_pod_info\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"host_ip\",\"tagv\":[\"=all\"]},{\"tagk\":\"namespace\",\"tagv\":[\"=all\"]},{\"tagk\":\"node\",\"tagv\":[\"=all\"]},{\"tagk\":\"pod\",\"tagv\":[\"=all\"]},{\"tagk\":\"pod_ip\",\"tagv\":[\"=all\"]}],\"counterListCount\":18,\"aggrFunc\":\"sum\"}],\"chartTypeOptions\":{\"chartType\":\"singleValue\",\"targetValue\":\"avg\",\"subType\":\"normal\",\"valueMap\":\"range\",\"mapConf\":[{}]},\"id\":117}",
|
||||
"weight": 0
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"容器总数\",\"type\":\"chart\",\"now\":\"1611727764211\",\"start\":\"1611724164211\",\"end\":\"1611727764211\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":6,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"kube_configmap_info\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"configmap\",\"tagv\":[\"=all\"]},{\"tagk\":\"namespace\",\"tagv\":[\"=all\"]}],\"counterListCount\":21,\"aggrFunc\":\"sum\"}],\"chartTypeOptions\":{\"chartType\":\"singleValue\",\"targetValue\":\"avg\",\"subType\":\"normal\",\"valueMap\":\"range\",\"mapConf\":[{}]},\"id\":117}",
|
||||
"weight": 1
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"node总数\",\"type\":\"chart\",\"now\":\"1611727764211\",\"start\":\"1611724164211\",\"end\":\"1611727764211\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":6,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"kube_node_info\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"kernel_version\",\"tagv\":[\"=all\"]},{\"tagk\":\"node\",\"tagv\":[\"=all\"]},{\"tagk\":\"os_image\",\"tagv\":[\"=all\"]}],\"counterListCount\":2,\"aggrFunc\":\"sum\"}],\"chartTypeOptions\":{\"chartType\":\"singleValue\",\"targetValue\":\"avg\",\"subType\":\"normal\",\"valueMap\":\"range\",\"mapConf\":[{}]},\"id\":117}",
|
||||
"weight": 2
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"deployment总数\",\"type\":\"chart\",\"now\":\"1611727764211\",\"start\":\"1611724164211\",\"end\":\"1611727764211\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":6,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"kube_deployment_labels\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"deployment\",\"tagv\":[\"=all\"]},{\"tagk\":\"namespace\",\"tagv\":[\"=all\"]}],\"counterListCount\":8,\"aggrFunc\":\"sum\"}],\"chartTypeOptions\":{\"chartType\":\"singleValue\",\"targetValue\":\"avg\",\"subType\":\"normal\",\"valueMap\":\"range\",\"mapConf\":[{}]},\"id\":117}",
|
||||
"weight": 3
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"daemonset总数\",\"type\":\"chart\",\"now\":\"1611727764211\",\"start\":\"1611724164211\",\"end\":\"1611727764211\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":6,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"kube_daemonset_labels\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"daemonset\",\"tagv\":[\"=all\"]},{\"tagk\":\"namespace\",\"tagv\":[\"=all\"]}],\"counterListCount\":4,\"aggrFunc\":\"sum\"}],\"chartTypeOptions\":{\"chartType\":\"singleValue\",\"targetValue\":\"avg\",\"subType\":\"normal\",\"valueMap\":\"range\",\"mapConf\":[{}]},\"id\":117}",
|
||||
"weight": 4
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"statefulset总数\",\"type\":\"chart\",\"now\":\"1611727764211\",\"start\":\"1611724164211\",\"end\":\"1611727764211\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":6,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"kube_statefulset_labels\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"namespace\",\"tagv\":[\"=all\"]},{\"tagk\":\"statefulset\",\"tagv\":[\"=all\"]}],\"counterListCount\":1,\"aggrFunc\":\"sum\"}],\"chartTypeOptions\":{\"chartType\":\"singleValue\",\"targetValue\":\"avg\",\"subType\":\"normal\",\"valueMap\":\"range\",\"mapConf\":[{}]},\"id\":117}",
|
||||
"weight": 5
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"configmap总数\",\"type\":\"chart\",\"now\":\"1611727764211\",\"start\":\"1611724164211\",\"end\":\"1611727764211\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":6,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"kube_configmap_info\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"configmap\",\"tagv\":[\"=all\"]},{\"tagk\":\"namespace\",\"tagv\":[\"=all\"]}],\"counterListCount\":21,\"aggrFunc\":\"sum\"}],\"chartTypeOptions\":{\"chartType\":\"singleValue\",\"targetValue\":\"avg\",\"subType\":\"normal\",\"valueMap\":\"range\",\"mapConf\":[{}]},\"id\":117}",
|
||||
"weight": 6
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"pvc总数\",\"type\":\"chart\",\"now\":\"1611727764211\",\"start\":\"1611724164211\",\"end\":\"1611727764211\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":6,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"kube_persistentvolumeclaim_info\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"namespace\",\"tagv\":[\"=all\"]},{\"tagk\":\"persistentvolumeclaim\",\"tagv\":[\"=all\"]},{\"tagk\":\"storageclass\",\"tagv\":[\"=all\"]},{\"tagk\":\"volumename\",\"tagv\":[\"=all\"]}],\"counterListCount\":1,\"aggrFunc\":\"sum\"}],\"chartTypeOptions\":{\"chartType\":\"singleValue\",\"targetValue\":\"avg\",\"subType\":\"normal\",\"valueMap\":\"range\",\"mapConf\":[{}]},\"id\":117}",
|
||||
"weight": 7
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"secret总数\",\"type\":\"chart\",\"now\":\"1611727764211\",\"start\":\"1611724164211\",\"end\":\"1611727764211\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":6,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"kube_secret_info\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"namespace\",\"tagv\":[\"=all\"]},{\"tagk\":\"secret\",\"tagv\":[\"=all\"]}],\"counterListCount\":57,\"aggrFunc\":\"sum\"}],\"chartTypeOptions\":{\"chartType\":\"singleValue\",\"targetValue\":\"avg\",\"subType\":\"normal\",\"valueMap\":\"range\",\"mapConf\":[{}]},\"id\":117}",
|
||||
"weight": 8
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "node指标",
|
||||
"weight": 1,
|
||||
"charts": [
|
||||
{
|
||||
"configs": "{\"title\":\"节点总数\",\"type\":\"chart\",\"now\":\"1611727764211\",\"start\":\"1611724164211\",\"end\":\"1611727764211\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":6,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"kube_node_info\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"kernel_version\",\"tagv\":[\"=all\"]},{\"tagk\":\"node\",\"tagv\":[\"=all\"]},{\"tagk\":\"os_image\",\"tagv\":[\"=all\"]}],\"counterListCount\":2,\"aggrFunc\":\"sum\"}],\"chartTypeOptions\":{\"chartType\":\"singleValue\",\"targetValue\":\"avg\",\"subType\":\"normal\",\"valueMap\":\"range\",\"mapConf\":[{}]},\"id\":112}",
|
||||
"weight": 0
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"节点可以分配cpu核数\",\"type\":\"chart\",\"now\":\"1611728391441\",\"start\":\"1611724791441\",\"end\":\"1611728391441\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":6,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"kube_node_status_allocatable_cpu_cores\",\"selectedTagkv\":[{\"tagk\":\"endpoint\",\"tagv\":[\"10.178.27.152\"]},{\"tagk\":\"node\",\"tagv\":[\"=all\"]}],\"counterListCount\":2}],\"chartTypeOptions\":{\"chartType\":\"table\",\"tableType\":\"stats\",\"columnsKey\":[\"last\"],\"valueMap\":\"range\",\"mapConf\":[{\"text\":\"\",\"from\":null,\"to\":null}]},\"id\":45}",
|
||||
"weight": 1
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"节点可以分配内存总量(单位:字节)\",\"type\":\"chart\",\"now\":\"1611728391441\",\"start\":\"1611724791441\",\"end\":\"1611728391441\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":6,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"kube_node_status_allocatable_memory_bytes\",\"selectedTagkv\":[{\"tagk\":\"endpoint\",\"tagv\":[\"10.178.27.152\"]},{\"tagk\":\"node\",\"tagv\":[\"=all\"]}],\"counterListCount\":2}],\"chartTypeOptions\":{\"chartType\":\"table\",\"tableType\":\"stats\",\"columnsKey\":[\"last\"],\"valueMap\":\"range\",\"mapConf\":[{}]},\"id\":46}",
|
||||
"weight": 2
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"节点可运行的pod总数\",\"type\":\"chart\",\"now\":\"1611728391441\",\"start\":\"1611724791441\",\"end\":\"1611728391441\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":6,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"kube_node_status_capacity_pods\",\"selectedTagkv\":[{\"tagk\":\"endpoint\",\"tagv\":[\"10.178.27.152\"]},{\"tagk\":\"node\",\"tagv\":[\"=all\"]}],\"counterListCount\":2}],\"chartTypeOptions\":{\"chartType\":\"pie\",\"pieType\":\"pie\",\"targetValue\":\"avg\"},\"id\":47}",
|
||||
"weight": 3
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"运行pod数\",\"type\":\"chart\",\"now\":\"1611827407063\",\"start\":\"1611823807063\",\"end\":\"1611827407063\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":6,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"kube_node_pod_num_value\",\"selectedTagkv\":[],\"counterListCount\":2}],\"id\":50}",
|
||||
"weight": 4
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"内存压力节点\",\"type\":\"chart\",\"now\":\"1611728391441\",\"start\":\"1611724791441\",\"end\":\"1611728391441\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":6,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"kube_node_status_condition\",\"selectedTagkv\":[{\"tagk\":\"endpoint\",\"tagv\":[\"10.178.27.152\"]},{\"tagk\":\"condition\",\"tagv\":[\"MemoryPressure\"]},{\"tagk\":\"node\",\"tagv\":[\"=all\"]},{\"tagk\":\"status\",\"tagv\":[\"true\"]}],\"counterListCount\":2}],\"id\":50}",
|
||||
"weight": 5
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"网络不可用节点\",\"type\":\"chart\",\"now\":\"1611728391441\",\"start\":\"1611724791441\",\"end\":\"1611728391441\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":6,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"kube_node_status_condition\",\"selectedTagkv\":[{\"tagk\":\"endpoint\",\"tagv\":[\"10.178.27.152\"]},{\"tagk\":\"condition\",\"tagv\":[\"NetworkUnavailable\"]},{\"tagk\":\"node\",\"tagv\":[\"=all\"]},{\"tagk\":\"status\",\"tagv\":[\"true\"]}],\"counterListCount\":2}],\"id\":51}",
|
||||
"weight": 6
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"cpu限制核数\",\"type\":\"chart\",\"now\":\"1611826614336\",\"start\":\"1611823014336\",\"end\":\"1611826614336\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":6,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"kube_node_pod_container_cpu_limits_value\",\"selectedTagkv\":[],\"counterListCount\":2}],\"id\":50}",
|
||||
"weight": 7
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"cpu限制率\",\"type\":\"chart\",\"now\":\"1611826681754\",\"start\":\"1611823081754\",\"end\":\"1611826681754\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":6,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"kube_node_pod_container_cpu_requests_percent\",\"selectedTagkv\":[],\"counterListCount\":2}],\"id\":50}",
|
||||
"weight": 8
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"cpu请求核数\",\"type\":\"chart\",\"now\":\"1611827407063\",\"start\":\"1611823807063\",\"end\":\"1611827407063\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":6,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"kube_node_pod_container_cpu_requests_value\",\"selectedTagkv\":[],\"counterListCount\":2}],\"id\":50}",
|
||||
"weight": 9
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"cpu请求率\",\"type\":\"chart\",\"now\":\"1611827407063\",\"start\":\"1611823807063\",\"end\":\"1611827407063\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":6,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"kube_node_pod_container_cpu_requests_percent\",\"selectedTagkv\":[],\"counterListCount\":2}],\"id\":50}",
|
||||
"weight": 10
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"内存请求\",\"type\":\"chart\",\"now\":\"1611827407063\",\"start\":\"1611823807063\",\"end\":\"1611827407063\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":6,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"kube_node_pod_container_memory_requests_value\",\"selectedTagkv\":[],\"counterListCount\":2}],\"id\":50}",
|
||||
"weight": 11
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"内存请求率\",\"type\":\"chart\",\"now\":\"1611827407063\",\"start\":\"1611823807063\",\"end\":\"1611827407063\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":6,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"kube_node_pod_container_memory_requests_percent\",\"selectedTagkv\":[],\"counterListCount\":2}],\"id\":50}",
|
||||
"weight": 12
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"内存限制\",\"type\":\"chart\",\"now\":\"1611827407063\",\"start\":\"1611823807063\",\"end\":\"1611827407063\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":6,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"kube_node_pod_container_memory_limits_value\",\"selectedTagkv\":[],\"counterListCount\":2}],\"id\":50}",
|
||||
"weight": 13
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"内存限制率\",\"type\":\"chart\",\"now\":\"1611828002150\",\"start\":\"1611824402150\",\"end\":\"1611828002150\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":6,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"kube_node_pod_container_memory_limits_percent\",\"selectedTagkv\":[],\"counterListCount\":2}],\"id\":381}",
|
||||
"weight": 14
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"运行pod数分位比\",\"type\":\"chart\",\"now\":\"1611827407063\",\"start\":\"1611823807063\",\"end\":\"1611827407063\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":6,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"kube_node_pod_num_percent\",\"selectedTagkv\":[],\"counterListCount\":2}],\"id\":50}",
|
||||
"weight": 15
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "pod指标",
|
||||
"weight": 2,
|
||||
"charts": [
|
||||
{
|
||||
"configs": "{\"title\":\"pengding 容器数\",\"type\":\"chart\",\"now\":\"1611728391441\",\"start\":\"1611724791441\",\"end\":\"1611728391441\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":6,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"kube_pod_status_phase\",\"selectedTagkv\":[{\"tagk\":\"endpoint\",\"tagv\":[\"10.178.27.152\",\"__nid__5__\"]},{\"tagk\":\"namespace\",\"tagv\":[\"=all\"]},{\"tagk\":\"phase\",\"tagv\":[\"Pending\"]},{\"tagk\":\"pod\",\"tagv\":[\"=all\"]}],\"counterListCount\":18,\"aggrFunc\":\"sum\",\"aggrGroup\":[\"pod\"]}],\"chartTypeOptions\":{\"chartType\":\"singleValue\",\"targetValue\":\"avg\",\"subType\":\"normal\",\"valueMap\":\"range\",\"mapConf\":[{}]},\"id\":53}",
|
||||
"weight": 0
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"pengding 容器数\",\"type\":\"chart\",\"now\":\"1611728391441\",\"start\":\"1611724791441\",\"end\":\"1611728391441\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":6,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"kube_pod_container_status_waiting\",\"selectedTagkv\":[{\"tagk\":\"endpoint\",\"tagv\":[\"10.178.27.152\",\"__nid__5__\"]},{\"tagk\":\"container\",\"tagv\":[\"=all\"]},{\"tagk\":\"namespace\",\"tagv\":[\"=all\"]},{\"tagk\":\"pod\",\"tagv\":[\"=all\"]}],\"counterListCount\":18,\"aggrFunc\":\"sum\",\"aggrGroup\":[\"pod\"]}],\"chartTypeOptions\":{\"chartType\":\"singleValue\",\"targetValue\":\"avg\",\"subType\":\"normal\",\"valueMap\":\"range\",\"mapConf\":[{}]},\"id\":54}",
|
||||
"weight": 1
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"pod处于waiting状态\",\"type\":\"chart\",\"now\":\"1611728391441\",\"start\":\"1611724791441\",\"end\":\"1611728391441\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":6,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"kube_pod_container_status_waiting\",\"selectedTagkv\":[{\"tagk\":\"endpoint\",\"tagv\":[\"10.178.27.152\",\"__nid__5__\"]},{\"tagk\":\"container\",\"tagv\":[\"=all\"]},{\"tagk\":\"namespace\",\"tagv\":[\"=all\"]},{\"tagk\":\"pod\",\"tagv\":[\"=all\"]}],\"counterListCount\":18,\"aggrFunc\":\"max\",\"aggrGroup\":[\"container\"]}],\"id\":55}",
|
||||
"weight": 2
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"pod处于waiting状态(pull image error)\",\"type\":\"chart\",\"now\":\"1611728391441\",\"start\":\"1611724791441\",\"end\":\"1611728391441\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":6,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"kube_pod_container_status_waiting_reason\",\"selectedTagkv\":[{\"tagk\":\"endpoint\",\"tagv\":[\"10.178.27.152\",\"__nid__5__\"]},{\"tagk\":\"container\",\"tagv\":[\"=all\"]},{\"tagk\":\"namespace\",\"tagv\":[\"=all\"]},{\"tagk\":\"pod\",\"tagv\":[\"=all\"]},{\"tagk\":\"reason\",\"tagv\":[\"ErrImagePull\"]}],\"counterListCount\":18,\"aggrFunc\":\"max\",\"aggrGroup\":[\"container\",\"reason\"]}],\"id\":56}",
|
||||
"weight": 3
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"pod容器重启qps\",\"type\":\"chart\",\"now\":\"1611728391441\",\"start\":\"1611724791441\",\"end\":\"1611728391441\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"threshold\":0,\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":6,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"kube_pod_container_status_restarts_total_rate\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"container\",\"tagv\":[\"=all\"]},{\"tagk\":\"namespace\",\"tagv\":[\"=all\"]},{\"tagk\":\"pod\",\"tagv\":[\"=all\"]}],\"counterListCount\":18,\"aggrFunc\":\"max\",\"aggrGroup\":[\"container\",\"pod\"]}],\"id\":57}",
|
||||
"weight": 4
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"pod数按namespace分布\",\"type\":\"chart\",\"now\":\"1611728391441\",\"start\":\"1611724791441\",\"end\":\"1611728391441\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"threshold\":null,\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":6,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"kube_pod_info\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"host_ip\",\"tagv\":[\"=all\"]},{\"tagk\":\"namespace\",\"tagv\":[\"=all\"]},{\"tagk\":\"node\",\"tagv\":[\"=all\"]},{\"tagk\":\"pod\",\"tagv\":[\"=all\"]},{\"tagk\":\"pod_ip\",\"tagv\":[\"=all\"]}],\"counterListCount\":18,\"aggrFunc\":\"sum\",\"aggrGroup\":[\"namespace\"]}],\"id\":114}",
|
||||
"weight": 5
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"pod数按namespace分布\",\"type\":\"chart\",\"now\":\"1611727764211\",\"start\":\"1611724164211\",\"end\":\"1611727764211\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":6,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"kube_pod_info\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"host_ip\",\"tagv\":[\"=all\"]},{\"tagk\":\"namespace\",\"tagv\":[\"=all\"]},{\"tagk\":\"node\",\"tagv\":[\"=all\"]},{\"tagk\":\"pod\",\"tagv\":[\"=all\"]},{\"tagk\":\"pod_ip\",\"tagv\":[\"=all\"]}],\"counterListCount\":18,\"aggrFunc\":\"sum\",\"aggrGroup\":[\"namespace\"]}],\"chartTypeOptions\":{\"chartType\":\"pie\",\"pieType\":\"pie\",\"targetValue\":\"avg\"},\"id\":115}",
|
||||
"weight": 6
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"pod数按node分布\",\"type\":\"chart\",\"now\":\"1611727764211\",\"start\":\"1611724164211\",\"end\":\"1611727764211\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":6,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"kube_pod_info\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"host_ip\",\"tagv\":[\"=all\"]},{\"tagk\":\"namespace\",\"tagv\":[\"=all\"]},{\"tagk\":\"node\",\"tagv\":[\"=all\"]},{\"tagk\":\"pod\",\"tagv\":[\"=all\"]},{\"tagk\":\"pod_ip\",\"tagv\":[\"=all\"]}],\"counterListCount\":18,\"aggrFunc\":\"sum\",\"aggrGroup\":[\"host_ip\"]}],\"chartTypeOptions\":{\"chartType\":\"pie\",\"pieType\":\"pie\",\"targetValue\":\"avg\"},\"id\":116}",
|
||||
"weight": 7
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"\",\"type\":\"chart\",\"now\":\"1611727764211\",\"start\":\"1611724164211\",\"end\":\"1611727764211\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":6,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"kube_pod_container_info\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"container\",\"tagv\":[\"=all\"]},{\"tagk\":\"namespace\",\"tagv\":[\"=all\"]},{\"tagk\":\"pod\",\"tagv\":[\"=all\"]}],\"counterListCount\":18}],\"chartTypeOptions\":{\"chartType\":\"table\",\"tableType\":\"stats\",\"columnsKey\":[\"last\"],\"valueMap\":\"range\",\"mapConf\":[{}]},\"id\":127,\"sortOrder\":{\"columnKey\":\"last\"}}",
|
||||
"weight": 8
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "deployment指标",
|
||||
"weight": 3,
|
||||
"charts": [
|
||||
{
|
||||
"configs": "{\"title\":\"可用副本数\",\"type\":\"chart\",\"now\":\"1610682325050\",\"start\":\"1610678725050\",\"end\":\"1610682325050\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":6,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"kube_deployment_status_replicas_available\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"deployment\",\"tagv\":[\"=all\"]},{\"tagk\":\"namespace\",\"tagv\":[\"=all\"]}],\"counterListCount\":1}],\"id\":58}",
|
||||
"weight": 0
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"不可用副本数\",\"type\":\"chart\",\"now\":\"1610682325050\",\"start\":\"1610678725050\",\"end\":\"1610682325050\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":6,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"kube_deployment_status_replicas_unavailable\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"deployment\",\"tagv\":[\"=all\"]},{\"tagk\":\"namespace\",\"tagv\":[\"=all\"]}],\"counterListCount\":1}],\"id\":58}",
|
||||
"weight": 1
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"deployment期望副本数\",\"type\":\"chart\",\"now\":\"1610682325050\",\"start\":\"1610678725050\",\"end\":\"1610682325050\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":6,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"kube_deployment_status_replicas\",\"selectedTagkv\":[{\"tagk\":\"endpoint\",\"tagv\":[\"10.178.27.152\",\"__nid__6__\"]},{\"tagk\":\"deployment\",\"tagv\":[\"=all\"]},{\"tagk\":\"namespace\",\"tagv\":[\"=all\"]}],\"counterListCount\":1}],\"chartTypeOptions\":{\"chartType\":\"pie\",\"pieType\":\"pie\",\"targetValue\":\"avg\"}}",
|
||||
"weight": 2
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "daemonset指标",
|
||||
"weight": 4,
|
||||
"charts": [
|
||||
{
|
||||
"configs": "{\"title\":\"应该运行ds的节点数\",\"type\":\"chart\",\"now\":\"1611728391441\",\"start\":\"1611724791441\",\"end\":\"1611728391441\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":6,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"kube_daemonset_status_desired_number_scheduled\",\"selectedTagkv\":[{\"tagk\":\"endpoint\",\"tagv\":[\"10.178.27.152\"]},{\"tagk\":\"daemonset\",\"tagv\":[\"=all\"]},{\"tagk\":\"namespace\",\"tagv\":[\"=all\"]}],\"counterListCount\":4}],\"id\":61}",
|
||||
"weight": 0
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"当前运行ds的节点数\",\"type\":\"chart\",\"now\":\"1611728391441\",\"start\":\"1611724791441\",\"end\":\"1611728391441\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":6,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"kube_daemonset_status_current_number_scheduled\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"daemonset\",\"tagv\":[\"=all\"]},{\"tagk\":\"namespace\",\"tagv\":[\"=all\"]}],\"counterListCount\":4}],\"id\":61}",
|
||||
"weight": 1
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"ds可用数\",\"type\":\"chart\",\"now\":\"1611728391441\",\"start\":\"1611724791441\",\"end\":\"1611728391441\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":6,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"kube_daemonset_status_number_available\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"daemonset\",\"tagv\":[\"=all\"]},{\"tagk\":\"namespace\",\"tagv\":[\"=all\"]}],\"counterListCount\":4}],\"id\":129}",
|
||||
"weight": 2
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "statefulset",
|
||||
"weight": 5,
|
||||
"charts": [
|
||||
{
|
||||
"configs": "{\"title\":\"当前副本数\",\"type\":\"chart\",\"now\":\"1611727764211\",\"start\":\"1611724164211\",\"end\":\"1611727764211\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":6,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"kube_statefulset_status_replicas_current\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"namespace\",\"tagv\":[\"=all\"]},{\"tagk\":\"statefulset\",\"tagv\":[\"=all\"]}],\"counterListCount\":1}],\"id\":130}",
|
||||
"weight": 0
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"当前ready数\",\"type\":\"chart\",\"now\":\"1611727764211\",\"start\":\"1611724164211\",\"end\":\"1611727764211\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":6,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"kube_statefulset_status_replicas_ready\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"namespace\",\"tagv\":[\"=all\"]},{\"tagk\":\"statefulset\",\"tagv\":[\"=all\"]}],\"counterListCount\":1}],\"id\":130}",
|
||||
"weight": 1
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"创建时间\",\"type\":\"chart\",\"now\":\"1611727764211\",\"start\":\"1611724164211\",\"end\":\"1611727764211\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":6,\"endpointsKey\":\"nids\",\"selectedEndpoint\":[\"6\"],\"selectedMetric\":\"kube_statefulset_created\",\"selectedTagkv\":[{\"tagk\":\"nids\",\"tagv\":[\"6\"]},{\"tagk\":\"namespace\",\"tagv\":[\"=all\"]},{\"tagk\":\"statefulset\",\"tagv\":[\"=all\"]}],\"counterListCount\":1}],\"id\":132}",
|
||||
"weight": 2
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
|
@ -1,38 +0,0 @@
|
|||
[
|
||||
{
|
||||
"name": "日常巡检大盘",
|
||||
"node_path": "",
|
||||
"tags": [
|
||||
{
|
||||
"name": "机器负载",
|
||||
"weight": 0,
|
||||
"charts": [
|
||||
{
|
||||
"configs": "{\"title\":\"CPU使用率\",\"type\":\"chart\",\"now\":\"1611191937020\",\"start\":\"1611188337020\",\"end\":\"1611191937020\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"threshold\":75,\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":1,\"endpointsKey\":\"endpoints\",\"selectedEndpoint\":[\"=all\"],\"selectedMetric\":\"cpu.util\",\"selectedTagkv\":[],\"counterListCount\":6}],\"id\":152}",
|
||||
"weight": 0
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"进程总数\",\"type\":\"chart\",\"now\":\"1611192346064\",\"start\":\"1611188746064\",\"end\":\"1611192346064\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":1,\"endpointsKey\":\"endpoints\",\"selectedEndpoint\":[\"=all\"],\"selectedMetric\":\"sys.ps.process.total\",\"selectedTagkv\":[],\"counterListCount\":6,\"aggrFunc\":\"avg\"}],\"chartTypeOptions\":{\"chartType\":\"singleValue\",\"targetValue\":\"avg\",\"subType\":\"normal\",\"valueMap\":\"range\",\"mapConf\":[{\"from\":0,\"to\":3000,\"color\":\"#07cf82\"},{\"from\":3000,\"to\":5000,\"color\":\"#ef900b\"},{\"from\":5000,\"to\":999999,\"color\":\"#f50505\"}],\"suffix\":\"个\"},\"id\":10}",
|
||||
"weight": 1
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"硬盘使用率\",\"type\":\"chart\",\"now\":\"1611211473892\",\"start\":\"1611207873892\",\"end\":\"1611211473892\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":1,\"endpointsKey\":\"endpoints\",\"selectedEndpoint\":[\"=all\"],\"selectedMetric\":\"disk.bytes.used.percent\",\"selectedTagkv\":[{\"tagk\":\"endpoint\",\"tagv\":[\"=all\"]},{\"tagk\":\"mount\",\"tagv\":[\"=all\"]}],\"counterListCount\":11}],\"chartTypeOptions\":{\"chartType\":\"table\",\"tableType\":\"stats\",\"columnsKey\":[\"last\"],\"valueMap\":\"range\",\"mapConf\":[{}]},\"id\":13,\"sortOrder\":{\"columnKey\":\"last\",\"order\":\"descend\"}}",
|
||||
"weight": 2
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"内存使用率均值-纯演示扇形图\",\"type\":\"chart\",\"now\":\"1611231230645\",\"start\":\"1611227630645\",\"end\":\"1611231230645\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":1,\"endpointsKey\":\"endpoints\",\"selectedEndpoint\":[\"=all\"],\"selectedMetric\":\"mem.bytes.used.percent\",\"selectedTagkv\":[{\"tagk\":\"endpoint\",\"tagv\":[\"=all\"]}],\"counterListCount\":6,\"aggrFunc\":\"avg\"}],\"chartTypeOptions\":{\"chartType\":\"singleValue\",\"targetValue\":\"avg\",\"subType\":\"solidGauge\",\"valueMap\":\"range\",\"mapConf\":[{\"from\":0,\"to\":40,\"color\":\"#06c663\"},{\"from\":40,\"to\":70,\"color\":\"#da8e0b\"},{\"from\":70,\"to\":90,\"color\":\"#f48b71\"},{\"from\":90,\"to\":111,\"color\":\"#fa0505\"}]},\"id\":11}",
|
||||
"weight": 3
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"IO使用率-纯演示水位图\",\"type\":\"chart\",\"now\":\"1611231230645\",\"start\":\"1611227630645\",\"end\":\"1611231230645\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":1,\"endpointsKey\":\"endpoints\",\"selectedEndpoint\":[\"=all\"],\"selectedMetric\":\"disk.io.util\",\"selectedTagkv\":[{\"tagk\":\"endpoint\",\"tagv\":[\"=all\"]},{\"tagk\":\"device\",\"tagv\":[\"=all\"]}],\"counterListCount\":24,\"aggrFunc\":\"avg\"}],\"chartTypeOptions\":{\"chartType\":\"singleValue\",\"targetValue\":\"avg\",\"subType\":\"liquidFillGauge\",\"valueMap\":\"range\",\"mapConf\":[{\"color\":\"#07b904\",\"from\":0,\"to\":50},{\"from\":50,\"to\":100,\"color\":\"#e01a1a\"}]},\"id\":12}",
|
||||
"weight": 4
|
||||
},
|
||||
{
|
||||
"configs": "{\"title\":\"进程数-纯演示饼图\",\"type\":\"chart\",\"now\":\"1611231230645\",\"start\":\"1611227630645\",\"end\":\"1611231230645\",\"comparisonOptions\":[{\"label\":\"1小时\",\"labelEn\":\"1 hour\",\"value\":\"3600000\"},{\"label\":\"2小时\",\"labelEn\":\"2 hours\",\"value\":\"7200000\"},{\"label\":\"1天\",\"labelEn\":\"1 day\",\"value\":\"86400000\"},{\"label\":\"2天\",\"labelEn\":\"2 days\",\"value\":\"172800000\"},{\"label\":\"7天\",\"labelEn\":\"7 days\",\"value\":\"604800000\"}],\"legend\":false,\"shared\":true,\"linkVisible\":true,\"metrics\":[{\"selectedNid\":1,\"endpointsKey\":\"endpoints\",\"selectedEndpoint\":[\"=all\"],\"selectedMetric\":\"sys.ps.process.total\",\"selectedTagkv\":[{\"tagk\":\"endpoint\",\"tagv\":[\"=all\"]}],\"counterListCount\":6}],\"chartTypeOptions\":{\"chartType\":\"pie\",\"pieType\":\"donut\",\"targetValue\":\"avg\"},\"id\":14}",
|
||||
"weight": 5
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
|
@ -0,0 +1,80 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: UTF-8 -*-
|
||||
import sys
|
||||
import json
|
||||
import os
|
||||
import smtplib
|
||||
from email.mime.text import MIMEText
|
||||
from email.header import Header
|
||||
|
||||
# 希望的demo实现效果:
|
||||
# 1. 从stdin拿到告警信息之后,格式化为一个有缩进的json写入一个临时文件
|
||||
# 2. 文件路径和名字是.alerts/${timestamp}_${ruleid}
|
||||
# 3. 调用SMTP服务器发送告警,微信、钉钉、飞书、slack、jira、短信、电话等等留给社区实现
|
||||
|
||||
mail_host = "smtp.163.com"
|
||||
mail_port = 994
|
||||
mail_user = "ulricqin"
|
||||
mail_pass = "password"
|
||||
mail_from = "ulricqin@163.com"
|
||||
|
||||
# just for test
|
||||
mail_body = """
|
||||
<p>邮件发送测试</p>
|
||||
<p><a href="https://www.baidu.com">baidu</a></p>
|
||||
"""
|
||||
|
||||
def main():
|
||||
payload = json.load(sys.stdin)
|
||||
persist(payload)
|
||||
|
||||
|
||||
def persist(payload):
|
||||
if not os.path.exists(".alerts"):
|
||||
os.makedirs(".alerts")
|
||||
|
||||
filename = '%d_%d' % (payload['event']['trigger_time'], payload['rule']['id'])
|
||||
filepath = os.path.join(".alerts", filename)
|
||||
|
||||
f = open(filepath, 'w')
|
||||
print(json.dumps(payload, indent=4), file=f)
|
||||
f.close()
|
||||
|
||||
|
||||
def send_mail(payload):
|
||||
print("send_mail")
|
||||
|
||||
|
||||
def send_wecom(payload):
|
||||
print("send_wecom")
|
||||
|
||||
|
||||
def send_dingtalk(payload):
|
||||
print("send_dingtalk")
|
||||
|
||||
|
||||
def mail_test():
|
||||
print("mail_test_todo")
|
||||
|
||||
recipients = ["ulricqin@qq.com", "ulric@163.com"]
|
||||
|
||||
message = MIMEText(mail_body, 'html', 'utf-8')
|
||||
message['From'] = mail_from
|
||||
message['To'] = ", ".join(recipients)
|
||||
message["Subject"] = "n9e alert"
|
||||
|
||||
smtp = smtplib.SMTP_SSL(mail_host, mail_port)
|
||||
smtp.login(mail_user, mail_pass)
|
||||
smtp.sendmail(mail_from, recipients, message.as_string())
|
||||
smtp.close()
|
||||
|
||||
print("mail_test_done")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) == 1:
|
||||
main()
|
||||
elif sys.argv[1] == "mail":
|
||||
mail_test()
|
||||
else:
|
||||
print("I am confused")
|
286
etc/server.yml
286
etc/server.yml
|
@ -1,201 +1,121 @@
|
|||
logger:
|
||||
dir: logs/server
|
||||
level: INFO
|
||||
# rotate by time
|
||||
keepHours: 24
|
||||
## rotate by size
|
||||
#rotatenum: 3
|
||||
#rotatesize: 256 # unit: MB
|
||||
dir: logs
|
||||
level: DEBUG
|
||||
# # rotate by time
|
||||
# keepHours: 4
|
||||
# rotate by size
|
||||
rotatenum: 3
|
||||
rotatesize: 256 # unit: MB
|
||||
|
||||
http:
|
||||
mode: release
|
||||
showLog: true
|
||||
session:
|
||||
cookieName: ecmc-sid
|
||||
cookieDomain: ""
|
||||
httpOnly: true
|
||||
gcInterval: 60
|
||||
cookieLifetime: 86400 # unit: second, 0: cookie life same to browser
|
||||
# whether print access log to DEBUG.log
|
||||
access: false
|
||||
listen: 0.0.0.0:8000
|
||||
pprof: false
|
||||
cookieName: n9e
|
||||
cookieDomain: ""
|
||||
cookieMaxAge: 86400
|
||||
cookieSecure: false
|
||||
cookieHttpOnly: true
|
||||
cookieSecret: 4696709ab8cc3ff2fea17b930158516b
|
||||
csrfSecret: 15b8ea164b5d3d9254677053c72a19f1
|
||||
|
||||
tokens:
|
||||
- rdb-builtin-token
|
||||
- ams-builtin-token
|
||||
rpc:
|
||||
listen: 0.0.0.0:9000
|
||||
|
||||
redis:
|
||||
# as queue
|
||||
local:
|
||||
enable: true
|
||||
addr: 127.0.0.1:6379
|
||||
pass: ""
|
||||
idle: 5
|
||||
timeout:
|
||||
conn: 500
|
||||
read: 3000
|
||||
write: 3000
|
||||
mysql:
|
||||
addr: "root:1234@tcp(127.0.0.1:3306)/n9e?charset=utf8&parseTime=True&loc=Asia%2FShanghai"
|
||||
max: 128
|
||||
idle: 16
|
||||
debug: false
|
||||
|
||||
# i18n:
|
||||
# # zh | en
|
||||
# lang: zh
|
||||
# dictPath: etc/i18n.json
|
||||
|
||||
rdb:
|
||||
# for ldap authorization
|
||||
ldap:
|
||||
host: "ldap.example.org"
|
||||
port: 389
|
||||
baseDn: "dc=example,dc=org"
|
||||
# AD: manange@example.org
|
||||
bindUser: "cn=manager,dc=example,dc=org"
|
||||
bindPass: "*******"
|
||||
# openldap: (&(uid=%s))
|
||||
# AD: (&(sAMAccountName=%s))
|
||||
authFilter: "(&(uid=%s))"
|
||||
attributes:
|
||||
dispname: "cn"
|
||||
email: "mail"
|
||||
phone: "mobile"
|
||||
im: ""
|
||||
coverAttributes: false
|
||||
autoRegist: true
|
||||
tls: false
|
||||
startTLS: false
|
||||
sender:
|
||||
mail:
|
||||
# three choice: smtp|shell|api
|
||||
way: smtp
|
||||
worker: 10
|
||||
api: http://127.0.0.1:2008/mail
|
||||
sms:
|
||||
# two choice: shell|api
|
||||
way: api
|
||||
worker: 10
|
||||
api: http://127.0.0.1:2008/sms
|
||||
voice:
|
||||
# two choice: shell|api
|
||||
way: shell
|
||||
worker: 10
|
||||
api: http://127.0.0.1:2008/voice
|
||||
im:
|
||||
# five choice: shell|api|wechat|wechat_robot|dingtalk_robot
|
||||
way: shell
|
||||
worker: 10
|
||||
api: http://127.0.0.1:2008/im
|
||||
## for enterprise edition
|
||||
#sso:
|
||||
# enable: false
|
||||
# ssoAddr: "http://{sso-host}"
|
||||
# redirectURL: "http://{rdb-host}/auth-callback"
|
||||
# clientId: ""
|
||||
# clientSecret: ""
|
||||
# apiKey: ""
|
||||
# attributes:
|
||||
# dispname: "display_name"
|
||||
# email: "email"
|
||||
# phone: "phone"
|
||||
# im: ""
|
||||
# coverAttributes: false
|
||||
# stateExpiresIn: 300
|
||||
#auth:
|
||||
# captcha: false
|
||||
# extraMode:
|
||||
# enable: false # enable whiteList, login retry lock, userControl, ...
|
||||
# whiteList: false
|
||||
# frozenDays: 90 # frozen time (day)
|
||||
# writenOffDays: 365 # writenOff time (day)
|
||||
# heartbeat:
|
||||
# # auto detect if blank
|
||||
# ip: ""
|
||||
# # unit: ms
|
||||
# interval: 1000
|
||||
|
||||
# ldap:
|
||||
# enable: false
|
||||
# host: ldap.example.org
|
||||
# port: 389
|
||||
# baseDn: "dc=example,dc=org"
|
||||
# # AD: manange@example.org
|
||||
# bindUser: "cn=manager,dc=example,dc=org"
|
||||
# bindPass: "*******"
|
||||
# # openldap: (&(uid=%s))
|
||||
# # AD: (&(sAMAccountName=%s))
|
||||
# authFilter: "(&(uid=%s))"
|
||||
# attributes:
|
||||
# nickname: "cn"
|
||||
# email: "mail"
|
||||
# phone: "mobile"
|
||||
# coverAttributes: false
|
||||
# autoRegist: true
|
||||
# tls: false
|
||||
# startTLS: false
|
||||
|
||||
#i18n:
|
||||
# lang: zh
|
||||
# judge:
|
||||
# readBatch: 2000
|
||||
# connTimeout: 2000
|
||||
# callTimeout: 5000
|
||||
# writerNum: 256
|
||||
# connMax: 2560
|
||||
# connIdle: 256
|
||||
|
||||
job:
|
||||
enable: true
|
||||
## database | remote
|
||||
#outputComeFrom: database
|
||||
#remoteAgtdPort: 2080
|
||||
# alert:
|
||||
# notifyScriptPath: ./etc/script/notify.py
|
||||
# notifyConcurrency: 200
|
||||
# mutedAlertPersist: true
|
||||
|
||||
transfer:
|
||||
trans:
|
||||
enable: true
|
||||
backend:
|
||||
datasource: "m3db"
|
||||
m3db:
|
||||
enabled: true
|
||||
maxSeriesPoints: 720 # default 720
|
||||
name: "m3db"
|
||||
namespace: "default"
|
||||
seriesLimit: 0
|
||||
docsLimit: 0
|
||||
daysLimit: 7 # max query time
|
||||
datasource: "prometheus"
|
||||
prometheus:
|
||||
enable: true
|
||||
name: prometheus
|
||||
batch: 100000
|
||||
maxRetry: 5
|
||||
# prometheus 查询返回最大点数query.max-samples
|
||||
maxSamples: 50000000
|
||||
# prometheus并发的查询 query.max-concurrency
|
||||
maxConcurrentQuery: 20
|
||||
# prometheus 回查窗口 query.lookback-delta
|
||||
lookbackDeltaMinute: 2
|
||||
# 查询全量索引时时间窗口限制,降低高基数
|
||||
maxFetchAllSeriesLimitMinute: 5
|
||||
remoteWrite:
|
||||
# m3db的配置
|
||||
#- name: m3db01
|
||||
# url: http://localhost:7201/api/v1/prom/remote/write
|
||||
# remoteTimeoutSecond: 5
|
||||
|
||||
# https://m3db.github.io/m3/m3db/architecture/consistencylevels/
|
||||
writeConsistencyLevel: "majority" # one|majority|all
|
||||
readConsistencyLevel: "unstrict_majority" # one|unstrict_majority|majority|all
|
||||
writeTimeout: 5s
|
||||
fetchTimeout: 5s
|
||||
connectTimeout: 5s
|
||||
config:
|
||||
service:
|
||||
# KV environment, zone, and service from which to write/read KV data (placement
|
||||
# and configuration). Leave these as the default values unless you know what
|
||||
# you're doing.
|
||||
env: default_env
|
||||
zone: embedded
|
||||
service: m3db
|
||||
etcdClusters:
|
||||
- zone: embedded
|
||||
endpoints:
|
||||
- 127.0.0.1:2379
|
||||
#tls:
|
||||
# caCrtPath: /etc/etcd/certs/ca.pem
|
||||
# crtPath: /etc/etcd/certs/etcd-client.pem
|
||||
# keyPath: /etc/etcd/certs/etcd-client-key.pem
|
||||
#tsdb:
|
||||
# enabled: false
|
||||
# name: "tsdb"
|
||||
# cluster:
|
||||
# tsdb01: 127.0.0.1:8011
|
||||
#influxdb:
|
||||
# enabled: false
|
||||
# username: "influx"
|
||||
# password: "admin123"
|
||||
# precision: "s"
|
||||
# database: "n9e"
|
||||
# address: "http://127.0.0.1:8086"
|
||||
#opentsdb:
|
||||
# enabled: false
|
||||
# address: "127.0.0.1:4242"
|
||||
#kafka:
|
||||
# enabled: false
|
||||
# brokersPeers: "192.168.1.1:9092,192.168.1.2:9092"
|
||||
# topic: "n9e"
|
||||
monapi:
|
||||
indexMod: server
|
||||
alarmEnabled: true
|
||||
region:
|
||||
- default
|
||||
|
||||
# clean history event
|
||||
cleaner:
|
||||
# retention days
|
||||
days: 100
|
||||
# number of events deleted per time
|
||||
batch: 100
|
||||
notify:
|
||||
p1: ["voice", "sms", "mail", "im"]
|
||||
p2: ["sms", "mail", "im"]
|
||||
p3: ["mail", "im"]
|
||||
# prometheus的配置
|
||||
- name: prome01
|
||||
url: http://localhost:9090/api/v1/write
|
||||
remoteTimeoutSecond: 5
|
||||
remoteRead:
|
||||
- name: prome01
|
||||
url: http://localhost:9090/api/v1/read
|
||||
remoteTimeoutSecond: 5
|
||||
|
||||
# addresses accessible using browser
|
||||
link:
|
||||
stra: http://n9e.com/mon/strategy/%v
|
||||
event: http://n9e.com/mon/history/his/%v
|
||||
claim: http://n9e.com/mon/history/cur/%v
|
||||
|
||||
judge:
|
||||
query:
|
||||
maxConn: 2000
|
||||
maxIdle: 100
|
||||
connTimeout: 1000
|
||||
callTimeout: 2000
|
||||
indexCallTimeout: 2000
|
||||
indexMod: server
|
||||
contactKeys:
|
||||
- label: "Wecom Robot Token"
|
||||
key: wecom_robot_token
|
||||
- label: "Dingtalk Robot Token"
|
||||
key: dingtalk_robot_token
|
||||
|
||||
wechat:
|
||||
corp_id: "xxxxxxxxxxxxx"
|
||||
agent_id: 1000000
|
||||
secret: "xxxxxxxxxxxxxxxxx"
|
||||
notifyChannels:
|
||||
- email
|
||||
- sms
|
||||
- voice
|
||||
- dingtalk
|
||||
- wecom
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
[Unit]
|
||||
Description=n9e agent
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
# modify when deploy in prod env
|
||||
User=root
|
||||
Group=root
|
||||
|
||||
Type=simple
|
||||
Environment="GIN_MODE=release"
|
||||
ExecStart=/home/n9e/n9e-agentd
|
||||
WorkingDirectory=/home/n9e
|
||||
|
||||
Restart=always
|
||||
RestartSec=1
|
||||
StartLimitInterval=0
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
|
@ -0,0 +1,19 @@
|
|||
[Unit]
|
||||
Description="n9e-agentd"
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/opt/n9e/n9e-agentd -c /opt/n9e/etc/agentd.yml
|
||||
WorkingDirectory=/opt/n9e
|
||||
|
||||
Restart=always
|
||||
RestartSecs=1s
|
||||
SuccessExitStatus=0
|
||||
LimitNOFILE=65536
|
||||
StandardOutput=syslog
|
||||
StandardError=syslog
|
||||
SyslogIdentifier=n9e-agentd
|
||||
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
|
@ -0,0 +1,19 @@
|
|||
[Unit]
|
||||
Description="n9e-server"
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/opt/n9e/n9e-server
|
||||
WorkingDirectory=/opt/n9e
|
||||
|
||||
Restart=always
|
||||
RestartSecs=1s
|
||||
SuccessExitStatus=0
|
||||
LimitNOFILE=65536
|
||||
StandardOutput=syslog
|
||||
StandardError=syslog
|
||||
SyslogIdentifier=n9e-server
|
||||
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
|
@ -1,21 +0,0 @@
|
|||
[Unit]
|
||||
Description=n9e prober
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
# modify when deploy in prod env
|
||||
User=root
|
||||
Group=root
|
||||
|
||||
Type=simple
|
||||
Environment="GIN_MODE=release"
|
||||
ExecStart=/home/n9e/n9e-prober
|
||||
WorkingDirectory=/home/n9e
|
||||
|
||||
Restart=always
|
||||
RestartSec=1
|
||||
StartLimitInterval=0
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
|
@ -1,24 +0,0 @@
|
|||
[Unit]
|
||||
Description=n9e server
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
# modify when deploy in prod env
|
||||
User=root
|
||||
Group=root
|
||||
|
||||
Type=simple
|
||||
Environment="GIN_MODE=release"
|
||||
ExecStart=/home/n9e/n9e-server
|
||||
WorkingDirectory=/home/n9e
|
||||
|
||||
Restart=always
|
||||
RestartSec=1
|
||||
StartLimitInterval=0
|
||||
|
||||
# LimitNOFILE=60000
|
||||
# LimitNPROC=10000
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
|
@ -1 +0,0 @@
|
|||
您好,您的验证码为 {{.Code}} 。
|
|
@ -1 +0,0 @@
|
|||
您好,您的验证码为 {{.Code}} 。
|
245
etc/tpl/mail.tpl
245
etc/tpl/mail.tpl
|
@ -1,245 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||
<title>夜莺告警通知</title>
|
||||
<style type="text/css">
|
||||
.wrapper {
|
||||
background-color: #f8f8f8;
|
||||
padding: 15px;
|
||||
height: 100%;
|
||||
}
|
||||
.main {
|
||||
width: 600px;
|
||||
padding: 30px;
|
||||
margin: 0 auto;
|
||||
background-color: #fff;
|
||||
font-size: 12px;
|
||||
font-family: verdana,'Microsoft YaHei',Consolas,'Deja Vu Sans Mono','Bitstream Vera Sans Mono';
|
||||
}
|
||||
header {
|
||||
border-radius: 2px 2px 0 0;
|
||||
}
|
||||
header .title {
|
||||
font-size: 16px;
|
||||
color: #333333;
|
||||
margin: 0;
|
||||
}
|
||||
header .sub-desc {
|
||||
color: #333;
|
||||
font-size: 14px;
|
||||
margin-top: 6px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
hr {
|
||||
margin: 20px 0;
|
||||
height: 0;
|
||||
border: none;
|
||||
border-top: 1px solid #e5e5e5;
|
||||
}
|
||||
em {
|
||||
font-weight: 600;
|
||||
}
|
||||
table {
|
||||
margin: 20px 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
table tbody tr{
|
||||
font-weight: 200;
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.succ {
|
||||
background-color: green;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.fail {
|
||||
background-color: red;
|
||||
color: white;
|
||||
}
|
||||
|
||||
table tbody tr th {
|
||||
width: 80px;
|
||||
text-align: right;
|
||||
}
|
||||
.text-right {
|
||||
text-align: right;
|
||||
}
|
||||
.body {
|
||||
margin-top: 24px;
|
||||
}
|
||||
.body-text {
|
||||
color: #666666;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
.body-extra {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
.body-extra.text-right a {
|
||||
text-decoration: none;
|
||||
color: #333;
|
||||
}
|
||||
.body-extra.text-right a:hover {
|
||||
color: #666;
|
||||
}
|
||||
.button {
|
||||
width: 200px;
|
||||
height: 50px;
|
||||
margin-top: 20px;
|
||||
text-align: center;
|
||||
border-radius: 2px;
|
||||
background: #2D77EE;
|
||||
line-height: 50px;
|
||||
font-size: 20px;
|
||||
color: #FFFFFF;
|
||||
cursor: pointer;
|
||||
}
|
||||
.button:hover {
|
||||
background: rgb(25, 115, 255);
|
||||
border-color: rgb(25, 115, 255);
|
||||
color: #fff;
|
||||
}
|
||||
footer {
|
||||
margin-top: 10px;
|
||||
text-align: right;
|
||||
}
|
||||
.footer-logo {
|
||||
text-align: right;
|
||||
}
|
||||
.footer-logo-image {
|
||||
width: 108px;
|
||||
height: 27px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
.copyright {
|
||||
margin-top: 10px;
|
||||
font-size: 12px;
|
||||
text-align: right;
|
||||
color: #999;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="wrapper">
|
||||
<div class="main">
|
||||
<header>
|
||||
<h3 class="title">{{.Sname}}</h3>
|
||||
<p class="sub-desc"></p>
|
||||
</header>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="body">
|
||||
<div class="body-text">
|
||||
<div style="color: red">
|
||||
{{if .IsUpgrade}}
|
||||
注意,告警已触发升级!
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table cellspacing="0" cellpadding="0" border="0">
|
||||
<tbody>
|
||||
{{if .IsAlert}}
|
||||
<tr class="fail">
|
||||
<th>级别状态:</th>
|
||||
<td>{{.Status}}</td>
|
||||
</tr>
|
||||
{{else}}
|
||||
<tr class="succ">
|
||||
<th>级别状态:</th>
|
||||
<td>{{.Status}}</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
|
||||
{{if .IsMachineDep}}
|
||||
<tr>
|
||||
<th>告警设备:</th>
|
||||
<td>{{.Endpoint}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>设备名称:</th>
|
||||
<td>{{.Name}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>设备备注:</th>
|
||||
<td>{{.Note}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>挂载节点:</th>
|
||||
<td>
|
||||
{{range .Bindings}}
|
||||
{{.}}<br />
|
||||
{{end}}
|
||||
</td>
|
||||
</tr>
|
||||
{{else}}
|
||||
<tr>
|
||||
<th>所属节点:</th>
|
||||
<td>{{.CurNodePath}}</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
<tr>
|
||||
<th>监控指标:</th>
|
||||
<td>{{.Metric}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>tags:</th>
|
||||
<td>{{.Tags}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>当前值:</th>
|
||||
<td>{{.Value}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>报警说明:</th>
|
||||
<td>
|
||||
{{.Info}}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>触发时间:</th>
|
||||
<td>
|
||||
{{.Etime}}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>报警详情:</th>
|
||||
<td>{{.Elink}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>报警策略:</th>
|
||||
<td>{{.Slink}}</td>
|
||||
</tr>
|
||||
{{if .HasClaim}}
|
||||
<tr>
|
||||
<th>认领报警:</th>
|
||||
<td>{{.Clink}}</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<hr>
|
||||
|
||||
<footer>
|
||||
<div class="footer-logo">
|
||||
<a href="https://n9e.didiyun.com">
|
||||
<img src="https://s3-gz01.didistatic.com/n9e-pub/image/n9e-logo-bg-white.png" class="footer-logo-image" alt="">
|
||||
</a>
|
||||
</div>
|
||||
<div class="copyright" style="font-style: italic">
|
||||
我们希望与您一起,将监控这个事情,做到极致!
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1 +0,0 @@
|
|||
您好,您的密码已被重置
|
|
@ -1,16 +0,0 @@
|
|||
{{if .IsUpgrade}}注意,告警已触发升级!{{end}}
|
||||
级别状态:{{.Status}}
|
||||
策略名称:{{.Sname}}
|
||||
告警设备:{{.Endpoint}}
|
||||
设备名称:{{.Name}}
|
||||
设备备注:{{.Note}}
|
||||
挂载节点:
|
||||
{{range .Bindings}}{{.}}
|
||||
{{end}}监控指标:{{.Metric}}
|
||||
指标标签:{{.Tags}}
|
||||
当前值:{{.Value}}
|
||||
报警说明:{{.Info | unescaped}}
|
||||
触发时间:{{.Etime}}
|
||||
报警详情:{{.Elink | urlconvert}}
|
||||
报警策略:{{.Slink | urlconvert}}
|
||||
{{if .HasClaim}}认领报警:{{.Clink | urlconvert}}{{end}}
|
108
go.mod
108
go.mod
|
@ -1,86 +1,56 @@
|
|||
module github.com/didi/nightingale/v4
|
||||
module github.com/didi/nightingale/v5
|
||||
|
||||
go 1.12
|
||||
go 1.14
|
||||
|
||||
require (
|
||||
github.com/Shopify/sarama v1.27.2
|
||||
github.com/alouca/gologger v0.0.0-20120904114645-7d4b7291de9c // indirect
|
||||
github.com/blang/semver v3.5.1+incompatible
|
||||
github.com/cespare/xxhash v1.1.0
|
||||
github.com/coreos/go-oidc v2.2.1+incompatible
|
||||
github.com/freedomkk-qfeng/go-fastping v0.0.0-20160109021039-d7bb493dee3e // indirect
|
||||
github.com/gaochao1/gosnmp v0.0.0-20150630013918-783a67a067fd // indirect
|
||||
github.com/gaochao1/sw v4.0.0+incompatible
|
||||
github.com/garyburd/redigo v1.6.2
|
||||
github.com/armon/go-metrics v0.3.4 // indirect
|
||||
github.com/gin-contrib/gzip v0.0.3
|
||||
github.com/gin-contrib/pprof v1.3.0
|
||||
github.com/gin-contrib/sessions v0.0.3
|
||||
github.com/gin-gonic/gin v1.6.3
|
||||
github.com/go-ping/ping v0.0.0-20201115131931-3300c582a663
|
||||
github.com/go-kit/kit v0.10.0
|
||||
github.com/go-ldap/ldap/v3 v3.2.4
|
||||
github.com/go-sql-driver/mysql v1.5.0
|
||||
github.com/google/uuid v1.1.2
|
||||
github.com/hashicorp/golang-lru v0.5.4
|
||||
github.com/hpcloud/tail v1.0.0
|
||||
github.com/influxdata/influxdb v1.8.0
|
||||
github.com/influxdata/telegraf v1.17.2
|
||||
github.com/jackc/pgx v3.6.0+incompatible
|
||||
github.com/lib/pq v1.6.0
|
||||
github.com/m3db/m3 v0.15.17
|
||||
github.com/gogo/protobuf v1.3.2
|
||||
github.com/golang/snappy v0.0.2
|
||||
github.com/gopherjs/gopherjs v0.0.0-20190910122728-9d188e94fb99 // indirect
|
||||
github.com/gorilla/sessions v1.2.0 // indirect
|
||||
github.com/hashicorp/go-immutable-radix v1.2.0 // indirect
|
||||
github.com/hashicorp/go-msgpack v0.5.5 // indirect
|
||||
github.com/hashicorp/go-uuid v1.0.2 // indirect
|
||||
github.com/hashicorp/golang-lru v0.5.4 // indirect
|
||||
github.com/hashicorp/hcl v1.0.1-0.20190611123218-cf7d376da96d // indirect
|
||||
github.com/magiconair/properties v1.8.2 // indirect
|
||||
github.com/mattn/go-isatty v0.0.12
|
||||
github.com/mattn/go-sqlite3 v1.14.0 // indirect
|
||||
github.com/mojocn/base64Captcha v1.3.1
|
||||
github.com/pquerna/cachecontrol v0.0.0-20200819021114-67c6ae64274f // indirect
|
||||
github.com/robfig/go-cache v0.0.0-20130306151617-9fc39e0dbf62 // indirect
|
||||
github.com/shirou/gopsutil v3.20.11+incompatible // indirect
|
||||
github.com/spaolacci/murmur3 v1.1.0
|
||||
github.com/sparrc/go-ping v0.0.0-20190613174326-4e5b6552494c
|
||||
github.com/n9e/agent-payload v0.0.0-20210619031503-b72325474651
|
||||
github.com/opentracing-contrib/go-stdlib v1.0.0
|
||||
github.com/opentracing/opentracing-go v1.2.0
|
||||
github.com/orcaman/concurrent-map v0.0.0-20210106121528-16402b402231
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/prometheus/client_golang v1.9.0
|
||||
github.com/prometheus/common v0.17.0
|
||||
github.com/prometheus/prometheus v1.8.2-0.20210220213500-8c8de46003d1
|
||||
github.com/smartystreets/assertions v1.0.0 // indirect
|
||||
github.com/spaolacci/murmur3 v1.1.0 // indirect
|
||||
github.com/spf13/cast v1.3.1-0.20190531151931-f31dc0aaab5a // indirect
|
||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||
github.com/spf13/viper v1.7.1
|
||||
github.com/streadway/amqp v1.0.0
|
||||
github.com/stretchr/testify v1.6.1
|
||||
github.com/toolkits/file v0.0.0-20160325033739-a5b3c5147e07
|
||||
github.com/toolkits/pkg v1.1.4
|
||||
github.com/toolkits/sys v0.0.0-20170615103026-1f33b217ffaf // indirect
|
||||
github.com/subosito/gotenv v1.2.1-0.20190917103637-de67a6614a4d // indirect
|
||||
github.com/toolkits/csrf v1.0.5
|
||||
github.com/toolkits/pkg v1.1.3
|
||||
github.com/ugorji/go/codec v1.1.7
|
||||
go.uber.org/automaxprocs v1.3.0 // indirect
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
|
||||
golang.org/x/text v0.3.3
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
||||
gopkg.in/ldap.v3 v3.1.0
|
||||
gopkg.in/square/go-jose.v2 v2.5.1 // indirect
|
||||
gopkg.in/yaml.v2 v2.3.0
|
||||
xorm.io/core v0.7.3
|
||||
xorm.io/xorm v0.8.1
|
||||
go.uber.org/atomic v1.7.0
|
||||
go.uber.org/automaxprocs v1.4.0 // indirect
|
||||
golang.org/x/text v0.3.5
|
||||
gopkg.in/ini.v1 v1.51.1 // indirect
|
||||
xorm.io/builder v0.3.7
|
||||
xorm.io/xorm v1.0.7
|
||||
)
|
||||
|
||||
replace github.com/satori/go.uuid => github.com/satori/go.uuid v1.2.0
|
||||
|
||||
// branch 0.9.3-pool-read-binary-3
|
||||
replace github.com/apache/thrift => github.com/m3db/thrift v0.0.0-20190820191926-05b5a2227fe4
|
||||
|
||||
// NB(nate): upgrading to the latest msgpack is not backwards compatibile as msgpack will no longer attempt to automatically
|
||||
// write an integer into the smallest number of bytes it will fit in. We rely on this behavior by having helper methods
|
||||
// in at least two encoders (see below) take int64s and expect that msgpack will size them down accordingly. We'll have
|
||||
// to make integer sizing explicit before attempting to upgrade.
|
||||
//
|
||||
// Encoders:
|
||||
// src/metrics/encoding/msgpack/base_encoder.go
|
||||
// src/dbnode/persist/fs/msgpack/encoder.go
|
||||
replace gopkg.in/vmihailenco/msgpack.v2 => github.com/vmihailenco/msgpack v2.8.3+incompatible
|
||||
|
||||
replace github.com/stretchr/testify => github.com/stretchr/testify v1.1.4-0.20160305165446-6fe211e49392
|
||||
|
||||
replace github.com/prometheus/common => github.com/prometheus/common v0.9.1
|
||||
|
||||
// Fix legacy import path - https://github.com/uber-go/atomic/pull/60
|
||||
replace github.com/uber-go/atomic => github.com/uber-go/atomic v1.4.0
|
||||
|
||||
// Pull in https://github.com/etcd-io/bbolt/pull/220, required for go 1.14 compatibility
|
||||
//
|
||||
// etcd 3.14.13 depends on v1.3.3, but everything before v1.3.5 has unsafe misuses, and fails hard on go 1.14
|
||||
// TODO: remove after etcd pulls in the change to a new release on 3.4 branch
|
||||
replace go.etcd.io/bbolt => go.etcd.io/bbolt v1.3.5
|
||||
|
||||
// https://github.com/ory/dockertest/issues/212
|
||||
replace golang.org/x/sys => golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6
|
||||
|
||||
// for transfer
|
||||
replace google.golang.org/grpc => google.golang.org/grpc v1.29.1
|
||||
replace google.golang.org/grpc => google.golang.org/grpc v1.26.0
|
||||
|
|
|
@ -0,0 +1,391 @@
|
|||
package http
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-contrib/sessions"
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"github.com/didi/nightingale/v5/models"
|
||||
"github.com/didi/nightingale/v5/pkg/i18n"
|
||||
"github.com/didi/nightingale/v5/pkg/ierr"
|
||||
)
|
||||
|
||||
const defaultLimit = 20
|
||||
|
||||
func dangerous(v interface{}, code ...int) {
|
||||
ierr.Dangerous(v, code...)
|
||||
}
|
||||
|
||||
func bomb(code int, format string, a ...interface{}) {
|
||||
ierr.Bomb(code, i18n.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
func bind(c *gin.Context, ptr interface{}) {
|
||||
dangerous(c.ShouldBindJSON(ptr), http.StatusBadRequest)
|
||||
}
|
||||
|
||||
func urlParamStr(c *gin.Context, field string) string {
|
||||
val := c.Param(field)
|
||||
|
||||
if val == "" {
|
||||
bomb(http.StatusBadRequest, "url param[%s] is blank", field)
|
||||
}
|
||||
|
||||
return val
|
||||
}
|
||||
|
||||
func urlParamInt64(c *gin.Context, field string) int64 {
|
||||
strval := urlParamStr(c, field)
|
||||
intval, err := strconv.ParseInt(strval, 10, 64)
|
||||
if err != nil {
|
||||
bomb(http.StatusBadRequest, "cannot convert %s to int64", strval)
|
||||
}
|
||||
|
||||
return intval
|
||||
}
|
||||
|
||||
func urlParamInt(c *gin.Context, field string) int {
|
||||
return int(urlParamInt64(c, field))
|
||||
}
|
||||
|
||||
func queryStr(c *gin.Context, key string, defaultVal ...string) string {
|
||||
val := c.Query(key)
|
||||
if val != "" {
|
||||
return val
|
||||
}
|
||||
|
||||
if len(defaultVal) == 0 {
|
||||
bomb(http.StatusBadRequest, "query param[%s] is necessary", key)
|
||||
}
|
||||
|
||||
return defaultVal[0]
|
||||
}
|
||||
|
||||
func queryInt(c *gin.Context, key string, defaultVal ...int) int {
|
||||
strv := c.Query(key)
|
||||
if strv != "" {
|
||||
intv, err := strconv.Atoi(strv)
|
||||
if err != nil {
|
||||
bomb(http.StatusBadRequest, "cannot convert [%s] to int", strv)
|
||||
}
|
||||
return intv
|
||||
}
|
||||
|
||||
if len(defaultVal) == 0 {
|
||||
bomb(http.StatusBadRequest, "query param[%s] is necessary", key)
|
||||
}
|
||||
|
||||
return defaultVal[0]
|
||||
}
|
||||
|
||||
func queryInt64(c *gin.Context, key string, defaultVal ...int64) int64 {
|
||||
strv := c.Query(key)
|
||||
if strv != "" {
|
||||
intv, err := strconv.ParseInt(strv, 10, 64)
|
||||
if err != nil {
|
||||
bomb(http.StatusBadRequest, "cannot convert [%s] to int64", strv)
|
||||
}
|
||||
return intv
|
||||
}
|
||||
|
||||
if len(defaultVal) == 0 {
|
||||
bomb(http.StatusBadRequest, "query param[%s] is necessary", key)
|
||||
}
|
||||
|
||||
return defaultVal[0]
|
||||
}
|
||||
|
||||
func queryBool(c *gin.Context, key string, defaultVal ...bool) bool {
|
||||
strv := c.Query(key)
|
||||
if strv != "" {
|
||||
if strv == "true" || strv == "1" || strv == "on" || strv == "checked" || strv == "yes" || strv == "Y" {
|
||||
return true
|
||||
} else if strv == "false" || strv == "0" || strv == "off" || strv == "no" || strv == "N" {
|
||||
return false
|
||||
} else {
|
||||
bomb(http.StatusBadRequest, "unknown arg[%s] value: %s", key, strv)
|
||||
}
|
||||
}
|
||||
|
||||
if len(defaultVal) == 0 {
|
||||
bomb(http.StatusBadRequest, "arg[%s] is necessary", key)
|
||||
}
|
||||
|
||||
return defaultVal[0]
|
||||
}
|
||||
|
||||
func offset(c *gin.Context, limit int) int {
|
||||
if limit <= 0 {
|
||||
limit = 10
|
||||
}
|
||||
|
||||
page := queryInt(c, "p", 1)
|
||||
return (page - 1) * limit
|
||||
}
|
||||
|
||||
func renderMessage(c *gin.Context, v interface{}, statusCode ...int) {
|
||||
code := 200
|
||||
if len(statusCode) > 0 {
|
||||
code = statusCode[0]
|
||||
}
|
||||
if v == nil {
|
||||
c.JSON(code, gin.H{"err": ""})
|
||||
return
|
||||
}
|
||||
|
||||
switch t := v.(type) {
|
||||
case string:
|
||||
c.JSON(code, gin.H{"err": i18n.Sprintf(t)})
|
||||
case error:
|
||||
c.JSON(code, gin.H{"err": t.Error()})
|
||||
}
|
||||
}
|
||||
|
||||
func renderData(c *gin.Context, data interface{}, err error, statusCode ...int) {
|
||||
code := 200
|
||||
if len(statusCode) > 0 {
|
||||
code = statusCode[0]
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
c.JSON(code, gin.H{"dat": data, "err": ""})
|
||||
return
|
||||
}
|
||||
|
||||
renderMessage(c, err.Error(), code)
|
||||
}
|
||||
|
||||
func renderZeroPage(c *gin.Context) {
|
||||
renderData(c, gin.H{
|
||||
"list": []int{},
|
||||
"total": 0,
|
||||
}, nil)
|
||||
}
|
||||
|
||||
type idsForm struct {
|
||||
Ids []int64 `json:"ids"`
|
||||
}
|
||||
|
||||
func (f idsForm) Validate() {
|
||||
if len(f.Ids) == 0 {
|
||||
bomb(http.StatusBadRequest, "ids empty")
|
||||
}
|
||||
}
|
||||
|
||||
func cookieUsername(c *gin.Context) string {
|
||||
session := sessions.Default(c)
|
||||
|
||||
value := session.Get("username")
|
||||
if value == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return value.(string)
|
||||
}
|
||||
|
||||
func headerUsername(c *gin.Context) string {
|
||||
token := c.GetHeader("Authorization")
|
||||
if token == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
ut, err := models.UserTokenGet("token=?", strings.TrimPrefix(token, "Bearer "))
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
if ut == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return ut.Username
|
||||
}
|
||||
|
||||
// must get username
|
||||
func loginUsername(c *gin.Context) string {
|
||||
usernameInterface, has := c.Get("username")
|
||||
if has {
|
||||
return usernameInterface.(string)
|
||||
}
|
||||
|
||||
username := cookieUsername(c)
|
||||
if username == "" {
|
||||
username = headerUsername(c)
|
||||
}
|
||||
|
||||
if username == "" {
|
||||
ierr.Bomb(http.StatusUnauthorized, "unauthorized")
|
||||
}
|
||||
|
||||
c.Set("username", username)
|
||||
return username
|
||||
}
|
||||
|
||||
func loginUser(c *gin.Context) *models.User {
|
||||
username := loginUsername(c)
|
||||
|
||||
user, err := models.UserGetByUsername(username)
|
||||
dangerous(err)
|
||||
|
||||
if user == nil {
|
||||
ierr.Bomb(http.StatusUnauthorized, "unauthorized")
|
||||
}
|
||||
|
||||
if user.Status == 1 {
|
||||
ierr.Bomb(http.StatusUnauthorized, "unauthorized")
|
||||
}
|
||||
|
||||
return user
|
||||
}
|
||||
|
||||
func User(id int64) *models.User {
|
||||
obj, err := models.UserGet("id=?", id)
|
||||
dangerous(err)
|
||||
|
||||
if obj == nil {
|
||||
bomb(http.StatusNotFound, "No such user")
|
||||
}
|
||||
|
||||
return obj
|
||||
}
|
||||
|
||||
func UserGroup(id int64) *models.UserGroup {
|
||||
obj, err := models.UserGroupGet("id=?", id)
|
||||
dangerous(err)
|
||||
|
||||
if obj == nil {
|
||||
bomb(http.StatusNotFound, "No such user group")
|
||||
}
|
||||
|
||||
return obj
|
||||
}
|
||||
|
||||
func Classpath(id int64) *models.Classpath {
|
||||
obj, err := models.ClasspathGet("id=?", id)
|
||||
dangerous(err)
|
||||
|
||||
if obj == nil {
|
||||
bomb(http.StatusNotFound, "No such classpath")
|
||||
}
|
||||
|
||||
return obj
|
||||
}
|
||||
|
||||
func Mute(id int64) *models.Mute {
|
||||
obj, err := models.MuteGet("id=?", id)
|
||||
dangerous(err)
|
||||
|
||||
if obj == nil {
|
||||
bomb(http.StatusNotFound, "No such mute config")
|
||||
}
|
||||
|
||||
return obj
|
||||
}
|
||||
|
||||
func Dashboard(id int64) *models.Dashboard {
|
||||
obj, err := models.DashboardGet("id=?", id)
|
||||
dangerous(err)
|
||||
|
||||
if obj == nil {
|
||||
bomb(http.StatusNotFound, "No such dashboard")
|
||||
}
|
||||
|
||||
return obj
|
||||
}
|
||||
|
||||
func ChartGroup(id int64) *models.ChartGroup {
|
||||
obj, err := models.ChartGroupGet("id=?", id)
|
||||
dangerous(err)
|
||||
|
||||
if obj == nil {
|
||||
bomb(http.StatusNotFound, "No such chart group")
|
||||
}
|
||||
|
||||
return obj
|
||||
}
|
||||
|
||||
func Chart(id int64) *models.Chart {
|
||||
obj, err := models.ChartGet("id=?", id)
|
||||
dangerous(err)
|
||||
|
||||
if obj == nil {
|
||||
bomb(http.StatusNotFound, "No such chart")
|
||||
}
|
||||
|
||||
return obj
|
||||
}
|
||||
|
||||
func AlertRule(id int64) *models.AlertRule {
|
||||
obj, err := models.AlertRuleGet("id=?", id)
|
||||
dangerous(err)
|
||||
|
||||
if obj == nil {
|
||||
bomb(http.StatusNotFound, "No such alert rule")
|
||||
}
|
||||
|
||||
return obj
|
||||
}
|
||||
|
||||
func AlertRuleGroup(id int64) *models.AlertRuleGroup {
|
||||
obj, err := models.AlertRuleGroupGet("id=?", id)
|
||||
dangerous(err)
|
||||
|
||||
if obj == nil {
|
||||
bomb(http.StatusNotFound, "No such alert rule group")
|
||||
}
|
||||
|
||||
return obj
|
||||
}
|
||||
|
||||
func AlertEvent(id int64) *models.AlertEvent {
|
||||
obj, err := models.AlertEventGet("id=?", id)
|
||||
dangerous(err)
|
||||
|
||||
if obj == nil {
|
||||
bomb(http.StatusNotFound, "No such alert event")
|
||||
}
|
||||
|
||||
return obj
|
||||
}
|
||||
|
||||
func CollectRule(id int64) *models.CollectRule {
|
||||
obj, err := models.CollectRuleGet("id=?", id)
|
||||
dangerous(err)
|
||||
|
||||
if obj == nil {
|
||||
bomb(http.StatusNotFound, "No such collect rule")
|
||||
}
|
||||
|
||||
return obj
|
||||
}
|
||||
|
||||
func MetricDescription(id int64) *models.MetricDescription {
|
||||
obj, err := models.MetricDescriptionGet("id=?", id)
|
||||
dangerous(err)
|
||||
|
||||
if obj == nil {
|
||||
bomb(http.StatusNotFound, "No such metric description")
|
||||
}
|
||||
|
||||
return obj
|
||||
}
|
||||
|
||||
func Resource(id int64) *models.Resource {
|
||||
obj, err := models.ResourceGet("id=?", id)
|
||||
dangerous(err)
|
||||
|
||||
if obj == nil {
|
||||
bomb(http.StatusNotFound, "No such resource")
|
||||
}
|
||||
|
||||
classpathResources, err := models.ClasspathResourceGets("res_ident=?", obj.Ident)
|
||||
dangerous(err)
|
||||
for _, cr := range classpathResources {
|
||||
obj.ClasspathIds = append(obj.ClasspathIds, cr.ClasspathId)
|
||||
}
|
||||
|
||||
return obj
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package http
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/didi/nightingale/v5/pkg/ierr"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func login() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
username := loginUsername(c)
|
||||
c.Set("username", username)
|
||||
// 这里调用loginUser主要是为了判断当前用户是否被disable了
|
||||
loginUser(c)
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
func admin() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
username := loginUsername(c)
|
||||
c.Set("username", username)
|
||||
|
||||
user := loginUser(c)
|
||||
if user.Role != "Admin" {
|
||||
ierr.Bomb(http.StatusForbidden, "forbidden")
|
||||
}
|
||||
|
||||
c.Next()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
package http
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gin-contrib/sessions"
|
||||
"github.com/gin-contrib/sessions/cookie"
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"github.com/didi/nightingale/v5/config"
|
||||
"github.com/didi/nightingale/v5/pkg/iaop"
|
||||
)
|
||||
|
||||
var srv = &http.Server{
|
||||
ReadTimeout: 10 * time.Second,
|
||||
WriteTimeout: 10 * time.Second,
|
||||
MaxHeaderBytes: 1 << 20,
|
||||
}
|
||||
|
||||
var skipPaths = []string{
|
||||
"/api/n9e/auth/login",
|
||||
"/api/n9e/self/password",
|
||||
"/api/n9e/push",
|
||||
"/v1/n9e/series",
|
||||
}
|
||||
|
||||
func Start() {
|
||||
c := config.Config
|
||||
|
||||
loggerMid := iaop.LoggerWithConfig(iaop.LoggerConfig{SkipPaths: skipPaths})
|
||||
recoveryMid := iaop.Recovery()
|
||||
|
||||
if strings.ToLower(c.HTTP.Mode) == "release" {
|
||||
gin.SetMode(gin.ReleaseMode)
|
||||
iaop.DisableConsoleColor()
|
||||
}
|
||||
|
||||
r := gin.New()
|
||||
r.Use(recoveryMid)
|
||||
|
||||
// whether print access log
|
||||
if c.HTTP.Access {
|
||||
r.Use(loggerMid)
|
||||
}
|
||||
|
||||
// use cookie to save session
|
||||
store := cookie.NewStore([]byte(config.Config.HTTP.CookieSecret))
|
||||
store.Options(sessions.Options{
|
||||
Domain: config.Config.HTTP.CookieDomain,
|
||||
MaxAge: config.Config.HTTP.CookieMaxAge,
|
||||
Secure: config.Config.HTTP.CookieSecure,
|
||||
HttpOnly: config.Config.HTTP.CookieHttpOnly,
|
||||
Path: "/",
|
||||
})
|
||||
session := sessions.Sessions(config.Config.HTTP.CookieName, store)
|
||||
r.Use(session)
|
||||
|
||||
configRoutes(r)
|
||||
configNoRoute(r)
|
||||
|
||||
srv.Addr = c.HTTP.Listen
|
||||
srv.Handler = r
|
||||
|
||||
go func() {
|
||||
fmt.Println("http.listening:", srv.Addr)
|
||||
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
||||
fmt.Printf("listening %s occur error: %s\n", srv.Addr, err)
|
||||
os.Exit(3)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// Shutdown http server
|
||||
func Shutdown() {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
if err := srv.Shutdown(ctx); err != nil {
|
||||
fmt.Println("cannot shutdown http server:", err)
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
// catching ctx.Done(). timeout of 5 seconds.
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
fmt.Println("shutdown http server timeout of 5 seconds.")
|
||||
default:
|
||||
fmt.Println("http server stopped")
|
||||
}
|
||||
}
|
||||
|
||||
func configNoRoute(r *gin.Engine) {
|
||||
r.NoRoute(func(c *gin.Context) {
|
||||
arr := strings.Split(c.Request.URL.Path, ".")
|
||||
suffix := arr[len(arr)-1]
|
||||
switch suffix {
|
||||
case "png":
|
||||
fallthrough
|
||||
case "jpeg":
|
||||
fallthrough
|
||||
case "jpg":
|
||||
fallthrough
|
||||
case "gif":
|
||||
fallthrough
|
||||
case "css":
|
||||
fallthrough
|
||||
case "js":
|
||||
fallthrough
|
||||
case "html":
|
||||
fallthrough
|
||||
case "htm":
|
||||
c.File(path.Join(strings.Split("pub/"+c.Request.URL.Path, "/")...))
|
||||
default:
|
||||
c.File(path.Join("pub", "index.html"))
|
||||
}
|
||||
})
|
||||
}
|
|
@ -0,0 +1,293 @@
|
|||
package http
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/gin-contrib/gzip"
|
||||
"github.com/gin-contrib/pprof"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/toolkits/csrf"
|
||||
|
||||
"github.com/didi/nightingale/v5/config"
|
||||
)
|
||||
|
||||
func configRoutes(r *gin.Engine) {
|
||||
csrfMid := csrf.Middleware(csrf.Options{
|
||||
Secret: config.Config.HTTP.CsrfSecret,
|
||||
ErrorFunc: func(c *gin.Context) {
|
||||
c.JSON(452, gin.H{"err": "csrf token mismatch"})
|
||||
c.Abort()
|
||||
},
|
||||
})
|
||||
|
||||
if config.Config.HTTP.Pprof {
|
||||
pprof.Register(r, "/api/debug/pprof")
|
||||
}
|
||||
|
||||
guest := r.Group("/api/n9e")
|
||||
{
|
||||
guest.GET("/ping", func(c *gin.Context) {
|
||||
c.String(200, "pong")
|
||||
})
|
||||
guest.GET("/pid", func(c *gin.Context) {
|
||||
c.String(200, fmt.Sprintf("%d", os.Getpid()))
|
||||
})
|
||||
guest.GET("/addr", func(c *gin.Context) {
|
||||
c.String(200, c.Request.RemoteAddr)
|
||||
})
|
||||
|
||||
guest.POST("/auth/login", loginPost)
|
||||
guest.GET("/auth/logout", logoutGet)
|
||||
}
|
||||
|
||||
// for brower, expose location in nginx.conf
|
||||
pages := r.Group("/api/n9e", csrfMid)
|
||||
|
||||
{
|
||||
pages.GET("/csrf", func(c *gin.Context) {
|
||||
renderData(c, csrf.GetToken(c), nil)
|
||||
})
|
||||
|
||||
pages.GET("/roles", rolesGet)
|
||||
pages.GET("/self/profile", selfProfileGet)
|
||||
pages.PUT("/self/profile", selfProfilePut)
|
||||
pages.PUT("/self/password", selfPasswordPut)
|
||||
pages.GET("/self/token", selfTokenGets)
|
||||
pages.POST("/self/token", selfTokenPost)
|
||||
pages.PUT("/self/token", selfTokenPut)
|
||||
pages.GET("/users", login(), userGets)
|
||||
pages.POST("/users", admin(), userAddPost)
|
||||
pages.GET("/user/:id/profile", login(), userProfileGet)
|
||||
pages.PUT("/user/:id/profile", admin(), userProfilePut)
|
||||
pages.PUT("/user/:id/status", admin(), userStatusPut)
|
||||
pages.PUT("/user/:id/password", admin(), userPasswordPut)
|
||||
pages.DELETE("/user/:id", admin(), userDel)
|
||||
|
||||
pages.GET("/user-groups", login(), userGroupListGet)
|
||||
pages.GET("/user-groups/mine", login(), userGroupMineGet)
|
||||
pages.POST("/user-groups", login(), userGroupAdd)
|
||||
pages.PUT("/user-group/:id", login(), userGroupPut)
|
||||
pages.GET("/user-group/:id", login(), userGroupGet)
|
||||
pages.POST("/user-group/:id/members", login(), userGroupMemberAdd)
|
||||
pages.DELETE("/user-group/:id/members", login(), userGroupMemberDel)
|
||||
pages.DELETE("/user-group/:id", login(), userGroupDel)
|
||||
|
||||
pages.GET("/classpaths", login(), classpathListGets)
|
||||
pages.POST("/classpaths", login(), classpathAdd)
|
||||
pages.PUT("/classpath/:id", login(), classpathPut)
|
||||
pages.DELETE("/classpath/:id", login(), classpathDel)
|
||||
pages.POST("/classpath/:id/resources", login(), classpathAddResources)
|
||||
pages.DELETE("/classpath/:id/resources", login(), classpathDelResources)
|
||||
pages.GET("/classpath/:id/resources", login(), classpathGetsResources)
|
||||
|
||||
pages.GET("/classpaths/favorites", login(), classpathFavoriteGet)
|
||||
pages.POST("/classpath/:id/favorites", login(), classpathFavoriteAdd)
|
||||
pages.DELETE("/classpath/:id/favorites", login(), classpathFavoriteDel)
|
||||
|
||||
pages.GET("/resources", login(), resourcesQuery)
|
||||
pages.PUT("/resources/note", resourceNotePut)
|
||||
pages.PUT("/resources/tags", resourceTagsPut)
|
||||
pages.PUT("/resources/classpaths", resourceClasspathsPut)
|
||||
pages.PUT("/resources/mute", resourceMutePut)
|
||||
pages.GET("/resource/:id", login(), resourceGet)
|
||||
pages.DELETE("/resource/:id", login(), resourceDel)
|
||||
|
||||
pages.GET("/mutes", login(), muteGets)
|
||||
pages.POST("/mutes", login(), muteAdd)
|
||||
pages.GET("/mute/:id", login(), muteGet)
|
||||
pages.DELETE("/mute/:id", login(), muteDel)
|
||||
|
||||
pages.GET("/dashboards", login(), dashboardGets)
|
||||
pages.POST("/dashboards", login(), dashboardAdd)
|
||||
pages.POST("/dashboards-clone", login(), dashboardClone)
|
||||
pages.GET("/dashboard/:id", login(), dashboardGet)
|
||||
pages.PUT("/dashboard/:id", login(), dashboardPut)
|
||||
pages.DELETE("/dashboard/:id", login(), dashboardDel)
|
||||
pages.POST("/dashboard/:id/favorites", login(), dashboardFavoriteAdd)
|
||||
pages.DELETE("/dashboard/:id/favorites", login(), dashboardFavoriteDel)
|
||||
pages.GET("/dashboard/:id/chart-groups", login(), chartGroupGets)
|
||||
pages.POST("/dashboard/:id/chart-groups", login(), chartGroupAdd)
|
||||
|
||||
pages.PUT("/chart-groups", login(), chartGroupsPut)
|
||||
pages.DELETE("/chart-group/:id", login(), chartGroupDel)
|
||||
pages.GET("/chart-group/:id/charts", login(), chartGets)
|
||||
pages.POST("/chart-group/:id/charts", login(), chartAdd)
|
||||
pages.PUT("/chart/:id", login(), chartPut)
|
||||
pages.DELETE("/chart/:id", login(), chartDel)
|
||||
pages.PUT("/charts/configs", login(), chartConfigsPut)
|
||||
pages.GET("/charts/tmps", login(), chartTmpGets)
|
||||
pages.POST("/charts/tmps", login(), chartTmpAdd)
|
||||
|
||||
pages.GET("/alert-rule-groups", login(), alertRuleGroupGets)
|
||||
pages.GET("/alert-rule-groups/favorites", login(), alertRuleGroupFavoriteGet)
|
||||
pages.POST("/alert-rule-groups", login(), alertRuleGroupAdd)
|
||||
pages.GET("/alert-rule-group/:id", login(), alertRuleGroupGet)
|
||||
pages.GET("/alert-rule-group/:id/alert-rules", login(), alertRuleOfGroupGet)
|
||||
pages.DELETE("/alert-rule-group/:id/alert-rules", login(), alertRuleOfGroupDel)
|
||||
pages.PUT("/alert-rule-group/:id", login(), alertRuleGroupPut)
|
||||
pages.DELETE("/alert-rule-group/:id", login(), alertRuleGroupDel)
|
||||
pages.POST("/alert-rule-group/:id/favorites", login(), alertRuleGroupFavoriteAdd)
|
||||
pages.DELETE("/alert-rule-group/:id/favorites", login(), alertRuleGroupFavoriteDel)
|
||||
pages.GET("/check-promql", checkPromeQl)
|
||||
|
||||
pages.POST("/alert-rules", login(), alertRuleAdd)
|
||||
pages.PUT("/alert-rules/status", login(), alertRuleStatusPut)
|
||||
pages.GET("/alert-rule/:id", login(), alertRuleGet)
|
||||
pages.PUT("/alert-rule/:id", login(), alertRulePut)
|
||||
pages.DELETE("/alert-rule/:id", login(), alertRuleDel)
|
||||
|
||||
pages.GET("/alert-events", login(), alertEventGets)
|
||||
pages.DELETE("/alert-events", login(), alertEventsDel)
|
||||
pages.GET("/alert-event/:id", login(), alertEventGet)
|
||||
pages.DELETE("/alert-event/:id", login(), alertEventDel)
|
||||
|
||||
pages.GET("/classpath/:id/collect-rules", login(), collectRuleGets)
|
||||
pages.POST("/collect-rules", login(), collectRuleAdd)
|
||||
pages.DELETE("/collect-rules", login(), collectRuleDel)
|
||||
pages.PUT("/collect-rule/:id", login(), collectRulePut)
|
||||
pages.POST("/log/check", regExpCheck) // check collect rule
|
||||
|
||||
pages.GET("/metric-descriptions", metricDescriptionGets)
|
||||
pages.POST("/metric-descriptions", login(), metricDescriptionAdd)
|
||||
pages.DELETE("/metric-descriptions", login(), metricDescriptionDel)
|
||||
pages.PUT("/metric-description/:id", login(), metricDescriptionPut)
|
||||
|
||||
pages.GET("/contact-channels", contactChannelsGet)
|
||||
pages.GET("/notify-channels", notifyChannelsGet)
|
||||
|
||||
pages.POST("/query", GetData)
|
||||
pages.POST("/tag-keys", GetTagKeys)
|
||||
pages.POST("/tag-values", GetTagValues)
|
||||
pages.POST("/tag-metrics", GetMetrics)
|
||||
pages.POST("/tag-pairs", GetTagPairs)
|
||||
}
|
||||
|
||||
// for thirdparty, do not expose location in nginx.conf
|
||||
v1 := r.Group("/v1/n9e")
|
||||
{
|
||||
v1.GET("/roles", rolesGet)
|
||||
v1.GET("/self/profile", selfProfileGet)
|
||||
v1.PUT("/self/profile", selfProfilePut)
|
||||
v1.PUT("/self/password", selfPasswordPut)
|
||||
v1.GET("/self/token", selfTokenGets)
|
||||
v1.POST("/self/token", selfTokenPost)
|
||||
v1.PUT("/self/token", selfTokenPut)
|
||||
v1.GET("/users", login(), userGets)
|
||||
v1.POST("/users", admin(), userAddPost)
|
||||
v1.GET("/user/:id/profile", login(), userProfileGet)
|
||||
v1.PUT("/user/:id/profile", admin(), userProfilePut)
|
||||
v1.PUT("/user/:id/status", admin(), userStatusPut)
|
||||
v1.PUT("/user/:id/password", admin(), userPasswordPut)
|
||||
v1.DELETE("/user/:id", admin(), userDel)
|
||||
|
||||
v1.GET("/user-groups", login(), userGroupListGet)
|
||||
v1.GET("/user-groups/mine", login(), userGroupMineGet)
|
||||
v1.POST("/user-groups", login(), userGroupAdd)
|
||||
v1.PUT("/user-group/:id", login(), userGroupPut)
|
||||
v1.GET("/user-group/:id", login(), userGroupGet)
|
||||
v1.POST("/user-group/:id/members", login(), userGroupMemberAdd)
|
||||
v1.DELETE("/user-group/:id/members", login(), userGroupMemberDel)
|
||||
v1.DELETE("/user-group/:id", login(), userGroupDel)
|
||||
|
||||
v1.GET("/classpaths", login(), classpathListGets)
|
||||
v1.POST("/classpaths", login(), classpathAdd)
|
||||
v1.PUT("/classpath/:id", login(), classpathPut)
|
||||
v1.DELETE("/classpath/:id", login(), classpathDel)
|
||||
v1.POST("/classpath/:id/resources", login(), classpathAddResources)
|
||||
v1.DELETE("/classpath/:id/resources", login(), classpathDelResources)
|
||||
v1.GET("/classpath/:id/resources", login(), classpathGetsResources)
|
||||
|
||||
v1.GET("/classpaths/favorites", login(), classpathFavoriteGet)
|
||||
v1.POST("/classpath/:id/favorites", login(), classpathFavoriteAdd)
|
||||
v1.DELETE("/classpath/:id/favorites", login(), classpathFavoriteDel)
|
||||
|
||||
v1.GET("/resources", login(), resourcesQuery)
|
||||
v1.PUT("/resources/note", resourceNotePut)
|
||||
v1.PUT("/resources/tags", resourceTagsPut)
|
||||
v1.PUT("/resources/classpaths", resourceClasspathsPut)
|
||||
v1.PUT("/resources/mute", resourceMutePut)
|
||||
v1.GET("/resource/:id", login(), resourceGet)
|
||||
v1.DELETE("/resource/:id", login(), resourceDel)
|
||||
|
||||
v1.GET("/classpath/:id/collect-rules", login(), collectRuleGets)
|
||||
|
||||
v1.GET("/mutes", login(), muteGets)
|
||||
v1.POST("/mutes", login(), muteAdd)
|
||||
v1.GET("/mute/:id", login(), muteGet)
|
||||
v1.DELETE("/mute/:id", login(), muteDel)
|
||||
|
||||
v1.GET("/dashboards", login(), dashboardGets)
|
||||
v1.POST("/dashboards", login(), dashboardAdd)
|
||||
v1.GET("/dashboard/:id", login(), dashboardGet)
|
||||
v1.PUT("/dashboard/:id", login(), dashboardPut)
|
||||
v1.DELETE("/dashboard/:id", login(), dashboardDel)
|
||||
v1.POST("/dashboard/:id/favorites", login(), dashboardFavoriteAdd)
|
||||
v1.DELETE("/dashboard/:id/favorites", login(), dashboardFavoriteDel)
|
||||
v1.GET("/dashboard/:id/chart-groups", login(), chartGroupGets)
|
||||
v1.POST("/dashboard/:id/chart-groups", login(), chartGroupAdd)
|
||||
|
||||
v1.PUT("/chart-groups", login(), chartGroupsPut)
|
||||
v1.DELETE("/chart-group/:id", login(), chartGroupDel)
|
||||
v1.GET("/chart-group/:id/charts", login(), chartGets)
|
||||
v1.POST("/chart-group/:id/charts", login(), chartAdd)
|
||||
v1.PUT("/chart/:id", login(), chartPut)
|
||||
v1.DELETE("/chart/:id", login(), chartDel)
|
||||
v1.PUT("/charts/configs", login(), chartConfigsPut)
|
||||
v1.GET("/charts/tmps", login(), chartTmpGets)
|
||||
v1.POST("/charts/tmps", login(), chartTmpAdd)
|
||||
|
||||
v1.GET("/alert-rule-groups", login(), alertRuleGroupGets)
|
||||
v1.POST("/alert-rule-groups", login(), alertRuleGroupAdd)
|
||||
v1.GET("/alert-rule-group/:id", login(), alertRuleGroupGet)
|
||||
v1.PUT("/alert-rule-group/:id", login(), alertRuleGroupPut)
|
||||
v1.DELETE("/alert-rule-group/:id", login(), alertRuleGroupDel)
|
||||
|
||||
v1.GET("/alert-rule-groups/favorites", login(), alertRuleGroupFavoriteGet)
|
||||
v1.DELETE("/alert-rule-group/:id/favorites", login(), alertRuleGroupFavoriteDel)
|
||||
v1.POST("/alert-rule-group/:id/favorites", login(), alertRuleGroupFavoriteAdd)
|
||||
|
||||
v1.GET("/alert-rule-group/:id/alert-rules", login(), alertRuleOfGroupGet)
|
||||
v1.DELETE("/alert-rule-group/:id/alert-rules", login(), alertRuleOfGroupDel)
|
||||
|
||||
v1.POST("/alert-rules", login(), alertRuleAdd)
|
||||
v1.PUT("/alert-rules/status", login(), alertRuleStatusPut)
|
||||
v1.GET("/alert-rule/:id", login(), alertRuleGet)
|
||||
v1.PUT("/alert-rule/:id", login(), alertRulePut)
|
||||
v1.DELETE("/alert-rule/:id", login(), alertRuleDel)
|
||||
|
||||
v1.GET("/alert-events", login(), alertEventGets)
|
||||
v1.DELETE("/alert-events", login(), alertEventsDel)
|
||||
v1.GET("/alert-event/:id", login(), alertEventGet)
|
||||
v1.DELETE("/alert-event/:id", login(), alertEventDel)
|
||||
|
||||
v1.POST("/collect-rules", login(), collectRuleAdd)
|
||||
v1.DELETE("/collect-rules", login(), collectRuleDel)
|
||||
v1.PUT("/collect-rule/:id", login(), collectRulePut)
|
||||
v1.GET("/collect-rules-belong-to-ident", collectRuleGetsByIdent)
|
||||
v1.GET("/collect-rules-summary", collectRuleSummaryGetByIdent)
|
||||
|
||||
v1.GET("/metric-descriptions", metricDescriptionGets)
|
||||
v1.POST("/metric-descriptions", login(), metricDescriptionAdd)
|
||||
v1.DELETE("/metric-descriptions", login(), metricDescriptionDel)
|
||||
v1.PUT("/metric-description/:id", login(), metricDescriptionPut)
|
||||
|
||||
v1.GET("/contact-channels", contactChannelsGet)
|
||||
v1.GET("/notify-channels", notifyChannelsGet)
|
||||
|
||||
v1.POST("/push", PushData)
|
||||
|
||||
v1.POST("/query", GetData)
|
||||
v1.GET("/check-promql", checkPromeQl)
|
||||
v1.POST("/tag-keys", GetTagKeys)
|
||||
v1.POST("/tag-values", GetTagValues)
|
||||
v1.POST("/tag-metrics", GetMetrics)
|
||||
v1.POST("/tag-pairs", GetTagPairs)
|
||||
}
|
||||
|
||||
push := r.Group("/v1/n9e/series").Use(gzip.Gzip(gzip.DefaultCompression))
|
||||
{
|
||||
push.POST("", PushSeries)
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
package http
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"github.com/didi/nightingale/v5/models"
|
||||
)
|
||||
|
||||
func alertEventGets(c *gin.Context) {
|
||||
stime := queryInt64(c, "stime", 0)
|
||||
etime := queryInt64(c, "etime", 0)
|
||||
hours := queryInt64(c, "hours", 0)
|
||||
now := time.Now().Unix()
|
||||
if hours != 0 {
|
||||
stime = now - 3600*hours
|
||||
etime = now + 3600*24
|
||||
}
|
||||
|
||||
if stime != 0 && etime == 0 {
|
||||
etime = now + 3600*24
|
||||
}
|
||||
|
||||
query := queryStr(c, "query", "")
|
||||
priority := queryInt(c, "priority", -1)
|
||||
status := queryInt(c, "status", -1)
|
||||
limit := queryInt(c, "limit", defaultLimit)
|
||||
|
||||
total, err := models.AlertEventTotal(stime, etime, query, status, priority)
|
||||
dangerous(err)
|
||||
|
||||
list, err := models.AlertEventGets(stime, etime, query, status, priority, limit, offset(c, limit))
|
||||
dangerous(err)
|
||||
|
||||
for i := 0; i < len(list); i++ {
|
||||
dangerous(list[i].FillObjs())
|
||||
}
|
||||
|
||||
if len(list) == 0 {
|
||||
renderZeroPage(c)
|
||||
return
|
||||
}
|
||||
|
||||
renderData(c, map[string]interface{}{
|
||||
"total": total,
|
||||
"list": list,
|
||||
}, nil)
|
||||
}
|
||||
|
||||
func alertEventGet(c *gin.Context) {
|
||||
renderData(c, AlertEvent(urlParamInt64(c, "id")), nil)
|
||||
}
|
||||
|
||||
func alertEventDel(c *gin.Context) {
|
||||
loginUser(c).MustPerm("alert_event_delete")
|
||||
renderMessage(c, AlertEvent(urlParamInt64(c, "id")).Del())
|
||||
}
|
||||
|
||||
func alertEventsDel(c *gin.Context) {
|
||||
var f idsForm
|
||||
bind(c, &f)
|
||||
f.Validate()
|
||||
loginUser(c).MustPerm("alert_event_delete")
|
||||
renderMessage(c, models.AlertEventsDel(f.Ids))
|
||||
}
|
|
@ -0,0 +1,165 @@
|
|||
package http
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"github.com/didi/nightingale/v5/config"
|
||||
"github.com/didi/nightingale/v5/models"
|
||||
)
|
||||
|
||||
func alertRuleGet(c *gin.Context) {
|
||||
renderData(c, AlertRule(urlParamInt64(c, "id")), nil)
|
||||
}
|
||||
|
||||
type alertRuleForm struct {
|
||||
GroupId int64 `json:"group_id"`
|
||||
Name string `json:"name"`
|
||||
Note string `json:"note"`
|
||||
Type int `json:"type"`
|
||||
Status int `json:"status"`
|
||||
Expression json.RawMessage `json:"expression"`
|
||||
AppendTags string `json:"append_tags"`
|
||||
EnableStime string `json:"enable_stime"`
|
||||
EnableEtime string `json:"enable_etime"`
|
||||
EnableDaysOfWeek string `json:"enable_days_of_week"`
|
||||
AlertDuration int `json:"alert_duration"`
|
||||
RecoveryDuration int `json:"recovery_duration"`
|
||||
RecoveryNotify int `json:"recovery_notify"`
|
||||
Priority int `json:"priority"`
|
||||
NotifyChannels string `json:"notify_channels"`
|
||||
NotifyGroups string `json:"notify_groups"`
|
||||
NotifyUsers string `json:"notify_users"`
|
||||
Callbacks string `json:"callbacks"`
|
||||
RunbookUrl string `json:"runbook_url"`
|
||||
}
|
||||
|
||||
func alertRuleAdd(c *gin.Context) {
|
||||
var f []alertRuleForm
|
||||
bind(c, &f)
|
||||
|
||||
me := loginUser(c).MustPerm("alert_rule_create")
|
||||
|
||||
for _, alertRule := range f {
|
||||
arg := AlertRuleGroup(alertRule.GroupId)
|
||||
alertRuleWritePermCheck(arg, me)
|
||||
|
||||
ar := models.AlertRule{
|
||||
GroupId: alertRule.GroupId,
|
||||
Name: alertRule.Name,
|
||||
Type: alertRule.Type,
|
||||
Note: alertRule.Note,
|
||||
Expression: alertRule.Expression,
|
||||
AlertDuration: alertRule.AlertDuration,
|
||||
AppendTags: alertRule.AppendTags,
|
||||
EnableStime: alertRule.EnableStime,
|
||||
EnableEtime: alertRule.EnableEtime,
|
||||
EnableDaysOfWeek: alertRule.EnableDaysOfWeek,
|
||||
RecoveryNotify: alertRule.RecoveryNotify,
|
||||
Priority: alertRule.Priority,
|
||||
NotifyChannels: alertRule.NotifyChannels,
|
||||
NotifyGroups: alertRule.NotifyGroups,
|
||||
NotifyUsers: alertRule.NotifyUsers,
|
||||
Callbacks: alertRule.Callbacks,
|
||||
RunbookUrl: alertRule.RunbookUrl,
|
||||
CreateBy: me.Username,
|
||||
UpdateBy: me.Username,
|
||||
}
|
||||
dangerous(ar.Add())
|
||||
}
|
||||
|
||||
renderMessage(c, nil)
|
||||
}
|
||||
|
||||
func alertRulePut(c *gin.Context) {
|
||||
var f alertRuleForm
|
||||
bind(c, &f)
|
||||
|
||||
me := loginUser(c).MustPerm("alert_rule_modify")
|
||||
ar := AlertRule(urlParamInt64(c, "id"))
|
||||
arg := AlertRuleGroup(ar.GroupId)
|
||||
alertRuleWritePermCheck(arg, me)
|
||||
|
||||
ar.Name = f.Name
|
||||
ar.Note = f.Note
|
||||
ar.Status = f.Status
|
||||
ar.AlertDuration = f.AlertDuration
|
||||
ar.Expression = f.Expression
|
||||
ar.AppendTags = f.AppendTags
|
||||
ar.EnableStime = f.EnableStime
|
||||
ar.EnableEtime = f.EnableEtime
|
||||
ar.EnableDaysOfWeek = f.EnableDaysOfWeek
|
||||
ar.RecoveryNotify = f.RecoveryNotify
|
||||
ar.Priority = f.Priority
|
||||
ar.NotifyChannels = f.NotifyChannels
|
||||
ar.NotifyGroups = f.NotifyGroups
|
||||
ar.NotifyUsers = f.NotifyUsers
|
||||
ar.Callbacks = f.Callbacks
|
||||
ar.RunbookUrl = f.RunbookUrl
|
||||
ar.CreateBy = me.Username
|
||||
ar.UpdateAt = time.Now().Unix()
|
||||
ar.UpdateBy = me.Username
|
||||
|
||||
renderMessage(c, ar.Update(
|
||||
"name",
|
||||
"note",
|
||||
"status",
|
||||
"alert_duration",
|
||||
"expression",
|
||||
"res_filters",
|
||||
"tags_filters",
|
||||
"append_tags",
|
||||
"enable_stime",
|
||||
"enable_etime",
|
||||
"enable_days_of_week",
|
||||
"recovery_duration",
|
||||
"recovery_notify",
|
||||
"priority",
|
||||
"notify_channels",
|
||||
"notify_groups",
|
||||
"notify_users",
|
||||
"callbacks",
|
||||
"runbook_url",
|
||||
"update_at",
|
||||
"update_by",
|
||||
))
|
||||
}
|
||||
|
||||
type alertRuleStatusForm struct {
|
||||
Ids []int64 `json:"ids"`
|
||||
Status int `json:"status"`
|
||||
}
|
||||
|
||||
func alertRuleStatusPut(c *gin.Context) {
|
||||
var f alertRuleStatusForm
|
||||
bind(c, &f)
|
||||
me := loginUser(c).MustPerm("alert_rule_modify")
|
||||
|
||||
if len(f.Ids) == 0 {
|
||||
bomb(http.StatusBadRequest, "ids is empty")
|
||||
}
|
||||
|
||||
for _, id := range f.Ids {
|
||||
alertRule := AlertRule(id)
|
||||
arg := AlertRuleGroup(alertRule.GroupId)
|
||||
alertRuleWritePermCheck(arg, me)
|
||||
}
|
||||
|
||||
renderMessage(c, models.AlertRuleUpdateStatus(f.Ids, f.Status))
|
||||
}
|
||||
|
||||
func alertRuleDel(c *gin.Context) {
|
||||
me := loginUser(c).MustPerm("alert_rule_delete")
|
||||
alertRule := AlertRule(urlParamInt64(c, "id"))
|
||||
arg := AlertRuleGroup(alertRule.GroupId)
|
||||
alertRuleWritePermCheck(arg, me)
|
||||
|
||||
renderMessage(c, alertRule.Del())
|
||||
}
|
||||
|
||||
func notifyChannelsGet(c *gin.Context) {
|
||||
renderData(c, config.Config.NotifyChannels, nil)
|
||||
}
|
|
@ -0,0 +1,165 @@
|
|||
package http
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"github.com/didi/nightingale/v5/cache"
|
||||
"github.com/didi/nightingale/v5/models"
|
||||
)
|
||||
|
||||
func alertRuleGroupGets(c *gin.Context) {
|
||||
limit := queryInt(c, "limit", defaultLimit)
|
||||
query := queryStr(c, "query", "")
|
||||
|
||||
total, err := models.AlertRuleGroupTotal(query)
|
||||
dangerous(err)
|
||||
|
||||
list, err := models.AlertRuleGroupGets(query, limit, offset(c, limit))
|
||||
dangerous(err)
|
||||
|
||||
renderData(c, gin.H{
|
||||
"list": list,
|
||||
"total": total,
|
||||
}, nil)
|
||||
}
|
||||
|
||||
func alertRuleGroupFavoriteGet(c *gin.Context) {
|
||||
lst, err := loginUser(c).FavoriteAlertRuleGroups()
|
||||
renderData(c, lst, err)
|
||||
}
|
||||
|
||||
type alertRuleGroupForm struct {
|
||||
Name string `json:"name"`
|
||||
UserGroupIds string `json:"user_group_ids"`
|
||||
}
|
||||
|
||||
func alertRuleGroupAdd(c *gin.Context) {
|
||||
var f alertRuleGroupForm
|
||||
bind(c, &f)
|
||||
|
||||
me := loginUser(c).MustPerm("alert_rule_group_create")
|
||||
|
||||
arg := models.AlertRuleGroup{
|
||||
Name: f.Name,
|
||||
UserGroupIds: f.UserGroupIds,
|
||||
CreateBy: me.Username,
|
||||
UpdateBy: me.Username,
|
||||
}
|
||||
|
||||
err := arg.Add()
|
||||
if err == nil {
|
||||
// 我创建的,顺便设置为我关注的
|
||||
models.AlertRuleGroupFavoriteAdd(arg.Id, me.Id)
|
||||
}
|
||||
|
||||
renderMessage(c, err)
|
||||
}
|
||||
|
||||
func alertRuleGroupGet(c *gin.Context) {
|
||||
alertRuleGroup := AlertRuleGroup(urlParamInt64(c, "id"))
|
||||
alertRuleGroup.FillUserGroups()
|
||||
renderData(c, alertRuleGroup, nil)
|
||||
}
|
||||
|
||||
func alertRuleOfGroupGet(c *gin.Context) {
|
||||
ars, err := models.AlertRulesOfGroup(urlParamInt64(c, "id"))
|
||||
renderData(c, ars, err)
|
||||
}
|
||||
|
||||
func alertRuleOfGroupDel(c *gin.Context) {
|
||||
var f idsForm
|
||||
bind(c, &f)
|
||||
f.Validate()
|
||||
loginUser(c).MustPerm("alert_rule_delete")
|
||||
renderMessage(c, models.AlertRulesDel(f.Ids))
|
||||
}
|
||||
|
||||
func alertRuleGroupPut(c *gin.Context) {
|
||||
var f alertRuleGroupForm
|
||||
bind(c, &f)
|
||||
|
||||
me := loginUser(c).MustPerm("alert_rule_group_modify")
|
||||
arg := AlertRuleGroup(urlParamInt64(c, "id"))
|
||||
alertRuleWritePermCheck(arg, me)
|
||||
|
||||
if arg.Name != f.Name {
|
||||
num, err := models.AlertRuleGroupCount("name=? and id<>?", f.Name, arg.Id)
|
||||
dangerous(err)
|
||||
|
||||
if num > 0 {
|
||||
bomb(200, "AlertRuleGroup %s already exists", f.Name)
|
||||
}
|
||||
}
|
||||
|
||||
arg.Name = f.Name
|
||||
arg.UserGroupIds = f.UserGroupIds
|
||||
arg.UpdateBy = me.Username
|
||||
arg.UpdateAt = time.Now().Unix()
|
||||
|
||||
renderMessage(c, arg.Update("name", "update_by", "update_at", "user_group_ids"))
|
||||
}
|
||||
|
||||
func alertRuleGroupDel(c *gin.Context) {
|
||||
me := loginUser(c).MustPerm("alert_rule_group_delete")
|
||||
arg := AlertRuleGroup(urlParamInt64(c, "id"))
|
||||
alertRuleWritePermCheck(arg, me)
|
||||
|
||||
renderMessage(c, arg.Del())
|
||||
}
|
||||
|
||||
func alertRuleGroupFavoriteAdd(c *gin.Context) {
|
||||
me := loginUser(c)
|
||||
arg := AlertRuleGroup(urlParamInt64(c, "id"))
|
||||
renderMessage(c, models.AlertRuleGroupFavoriteAdd(arg.Id, me.Id))
|
||||
}
|
||||
|
||||
func alertRuleGroupFavoriteDel(c *gin.Context) {
|
||||
me := loginUser(c)
|
||||
arg := AlertRuleGroup(urlParamInt64(c, "id"))
|
||||
renderMessage(c, models.AlertRuleGroupFavoriteDel(arg.Id, me.Id))
|
||||
}
|
||||
|
||||
func alertRuleWritePermCheck(alertRuleGroup *models.AlertRuleGroup, user *models.User) {
|
||||
if user.Role == "Admin" {
|
||||
return
|
||||
}
|
||||
|
||||
gids := IdsInt64(alertRuleGroup.UserGroupIds)
|
||||
if len(gids) == 0 {
|
||||
// 压根没有配置管理团队,表示对所有Standard角色放开,那就不校验了
|
||||
return
|
||||
}
|
||||
|
||||
for _, gid := range gids {
|
||||
if cache.UserGroupMember.Exists(gid, user.Id) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
bomb(http.StatusForbidden, "no permission")
|
||||
}
|
||||
|
||||
func IdsInt64(ids string) []int64 {
|
||||
if ids == "" {
|
||||
return []int64{}
|
||||
}
|
||||
|
||||
arr := strings.Fields(ids)
|
||||
count := len(arr)
|
||||
ret := make([]int64, 0, count)
|
||||
for i := 0; i < count; i++ {
|
||||
if arr[i] != "" {
|
||||
id, err := strconv.ParseInt(arr[i], 10, 64)
|
||||
if err == nil {
|
||||
ret = append(ret, id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
package http
|
||||
|
||||
import (
|
||||
"github.com/gin-contrib/sessions"
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"github.com/didi/nightingale/v5/config"
|
||||
"github.com/didi/nightingale/v5/models"
|
||||
)
|
||||
|
||||
type loginForm struct {
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
}
|
||||
|
||||
func loginPost(c *gin.Context) {
|
||||
var f loginForm
|
||||
bind(c, &f)
|
||||
|
||||
user, err1 := models.PassLogin(f.Username, f.Password)
|
||||
if err1 == nil {
|
||||
if user.Status == 1 {
|
||||
renderMessage(c, "User disabled")
|
||||
return
|
||||
}
|
||||
session := sessions.Default(c)
|
||||
session.Set("username", f.Username)
|
||||
session.Save()
|
||||
renderData(c, user, nil)
|
||||
return
|
||||
}
|
||||
|
||||
// password login fail, try ldap
|
||||
if config.Config.LDAP.Enable {
|
||||
user, err2 := models.LdapLogin(f.Username, f.Password)
|
||||
if err2 == nil {
|
||||
if user.Status == 1 {
|
||||
renderMessage(c, "User disabled")
|
||||
return
|
||||
}
|
||||
session := sessions.Default(c)
|
||||
session.Set("username", f.Username)
|
||||
session.Save()
|
||||
renderData(c, user, nil)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// password and ldap both fail
|
||||
renderMessage(c, err1)
|
||||
}
|
||||
|
||||
func logoutGet(c *gin.Context) {
|
||||
session := sessions.Default(c)
|
||||
session.Set("username", "")
|
||||
session.Save()
|
||||
renderMessage(c, nil)
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
package http
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"github.com/didi/nightingale/v5/models"
|
||||
)
|
||||
|
||||
func chartGets(c *gin.Context) {
|
||||
objs, err := models.ChartGets(urlParamInt64(c, "id"))
|
||||
renderData(c, objs, err)
|
||||
}
|
||||
|
||||
type chartForm struct {
|
||||
Configs string `json:"configs"`
|
||||
Weight int `json:"weight"`
|
||||
}
|
||||
|
||||
func chartAdd(c *gin.Context) {
|
||||
var f chartForm
|
||||
bind(c, &f)
|
||||
|
||||
loginUser(c).MustPerm("dashboard_modify")
|
||||
|
||||
cg := ChartGroup(urlParamInt64(c, "id"))
|
||||
ct := models.Chart{
|
||||
GroupId: cg.Id,
|
||||
Configs: f.Configs,
|
||||
Weight: f.Weight,
|
||||
}
|
||||
|
||||
dangerous(ct.Add())
|
||||
|
||||
renderData(c, ct, nil)
|
||||
}
|
||||
|
||||
type chartPutForm struct {
|
||||
Configs string `json:"configs"`
|
||||
}
|
||||
|
||||
func chartPut(c *gin.Context) {
|
||||
var f chartPutForm
|
||||
bind(c, &f)
|
||||
|
||||
loginUser(c).MustPerm("dashboard_modify")
|
||||
|
||||
ct := Chart(urlParamInt64(c, "id"))
|
||||
ct.Configs = f.Configs
|
||||
|
||||
dangerous(ct.Update("configs"))
|
||||
|
||||
renderData(c, ct, nil)
|
||||
}
|
||||
|
||||
func chartDel(c *gin.Context) {
|
||||
loginUser(c).MustPerm("dashboard_modify")
|
||||
renderMessage(c, Chart(urlParamInt64(c, "id")).Del())
|
||||
}
|
||||
|
||||
type chartConfig struct {
|
||||
Id int64 `json:"id"`
|
||||
GroupId int64 `json:"group_id"`
|
||||
Configs string `json:"configs"`
|
||||
}
|
||||
|
||||
func chartConfigsPut(c *gin.Context) {
|
||||
var arr []chartConfig
|
||||
bind(c, &arr)
|
||||
|
||||
loginUser(c).MustPerm("dashboard_modify")
|
||||
|
||||
for i := 0; i < len(arr); i++ {
|
||||
ct := Chart(arr[i].Id)
|
||||
ct.Configs = arr[i].Configs
|
||||
if arr[i].GroupId > 0 {
|
||||
ct.GroupId = arr[i].GroupId
|
||||
}
|
||||
dangerous(ct.Update("configs", "group_id"))
|
||||
}
|
||||
|
||||
renderMessage(c, nil)
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
package http
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"github.com/didi/nightingale/v5/models"
|
||||
)
|
||||
|
||||
func chartGroupGets(c *gin.Context) {
|
||||
objs, err := models.ChartGroupGets(urlParamInt64(c, "id"))
|
||||
renderData(c, objs, err)
|
||||
}
|
||||
|
||||
type chartGroupForm struct {
|
||||
Name string `json:"name"`
|
||||
Weight int `json:"weight"`
|
||||
}
|
||||
|
||||
func chartGroupAdd(c *gin.Context) {
|
||||
var f chartGroupForm
|
||||
bind(c, &f)
|
||||
|
||||
loginUser(c).MustPerm("dashboard_modify")
|
||||
|
||||
d := Dashboard(urlParamInt64(c, "id"))
|
||||
|
||||
cg := models.ChartGroup{
|
||||
DashboardId: d.Id,
|
||||
Name: f.Name,
|
||||
Weight: f.Weight,
|
||||
}
|
||||
|
||||
dangerous(cg.Add())
|
||||
|
||||
renderData(c, cg, nil)
|
||||
}
|
||||
|
||||
func chartGroupsPut(c *gin.Context) {
|
||||
var arr []models.ChartGroup
|
||||
bind(c, &arr)
|
||||
|
||||
loginUser(c).MustPerm("dashboard_modify")
|
||||
|
||||
for i := 0; i < len(arr); i++ {
|
||||
dangerous(arr[i].Update("name", "weight"))
|
||||
}
|
||||
|
||||
renderMessage(c, nil)
|
||||
}
|
||||
|
||||
func chartGroupDel(c *gin.Context) {
|
||||
loginUser(c).MustPerm("dashboard_modify")
|
||||
cg := models.ChartGroup{Id: urlParamInt64(c, "id")}
|
||||
renderMessage(c, cg.Del())
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
package http
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"github.com/didi/nightingale/v5/models"
|
||||
)
|
||||
|
||||
type chartTmpForm struct {
|
||||
Configs string `json:"configs"`
|
||||
}
|
||||
|
||||
func chartTmpAdd(c *gin.Context) {
|
||||
ids := []int64{}
|
||||
|
||||
var forms []chartTmpForm
|
||||
bind(c, &forms)
|
||||
|
||||
for _, f := range forms {
|
||||
chart := models.ChartTmp{
|
||||
Configs: f.Configs,
|
||||
CreateBy: loginUsername(c),
|
||||
CreateAt: time.Now().Unix(),
|
||||
}
|
||||
dangerous(chart.Add())
|
||||
ids = append(ids, chart.Id)
|
||||
}
|
||||
|
||||
renderData(c, ids, nil)
|
||||
}
|
||||
|
||||
func chartTmpGets(c *gin.Context) {
|
||||
objs := []*models.ChartTmp{}
|
||||
idStr := queryStr(c, "ids")
|
||||
ids := strings.Split(idStr, ",")
|
||||
for _, id := range ids {
|
||||
i, err := strconv.ParseInt(id, 10, 64)
|
||||
dangerous(err)
|
||||
|
||||
obj, err := models.ChartTmpGet("id=?", i)
|
||||
dangerous(err)
|
||||
objs = append(objs, obj)
|
||||
}
|
||||
|
||||
renderData(c, objs, nil)
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
package http
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"github.com/didi/nightingale/v5/models"
|
||||
)
|
||||
|
||||
func classpathListGets(c *gin.Context) {
|
||||
limit := queryInt(c, "limit", defaultLimit)
|
||||
query := queryStr(c, "query", "")
|
||||
|
||||
total, err := models.ClasspathTotal(query)
|
||||
dangerous(err)
|
||||
|
||||
list, err := models.ClasspathGets(query, limit, offset(c, limit))
|
||||
dangerous(err)
|
||||
|
||||
renderData(c, gin.H{
|
||||
"list": list,
|
||||
"total": total,
|
||||
}, nil)
|
||||
}
|
||||
|
||||
func classpathFavoriteGet(c *gin.Context) {
|
||||
lst, err := loginUser(c).FavoriteClasspaths()
|
||||
renderData(c, lst, err)
|
||||
}
|
||||
|
||||
type classpathForm struct {
|
||||
Path string `json:"path"`
|
||||
Note string `json:"note"`
|
||||
}
|
||||
|
||||
func classpathAdd(c *gin.Context) {
|
||||
var f classpathForm
|
||||
bind(c, &f)
|
||||
|
||||
me := loginUser(c).MustPerm("classpath_create")
|
||||
|
||||
cp := models.Classpath{
|
||||
Path: f.Path,
|
||||
Note: f.Note,
|
||||
Preset: 0,
|
||||
CreateBy: me.Username,
|
||||
UpdateBy: me.Username,
|
||||
}
|
||||
|
||||
renderMessage(c, cp.Add())
|
||||
}
|
||||
|
||||
func classpathPut(c *gin.Context) {
|
||||
var f classpathForm
|
||||
bind(c, &f)
|
||||
|
||||
me := loginUser(c).MustPerm("classpath_modify")
|
||||
cp := Classpath(urlParamInt64(c, "id"))
|
||||
|
||||
if cp.Path != f.Path {
|
||||
num, err := models.ClasspathCount("path=? and id<>?", f.Path, cp.Id)
|
||||
dangerous(err)
|
||||
|
||||
if num > 0 {
|
||||
bomb(200, "Classpath %s already exists", f.Path)
|
||||
}
|
||||
}
|
||||
|
||||
cp.Path = f.Path
|
||||
cp.Note = f.Note
|
||||
cp.UpdateBy = me.Username
|
||||
cp.UpdateAt = time.Now().Unix()
|
||||
|
||||
renderMessage(c, cp.Update("path", "note", "update_by", "update_at"))
|
||||
}
|
||||
|
||||
func classpathDel(c *gin.Context) {
|
||||
loginUser(c).MustPerm("classpath_delete")
|
||||
|
||||
cp := Classpath(urlParamInt64(c, "id"))
|
||||
if cp.Preset == 1 {
|
||||
bomb(200, "Preset classpath %s cannot delete", cp.Path)
|
||||
}
|
||||
|
||||
renderMessage(c, cp.Del())
|
||||
}
|
||||
|
||||
func classpathAddResources(c *gin.Context) {
|
||||
var arr []string
|
||||
bind(c, &arr)
|
||||
|
||||
me := loginUser(c).MustPerm("classpath_add_resource")
|
||||
cp := Classpath(urlParamInt64(c, "id"))
|
||||
|
||||
dangerous(cp.AddResources(arr))
|
||||
|
||||
cp.UpdateAt = time.Now().Unix()
|
||||
cp.UpdateBy = me.Username
|
||||
cp.Update("update_at", "update_by")
|
||||
|
||||
renderMessage(c, nil)
|
||||
}
|
||||
|
||||
func classpathDelResources(c *gin.Context) {
|
||||
var arr []string
|
||||
bind(c, &arr)
|
||||
classpathId := urlParamInt64(c, "id")
|
||||
me := loginUser(c).MustPerm("classpath_del_resource")
|
||||
|
||||
if classpathId == 1 {
|
||||
bomb(200, "Resource cannot delete in preset classpath")
|
||||
}
|
||||
|
||||
cp := Classpath(classpathId)
|
||||
|
||||
dangerous(cp.DelResources(arr))
|
||||
|
||||
cp.UpdateAt = time.Now().Unix()
|
||||
cp.UpdateBy = me.Username
|
||||
cp.Update("update_at", "update_by")
|
||||
|
||||
renderMessage(c, nil)
|
||||
}
|
||||
|
||||
func classpathFavoriteAdd(c *gin.Context) {
|
||||
me := loginUser(c)
|
||||
cp := Classpath(urlParamInt64(c, "id"))
|
||||
renderMessage(c, models.ClasspathFavoriteAdd(cp.Id, me.Id))
|
||||
}
|
||||
|
||||
func classpathFavoriteDel(c *gin.Context) {
|
||||
me := loginUser(c)
|
||||
cp := Classpath(urlParamInt64(c, "id"))
|
||||
renderMessage(c, models.ClasspathFavoriteDel(cp.Id, me.Id))
|
||||
}
|
|
@ -1,176 +1,137 @@
|
|||
package http
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/didi/nightingale/v4/src/models"
|
||||
"github.com/didi/nightingale/v4/src/modules/server/cache"
|
||||
"github.com/didi/nightingale/v4/src/modules/server/collector"
|
||||
"github.com/didi/nightingale/v4/src/modules/server/config"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/toolkits/pkg/errors"
|
||||
"github.com/toolkits/pkg/logger"
|
||||
|
||||
"github.com/didi/nightingale/v5/cache"
|
||||
"github.com/didi/nightingale/v5/models"
|
||||
)
|
||||
|
||||
type CollectRecv struct {
|
||||
Type string `json:"type"`
|
||||
Data json.RawMessage `json:"data"`
|
||||
type collectRuleForm struct {
|
||||
ClasspathId int64 `json:"classpath_id"`
|
||||
PrefixMatch int `json:"prefix_match"`
|
||||
Name string `json:"name"`
|
||||
Note string `json:"note"`
|
||||
Step int `json:"step"`
|
||||
Type string `json:"type"`
|
||||
Data string `json:"data"`
|
||||
AppendTags string `json:"append_tags"`
|
||||
}
|
||||
|
||||
func collectRulePost(c *gin.Context) {
|
||||
var recv []CollectRecv
|
||||
errors.Dangerous(c.ShouldBind(&recv))
|
||||
func collectRuleAdd(c *gin.Context) {
|
||||
var f collectRuleForm
|
||||
bind(c, &f)
|
||||
|
||||
buf := &bytes.Buffer{}
|
||||
creator := loginUsername(c)
|
||||
for _, obj := range recv {
|
||||
cl, err := collector.GetCollector(obj.Type)
|
||||
errors.Dangerous(err)
|
||||
me := loginUser(c).MustPerm("collect_rule_create")
|
||||
|
||||
if err := cl.Create([]byte(obj.Data), creator); err != nil {
|
||||
if _, ok := err.(collector.DryRun); ok {
|
||||
fmt.Fprintf(buf, "%s\n", err)
|
||||
} else {
|
||||
errors.Bomb("%s add rule err %s", obj.Type, err)
|
||||
}
|
||||
}
|
||||
cr := models.CollectRule{
|
||||
ClasspathId: f.ClasspathId,
|
||||
PrefixMatch: f.PrefixMatch,
|
||||
Name: f.Name,
|
||||
Note: f.Note,
|
||||
Step: f.Step,
|
||||
Type: f.Type,
|
||||
Data: f.Data,
|
||||
AppendTags: f.AppendTags,
|
||||
CreateBy: me.Username,
|
||||
UpdateBy: me.Username,
|
||||
}
|
||||
|
||||
buf.WriteString("ok")
|
||||
renderData(c, buf.String(), nil)
|
||||
}
|
||||
|
||||
func collectRulesGetByLocalEndpoint(c *gin.Context) {
|
||||
collect := cache.CollectCache.GetBy(urlParamStr(c, "endpoint"))
|
||||
renderData(c, collect, nil)
|
||||
}
|
||||
|
||||
func collectRuleGet(c *gin.Context) {
|
||||
t := queryStr(c, "type")
|
||||
id := queryInt64(c, "id")
|
||||
|
||||
cl, err := collector.GetCollector(t)
|
||||
errors.Dangerous(err)
|
||||
|
||||
ret, err := cl.Get(id)
|
||||
renderData(c, ret, err)
|
||||
}
|
||||
|
||||
func collectRulesGet(c *gin.Context) {
|
||||
nid := queryInt64(c, "nid", -1)
|
||||
tp := queryStr(c, "type", "")
|
||||
var resp []interface{}
|
||||
var types []string
|
||||
|
||||
if tp == "" {
|
||||
types = []string{"port", "proc", "log", "plugin"}
|
||||
} else {
|
||||
types = []string{tp}
|
||||
}
|
||||
|
||||
nids := []int64{nid}
|
||||
for _, t := range types {
|
||||
cl, err := collector.GetCollector(t)
|
||||
if err != nil {
|
||||
logger.Warning(t, err)
|
||||
continue
|
||||
}
|
||||
|
||||
ret, err := cl.Gets(nids)
|
||||
if err != nil {
|
||||
logger.Warning(t, err)
|
||||
continue
|
||||
}
|
||||
resp = append(resp, ret...)
|
||||
}
|
||||
|
||||
renderData(c, resp, nil)
|
||||
}
|
||||
|
||||
func collectRulesGetV2(c *gin.Context) {
|
||||
nid := queryInt64(c, "nid", 0)
|
||||
limit := queryInt(c, "limit", 20)
|
||||
typ := queryStr(c, "type", "")
|
||||
|
||||
total, list, err := models.GetCollectRules(typ, nid, limit, offset(c, limit))
|
||||
|
||||
renderData(c, map[string]interface{}{
|
||||
"total": total,
|
||||
"list": list,
|
||||
}, err)
|
||||
renderMessage(c, cr.Add())
|
||||
}
|
||||
|
||||
func collectRulePut(c *gin.Context) {
|
||||
var recv CollectRecv
|
||||
errors.Dangerous(c.ShouldBind(&recv))
|
||||
var f collectRuleForm
|
||||
bind(c, &f)
|
||||
|
||||
cl, err := collector.GetCollector(recv.Type)
|
||||
errors.Dangerous(err)
|
||||
me := loginUser(c).MustPerm("collect_rule_modify")
|
||||
cr := CollectRule(urlParamInt64(c, "id"))
|
||||
|
||||
buf := &bytes.Buffer{}
|
||||
creator := loginUsername(c)
|
||||
if err := cl.Update([]byte(recv.Data), creator); err != nil {
|
||||
if _, ok := err.(collector.DryRun); ok {
|
||||
fmt.Fprintf(buf, "%s\n", err)
|
||||
} else {
|
||||
errors.Bomb("%s update rule err %s", recv.Type, err)
|
||||
}
|
||||
cr.PrefixMatch = f.PrefixMatch
|
||||
cr.Name = f.Name
|
||||
cr.Note = f.Note
|
||||
cr.Step = f.Step
|
||||
cr.Type = f.Type
|
||||
cr.Data = f.Data
|
||||
cr.AppendTags = f.AppendTags
|
||||
cr.UpdateAt = time.Now().Unix()
|
||||
cr.UpdateBy = me.Username
|
||||
|
||||
renderMessage(c, cr.Update(
|
||||
"prefix_match",
|
||||
"name",
|
||||
"note",
|
||||
"step",
|
||||
"type",
|
||||
"data",
|
||||
"update_at",
|
||||
"update_by",
|
||||
"append_tags",
|
||||
))
|
||||
}
|
||||
|
||||
func collectRuleDel(c *gin.Context) {
|
||||
var f idsForm
|
||||
bind(c, &f)
|
||||
f.Validate()
|
||||
loginUser(c).MustPerm("collect_rule_delete")
|
||||
renderMessage(c, models.CollectRulesDel(f.Ids))
|
||||
}
|
||||
|
||||
func collectRuleGets(c *gin.Context) {
|
||||
classpathId := urlParamInt64(c, "id")
|
||||
|
||||
where := "classpath_id = ?"
|
||||
param := []interface{}{classpathId}
|
||||
|
||||
typ := queryStr(c, "type", "")
|
||||
if typ != "" {
|
||||
where += " and type = ?"
|
||||
param = append(param, typ)
|
||||
}
|
||||
buf.WriteString("ok")
|
||||
renderData(c, buf.String(), nil)
|
||||
|
||||
objs, err := models.CollectRuleGets(where, param...)
|
||||
renderData(c, objs, err)
|
||||
}
|
||||
|
||||
type CollectsDelRev struct {
|
||||
Type string `json:"type"`
|
||||
Ids []int64 `json:"ids"`
|
||||
func collectRuleGetsByIdent(c *gin.Context) {
|
||||
ident := queryStr(c, "ident")
|
||||
|
||||
objs := cache.CollectRulesOfIdent.GetBy(ident)
|
||||
renderData(c, objs, nil)
|
||||
}
|
||||
|
||||
func collectsRuleDel(c *gin.Context) {
|
||||
var recv []CollectsDelRev
|
||||
errors.Dangerous(c.ShouldBind(&recv))
|
||||
type Summary struct {
|
||||
LatestUpdatedAt int64 `json:"latestUpdatedAt"`
|
||||
Total int `json:"total"`
|
||||
}
|
||||
|
||||
username := loginUsername(c)
|
||||
for _, obj := range recv {
|
||||
for i := 0; i < len(obj.Ids); i++ {
|
||||
cl, err := collector.GetCollector(obj.Type)
|
||||
errors.Dangerous(err)
|
||||
|
||||
if err := cl.Delete(obj.Ids[i], username); err != nil {
|
||||
errors.Dangerous(err)
|
||||
func collectRuleSummaryGetByIdent(c *gin.Context) {
|
||||
ident := queryStr(c, "ident")
|
||||
var summary Summary
|
||||
objs := cache.CollectRulesOfIdent.GetBy(ident)
|
||||
total := len(objs)
|
||||
if total > 0 {
|
||||
summary.Total = total
|
||||
var latestUpdatedAt int64
|
||||
for _, obj := range objs {
|
||||
if latestUpdatedAt < obj.UpdateAt {
|
||||
latestUpdatedAt = obj.UpdateAt
|
||||
}
|
||||
}
|
||||
summary.LatestUpdatedAt = latestUpdatedAt
|
||||
}
|
||||
|
||||
renderData(c, "ok", nil)
|
||||
renderData(c, summary, nil)
|
||||
}
|
||||
|
||||
func collectRuleTypesGet(c *gin.Context) {
|
||||
category := queryStr(c, "category")
|
||||
switch category {
|
||||
case "remote":
|
||||
renderData(c, collector.GetRemoteCollectors(), nil)
|
||||
case "local":
|
||||
renderData(c, collector.GetLocalCollectors(), nil)
|
||||
default:
|
||||
renderData(c, nil, nil)
|
||||
}
|
||||
}
|
||||
|
||||
func collectRuleTemplateGet(c *gin.Context) {
|
||||
t := urlParamStr(c, "type")
|
||||
collector, err := collector.GetCollector(t)
|
||||
errors.Dangerous(err)
|
||||
|
||||
tpl, err := collector.Template()
|
||||
renderData(c, tpl, err)
|
||||
}
|
||||
|
||||
type RegExpCheckDto struct {
|
||||
type RegExpCheck struct {
|
||||
Success bool `json:"success"`
|
||||
Data []map[string]string `json:"tags"`
|
||||
}
|
||||
|
@ -178,10 +139,10 @@ type RegExpCheckDto struct {
|
|||
var RegExpExcludePatition string = "```EXCLUDE```"
|
||||
|
||||
func regExpCheck(c *gin.Context) {
|
||||
param := make(map[string]string, 0)
|
||||
errors.Dangerous(c.ShouldBind(¶m))
|
||||
param := make(map[string]string)
|
||||
dangerous(c.ShouldBind(¶m))
|
||||
|
||||
ret := &RegExpCheckDto{
|
||||
ret := &RegExpCheck{
|
||||
Success: true,
|
||||
Data: make([]map[string]string, 0),
|
||||
}
|
||||
|
@ -207,7 +168,7 @@ func regExpCheck(c *gin.Context) {
|
|||
}
|
||||
|
||||
// 计算方式
|
||||
calc_method, _ := param["calc_method"]
|
||||
calc_method := param["calc_method"]
|
||||
|
||||
// 处理主正则(with exclude)
|
||||
if re, ok := param["re"]; !ok || re == "" {
|
||||
|
@ -375,39 +336,5 @@ func genSubErrMsg(sign string) string {
|
|||
|
||||
// 生成子串匹配错误信息
|
||||
func genIllegalCharErrMsg() string {
|
||||
return fmt.Sprintf(`正则匹配成功。但是tag的key或者value包含非法字符:[:,/=\r\n\t], 请重新调整`)
|
||||
}
|
||||
|
||||
func collectRulesGetByRemoteEndpoint(c *gin.Context) {
|
||||
rules := cache.CollectRuleCache.GetBy(urlParamStr(c, "endpoint"))
|
||||
renderData(c, rules, nil)
|
||||
|
||||
}
|
||||
|
||||
func apiCollectsGet(c *gin.Context) {
|
||||
node := queryStr(c, "node")
|
||||
region := queryStr(c, "region")
|
||||
key := region + "-" + node
|
||||
collects := cache.ApiCollectCache.GetBy(key)
|
||||
renderData(c, collects, nil)
|
||||
}
|
||||
|
||||
func snmpCollectsGet(c *gin.Context) {
|
||||
node := queryStr(c, "node")
|
||||
region := queryStr(c, "region")
|
||||
key := region + "-" + node
|
||||
collects := cache.SnmpCollectCache.GetBy(key)
|
||||
renderData(c, collects, nil)
|
||||
}
|
||||
|
||||
func snmpHWsGet(c *gin.Context) {
|
||||
node := queryStr(c, "node")
|
||||
region := queryStr(c, "region")
|
||||
key := region + "-" + node
|
||||
hws := cache.SnmpHWCache.GetBy(key)
|
||||
renderData(c, hws, nil)
|
||||
}
|
||||
|
||||
func apiRegionGet(c *gin.Context) {
|
||||
renderData(c, config.Config.Monapi.Region, nil)
|
||||
return `正则匹配成功。但是tag的key或者value包含非法字符:[:,/=\r\n\t], 请重新调整`
|
||||
}
|
|
@ -0,0 +1,154 @@
|
|||
package http
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"github.com/didi/nightingale/v5/models"
|
||||
)
|
||||
|
||||
func dashboardGets(c *gin.Context) {
|
||||
limit := queryInt(c, "limit", defaultLimit)
|
||||
query := queryStr(c, "query", "")
|
||||
onlyfavorite := queryBool(c, "onlyfavorite", false)
|
||||
|
||||
me := loginUser(c)
|
||||
ids, err := me.FavoriteDashboardIds()
|
||||
dangerous(err)
|
||||
|
||||
// 我的收藏是空的,所以直接返回空列表
|
||||
if onlyfavorite && len(ids) == 0 {
|
||||
renderZeroPage(c)
|
||||
return
|
||||
}
|
||||
|
||||
total, err := models.DashboardTotal(onlyfavorite, ids, query)
|
||||
dangerous(err)
|
||||
|
||||
list, err := models.DashboardGets(onlyfavorite, ids, query, limit, offset(c, limit))
|
||||
dangerous(err)
|
||||
|
||||
if onlyfavorite {
|
||||
for i := 0; i < len(list); i++ {
|
||||
list[i].Favorite = 1
|
||||
}
|
||||
} else {
|
||||
for i := 0; i < len(list); i++ {
|
||||
list[i].FillFavorite(ids)
|
||||
}
|
||||
}
|
||||
|
||||
renderData(c, gin.H{
|
||||
"list": list,
|
||||
"total": total,
|
||||
}, nil)
|
||||
}
|
||||
|
||||
func dashboardGet(c *gin.Context) {
|
||||
renderData(c, Dashboard(urlParamInt64(c, "id")), nil)
|
||||
}
|
||||
|
||||
type dashboardForm struct {
|
||||
Id int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Tags string `json:"tags"`
|
||||
Configs string `json:"configs"`
|
||||
}
|
||||
|
||||
func dashboardAdd(c *gin.Context) {
|
||||
var f dashboardForm
|
||||
bind(c, &f)
|
||||
|
||||
me := loginUser(c).MustPerm("dashboard_create")
|
||||
|
||||
d := &models.Dashboard{
|
||||
Name: f.Name,
|
||||
Tags: f.Tags,
|
||||
Configs: f.Configs,
|
||||
CreateBy: me.Username,
|
||||
UpdateBy: me.Username,
|
||||
}
|
||||
|
||||
dangerous(d.Add())
|
||||
|
||||
renderData(c, d, nil)
|
||||
}
|
||||
|
||||
func dashboardPut(c *gin.Context) {
|
||||
var f dashboardForm
|
||||
bind(c, &f)
|
||||
|
||||
me := loginUser(c).MustPerm("dashboard_modify")
|
||||
d := Dashboard(urlParamInt64(c, "id"))
|
||||
|
||||
if d.Name != f.Name {
|
||||
num, err := models.DashboardCount("name=? and id<>?", f.Name, d.Id)
|
||||
dangerous(err)
|
||||
|
||||
if num > 0 {
|
||||
bomb(200, "Dashboard %s already exists", f.Name)
|
||||
}
|
||||
}
|
||||
|
||||
d.Name = f.Name
|
||||
d.Tags = f.Tags
|
||||
d.Configs = f.Configs
|
||||
d.UpdateAt = time.Now().Unix()
|
||||
d.UpdateBy = me.Username
|
||||
|
||||
dangerous(d.Update("name", "tags", "configs", "update_at", "update_by"))
|
||||
|
||||
renderData(c, d, nil)
|
||||
}
|
||||
|
||||
func dashboardClone(c *gin.Context) {
|
||||
var f dashboardForm
|
||||
bind(c, &f)
|
||||
|
||||
me := loginUser(c).MustPerm("dashboard_create")
|
||||
|
||||
d := &models.Dashboard{
|
||||
Name: f.Name,
|
||||
Tags: f.Tags,
|
||||
Configs: f.Configs,
|
||||
CreateBy: me.Username,
|
||||
UpdateBy: me.Username,
|
||||
}
|
||||
dangerous(d.AddOnly())
|
||||
|
||||
chartGroups, err := models.ChartGroupGets(f.Id)
|
||||
dangerous(err)
|
||||
for _, chartGroup := range chartGroups {
|
||||
charts, err := models.ChartGets(chartGroup.Id)
|
||||
dangerous(err)
|
||||
chartGroup.DashboardId = d.Id
|
||||
chartGroup.Id = 0
|
||||
dangerous(chartGroup.Add())
|
||||
|
||||
for _, chart := range charts {
|
||||
chart.Id = 0
|
||||
chart.GroupId = chartGroup.Id
|
||||
dangerous(chart.Add())
|
||||
}
|
||||
}
|
||||
|
||||
renderData(c, d, nil)
|
||||
}
|
||||
|
||||
func dashboardDel(c *gin.Context) {
|
||||
loginUser(c).MustPerm("dashboard_delete")
|
||||
renderMessage(c, Dashboard(urlParamInt64(c, "id")).Del())
|
||||
}
|
||||
|
||||
func dashboardFavoriteAdd(c *gin.Context) {
|
||||
me := loginUser(c)
|
||||
d := Dashboard(urlParamInt64(c, "id"))
|
||||
renderMessage(c, models.DashboardFavoriteAdd(d.Id, me.Id))
|
||||
}
|
||||
|
||||
func dashboardFavoriteDel(c *gin.Context) {
|
||||
me := loginUser(c)
|
||||
d := Dashboard(urlParamInt64(c, "id"))
|
||||
renderMessage(c, models.DashboardFavoriteDel(d.Id, me.Id))
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
package http
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"github.com/didi/nightingale/v5/models"
|
||||
)
|
||||
|
||||
func metricDescriptionGets(c *gin.Context) {
|
||||
limit := queryInt(c, "limit", defaultLimit)
|
||||
query := queryStr(c, "query", "")
|
||||
|
||||
total, err := models.MetricDescriptionTotal(query)
|
||||
dangerous(err)
|
||||
|
||||
list, err := models.MetricDescriptionGets(query, limit, offset(c, limit))
|
||||
dangerous(err)
|
||||
|
||||
renderData(c, gin.H{
|
||||
"list": list,
|
||||
"total": total,
|
||||
}, nil)
|
||||
}
|
||||
|
||||
type metricDescriptionFrom struct {
|
||||
Data string `json:"data"`
|
||||
}
|
||||
|
||||
// 没有单个新增的功能,只有批量导入
|
||||
func metricDescriptionAdd(c *gin.Context) {
|
||||
var f metricDescriptionFrom
|
||||
var metricDescriptions []models.MetricDescription
|
||||
bind(c, &f)
|
||||
lines := strings.Split(f.Data, "\n")
|
||||
for _, md := range lines {
|
||||
arr := strings.Split(md, ":")
|
||||
if len(arr) != 2 {
|
||||
bomb(200, "metric description %s is illegal", md)
|
||||
}
|
||||
m := models.MetricDescription{
|
||||
Metric: arr[0],
|
||||
Description: arr[1],
|
||||
}
|
||||
metricDescriptions = append(metricDescriptions, m)
|
||||
}
|
||||
|
||||
if len(metricDescriptions) == 0 {
|
||||
bomb(http.StatusBadRequest, "Decoded metric description empty")
|
||||
}
|
||||
|
||||
loginUser(c).MustPerm("metric_description_create")
|
||||
|
||||
renderMessage(c, models.MetricDescriptionUpdate(metricDescriptions))
|
||||
}
|
||||
|
||||
func metricDescriptionDel(c *gin.Context) {
|
||||
var f idsForm
|
||||
bind(c, &f)
|
||||
|
||||
loginUser(c).MustPerm("metric_description_delete")
|
||||
|
||||
renderMessage(c, models.MetricDescriptionDel(f.Ids))
|
||||
}
|
||||
|
||||
type metricDescriptionForm struct {
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
func metricDescriptionPut(c *gin.Context) {
|
||||
var f metricDescriptionForm
|
||||
bind(c, &f)
|
||||
|
||||
loginUser(c).MustPerm("metric_description_modify")
|
||||
|
||||
md := MetricDescription(urlParamInt64(c, "id"))
|
||||
md.Description = f.Description
|
||||
|
||||
renderMessage(c, md.Update("description"))
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
package http
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"github.com/didi/nightingale/v5/models"
|
||||
)
|
||||
|
||||
func muteGets(c *gin.Context) {
|
||||
limit := queryInt(c, "limit", defaultLimit)
|
||||
query := queryStr(c, "query", "")
|
||||
|
||||
total, err := models.MuteTotal(query)
|
||||
dangerous(err)
|
||||
|
||||
list, err := models.MuteGets(query, limit, offset(c, limit))
|
||||
dangerous(err)
|
||||
|
||||
renderData(c, gin.H{
|
||||
"list": list,
|
||||
"total": total,
|
||||
}, nil)
|
||||
}
|
||||
|
||||
type muteForm struct {
|
||||
Metric string `json:"metric"`
|
||||
ResFilters string `json:"res_filters"`
|
||||
TagFilters string `json:"tags_filters"`
|
||||
Cause string `json:"cause"`
|
||||
Btime int64 `json:"btime"`
|
||||
Etime int64 `json:"etime"`
|
||||
}
|
||||
|
||||
func muteAdd(c *gin.Context) {
|
||||
var f muteForm
|
||||
bind(c, &f)
|
||||
|
||||
me := loginUser(c).MustPerm("mute_create")
|
||||
|
||||
mt := models.Mute{
|
||||
Metric: f.Metric,
|
||||
ResFilters: f.ResFilters,
|
||||
TagFilters: f.TagFilters,
|
||||
Cause: f.Cause,
|
||||
Btime: f.Btime,
|
||||
Etime: f.Etime,
|
||||
CreateBy: me.Username,
|
||||
}
|
||||
|
||||
renderMessage(c, mt.Add())
|
||||
}
|
||||
|
||||
func muteGet(c *gin.Context) {
|
||||
renderData(c, Mute(urlParamInt64(c, "id")), nil)
|
||||
}
|
||||
|
||||
func muteDel(c *gin.Context) {
|
||||
loginUser(c).MustPerm("mute_delete")
|
||||
renderMessage(c, Mute(urlParamInt64(c, "id")).Del())
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package http
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/prometheus/prometheus/promql/parser"
|
||||
|
||||
"github.com/didi/nightingale/v5/vos"
|
||||
)
|
||||
|
||||
func checkPromeQl(c *gin.Context) {
|
||||
|
||||
ql := c.Query("promql")
|
||||
_, err := parser.ParseExpr(ql)
|
||||
respD := &vos.PromQlCheckResp{}
|
||||
isCorrect := true
|
||||
if err != nil {
|
||||
|
||||
isCorrect = false
|
||||
respD.ParseError = err.Error()
|
||||
}
|
||||
|
||||
respD.QlCorrect = isCorrect
|
||||
renderData(c, respD, nil)
|
||||
}
|
|
@ -0,0 +1,190 @@
|
|||
package http
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/toolkits/pkg/str"
|
||||
|
||||
"github.com/didi/nightingale/v5/models"
|
||||
)
|
||||
|
||||
func classpathGetsResources(c *gin.Context) {
|
||||
limit := queryInt(c, "limit", defaultLimit)
|
||||
prefix := queryInt(c, "prefix", 0)
|
||||
query := queryStr(c, "query", "")
|
||||
|
||||
cp := Classpath(urlParamInt64(c, "id"))
|
||||
var classpathIds []int64
|
||||
if prefix == 1 {
|
||||
cps, err := models.ClasspathGetsByPrefix(cp.Path)
|
||||
dangerous(err)
|
||||
for i := range cps {
|
||||
classpathIds = append(classpathIds, cps[i].Id)
|
||||
}
|
||||
} else {
|
||||
classpathIds = append(classpathIds, cp.Id)
|
||||
}
|
||||
|
||||
total, err := models.ResourceTotalByClasspathId(classpathIds, query)
|
||||
dangerous(err)
|
||||
|
||||
reses, err := models.ResourceGetsByClasspathId(classpathIds, query, limit, offset(c, limit))
|
||||
dangerous(err)
|
||||
|
||||
renderData(c, gin.H{
|
||||
"classpath": cp,
|
||||
"list": reses,
|
||||
"total": total,
|
||||
}, nil)
|
||||
}
|
||||
|
||||
func resourcesQuery(c *gin.Context) {
|
||||
limit := queryInt(c, "limit", defaultLimit)
|
||||
qres := queryStr(c, "qres", "")
|
||||
|
||||
// qpaths 可以选择多个,英文逗号分隔的多个id
|
||||
qpaths := str.IdsInt64(queryStr(c, "qpaths", ""))
|
||||
|
||||
total, err := models.ResourceTotalByClasspathQuery(qpaths, qres)
|
||||
dangerous(err)
|
||||
|
||||
reses, err := models.ResourceGetsByClasspathQuery(qpaths, qres, limit, offset(c, limit))
|
||||
dangerous(err)
|
||||
|
||||
if len(reses) == 0 {
|
||||
renderZeroPage(c)
|
||||
return
|
||||
}
|
||||
|
||||
renderData(c, gin.H{
|
||||
"list": reses,
|
||||
"total": total,
|
||||
}, nil)
|
||||
}
|
||||
|
||||
func resourceGet(c *gin.Context) {
|
||||
renderData(c, Resource(urlParamInt64(c, "id")), nil)
|
||||
}
|
||||
|
||||
func resourceDel(c *gin.Context) {
|
||||
loginUser(c).MustPerm("resource_modify")
|
||||
renderData(c, Resource(urlParamInt64(c, "id")).Del(), nil)
|
||||
}
|
||||
|
||||
type resourceNoteForm struct {
|
||||
Ids []int64 `json:"ids"`
|
||||
Note string `json:"note"`
|
||||
}
|
||||
|
||||
// 修改主机设备的备注
|
||||
func resourceNotePut(c *gin.Context) {
|
||||
var f resourceNoteForm
|
||||
bind(c, &f)
|
||||
|
||||
if len(f.Ids) == 0 {
|
||||
bomb(http.StatusBadRequest, "ids is empty")
|
||||
}
|
||||
|
||||
loginUser(c).MustPerm("resource_modify")
|
||||
|
||||
renderMessage(c, models.ResourceUpdateNote(f.Ids, f.Note))
|
||||
}
|
||||
|
||||
type resourceTagsForm struct {
|
||||
Ids []int64 `json:"ids"`
|
||||
Tags string `json:"tags"`
|
||||
}
|
||||
|
||||
func resourceTagsPut(c *gin.Context) {
|
||||
var f resourceTagsForm
|
||||
bind(c, &f)
|
||||
|
||||
if len(f.Ids) == 0 {
|
||||
bomb(http.StatusBadRequest, "ids is empty")
|
||||
}
|
||||
|
||||
loginUser(c).MustPerm("resource_modify")
|
||||
|
||||
renderMessage(c, models.ResourceUpdateTags(f.Ids, f.Tags))
|
||||
}
|
||||
|
||||
type resourceMuteForm struct {
|
||||
Ids []int64 `json:"ids"`
|
||||
Btime int64 `json:"btime"`
|
||||
Etime int64 `json:"etime"`
|
||||
}
|
||||
|
||||
func resourceMutePut(c *gin.Context) {
|
||||
var f resourceMuteForm
|
||||
bind(c, &f)
|
||||
|
||||
if len(f.Ids) == 0 {
|
||||
bomb(http.StatusBadRequest, "ids is empty")
|
||||
}
|
||||
|
||||
loginUser(c).MustPerm("resource_modify")
|
||||
|
||||
renderMessage(c, models.ResourceUpdateMute(f.Ids, f.Btime, f.Etime))
|
||||
}
|
||||
|
||||
type resourceClasspathsForm struct {
|
||||
ResIdents []string `json:"res_idents"`
|
||||
ClasspathIds []int64 `json:"classpath_ids"`
|
||||
}
|
||||
|
||||
func resourceClasspathsPut(c *gin.Context) {
|
||||
var f resourceClasspathsForm
|
||||
m := make(map[string]map[int64]struct{}) //store database data to compare
|
||||
toAdd := make(map[string][]int64)
|
||||
|
||||
bind(c, &f)
|
||||
loginUser(c).MustPerm("resource_modify")
|
||||
|
||||
sql := "res_ident in (\"" + strings.Join(f.ResIdents, ",") + "\")"
|
||||
oldClasspathResources, err := models.ClasspathResourceGets(sql)
|
||||
dangerous(err)
|
||||
|
||||
for _, obj := range oldClasspathResources {
|
||||
if _, exists := m[obj.ResIdent]; !exists {
|
||||
m[obj.ResIdent] = make(map[int64]struct{})
|
||||
}
|
||||
m[obj.ResIdent][obj.ClasspathId] = struct{}{}
|
||||
}
|
||||
|
||||
for _, ident := range f.ResIdents {
|
||||
toAdd[ident] = []int64{}
|
||||
if _, exists := m[ident]; exists {
|
||||
for _, classpathId := range f.ClasspathIds {
|
||||
if _, exists := m[ident][classpathId]; exists {
|
||||
// classpathResource 在数据库中已存在,不做处理
|
||||
delete(m[ident], classpathId)
|
||||
} else {
|
||||
toAdd[ident] = append(toAdd[ident], classpathId)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
toAdd[ident] = f.ClasspathIds
|
||||
}
|
||||
}
|
||||
|
||||
//删除数据库中多余的classpathResources
|
||||
for ident := range m {
|
||||
for classpathId := range m[ident] {
|
||||
if classpathId == 1 {
|
||||
continue
|
||||
}
|
||||
|
||||
dangerous(models.ClasspathResourceDel(classpathId, []string{ident}))
|
||||
}
|
||||
}
|
||||
|
||||
//添加数据库没有的classpathResources
|
||||
for ident, cids := range toAdd {
|
||||
for _, cid := range cids {
|
||||
dangerous(models.ClasspathResourceAdd(cid, ident))
|
||||
}
|
||||
}
|
||||
renderMessage(c, nil)
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package http
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"github.com/didi/nightingale/v5/models"
|
||||
)
|
||||
|
||||
func rolesGet(c *gin.Context) {
|
||||
lst, err := models.RoleGetsAll()
|
||||
renderData(c, lst, err)
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
package http
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func selfProfileGet(c *gin.Context) {
|
||||
renderData(c, loginUser(c), nil)
|
||||
}
|
||||
|
||||
type selfProfileForm struct {
|
||||
Nickname string `json:"nickname"`
|
||||
Phone string `json:"phone"`
|
||||
Email string `json:"email"`
|
||||
Portrait string `json:"portrait"`
|
||||
Contacts json.RawMessage `json:"contacts"`
|
||||
}
|
||||
|
||||
func selfProfilePut(c *gin.Context) {
|
||||
var f selfProfileForm
|
||||
bind(c, &f)
|
||||
|
||||
user := loginUser(c)
|
||||
user.Nickname = f.Nickname
|
||||
user.Phone = f.Phone
|
||||
user.Email = f.Email
|
||||
user.Portrait = f.Portrait
|
||||
user.Contacts = f.Contacts
|
||||
user.UpdateAt = time.Now().Unix()
|
||||
user.UpdateBy = user.Username
|
||||
|
||||
renderMessage(
|
||||
c,
|
||||
user.Update(
|
||||
"nickname",
|
||||
"phone",
|
||||
"email",
|
||||
"portrait",
|
||||
"contacts",
|
||||
"update_at",
|
||||
"update_by",
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
type selfPasswordForm struct {
|
||||
OldPass string `json:"oldpass" binding:"required"`
|
||||
NewPass string `json:"newpass" binding:"required"`
|
||||
}
|
||||
|
||||
func selfPasswordPut(c *gin.Context) {
|
||||
var f selfPasswordForm
|
||||
bind(c, &f)
|
||||
renderMessage(c, loginUser(c).ChangePassword(f.OldPass, f.NewPass))
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package http
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"github.com/didi/nightingale/v5/models"
|
||||
)
|
||||
|
||||
func selfTokenGets(c *gin.Context) {
|
||||
objs, err := models.UserTokenGets("user_id=?", loginUser(c).Id)
|
||||
renderData(c, objs, err)
|
||||
}
|
||||
|
||||
func selfTokenPost(c *gin.Context) {
|
||||
user := loginUser(c)
|
||||
obj, err := models.UserTokenNew(user.Id, user.Username)
|
||||
renderData(c, obj, err)
|
||||
}
|
||||
|
||||
type selfTokenForm struct {
|
||||
Token string `json:"token"`
|
||||
}
|
||||
|
||||
func selfTokenPut(c *gin.Context) {
|
||||
user := loginUser(c)
|
||||
|
||||
var f selfTokenForm
|
||||
bind(c, &f)
|
||||
|
||||
obj, err := models.UserTokenReset(user.Id, f.Token)
|
||||
renderData(c, obj, err)
|
||||
}
|
|
@ -0,0 +1,176 @@
|
|||
package http
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/didi/nightingale/v5/backend"
|
||||
"github.com/didi/nightingale/v5/cache"
|
||||
"github.com/didi/nightingale/v5/trans"
|
||||
"github.com/didi/nightingale/v5/vos"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gin-gonic/gin/binding"
|
||||
agentpayload "github.com/n9e/agent-payload/gogen"
|
||||
"github.com/toolkits/pkg/logger"
|
||||
)
|
||||
|
||||
// 错误消息也是返回了200,是和客户端的约定,客户端如果发现code!=200就会重试
|
||||
func PushSeries(c *gin.Context) {
|
||||
req := agentpayload.N9EMetricsPayload{}
|
||||
|
||||
if c.ContentType() == "application/x-protobuf" {
|
||||
err := c.ShouldBindBodyWith(&req, binding.ProtoBuf)
|
||||
if err != nil {
|
||||
message := fmt.Sprintf("error: decode protobuf body occur error: %v", err)
|
||||
logger.Warning(message)
|
||||
c.String(200, message)
|
||||
return
|
||||
}
|
||||
|
||||
count := len(req.Samples)
|
||||
if count == 0 {
|
||||
c.String(200, "error: samples is empty")
|
||||
return
|
||||
}
|
||||
|
||||
metricPoints := make([]*vos.MetricPoint, 0, count)
|
||||
for i := 0; i < count; i++ {
|
||||
logger.Debugf("recv %v", req.Samples[i])
|
||||
metricPoints = append(metricPoints, convertAgentdPoint(req.Samples[i]))
|
||||
}
|
||||
|
||||
if err = trans.Push(metricPoints); err != nil {
|
||||
logger.Debugf("error: trans.push %+v err:%v", req.Samples, err)
|
||||
c.String(200, "error: "+err.Error())
|
||||
} else {
|
||||
c.String(200, "success: received %d points", len(metricPoints))
|
||||
}
|
||||
} else {
|
||||
logger.Debugf("error: trans.push %+v Content-Type(%s) not equals application/x-protobuf", req.Samples)
|
||||
c.String(200, "error: Content-Type(%s) not equals application/x-protobuf")
|
||||
}
|
||||
}
|
||||
|
||||
func convertAgentdPoint(obj *agentpayload.N9EMetricsPayload_Sample) *vos.MetricPoint {
|
||||
return &vos.MetricPoint{
|
||||
Metric: obj.Metric,
|
||||
Ident: obj.Ident,
|
||||
Alias: obj.Alias,
|
||||
TagsMap: obj.Tags,
|
||||
Time: obj.Time,
|
||||
ValueUntyped: obj.Value,
|
||||
}
|
||||
}
|
||||
|
||||
func PushData(c *gin.Context) {
|
||||
var points []*vos.MetricPoint
|
||||
err := c.ShouldBindJSON(&points)
|
||||
if err != nil {
|
||||
message := fmt.Sprintf("error: decode json body occur error: %v", err)
|
||||
logger.Warning(message)
|
||||
c.String(200, message)
|
||||
return
|
||||
}
|
||||
|
||||
if err = trans.Push(points); err != nil {
|
||||
c.String(200, "error: "+err.Error())
|
||||
} else {
|
||||
c.String(200, "success")
|
||||
}
|
||||
}
|
||||
|
||||
func GetTagKeys(c *gin.Context) {
|
||||
recv := vos.CommonTagQueryParam{}
|
||||
dangerous(c.ShouldBindJSON(&recv))
|
||||
|
||||
dataSource, err := backend.GetDataSourceFor("")
|
||||
if err != nil {
|
||||
logger.Warningf("could not find datasource")
|
||||
renderMessage(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
resp := dataSource.QueryTagKeys(recv)
|
||||
renderData(c, resp, nil)
|
||||
}
|
||||
|
||||
func GetTagValues(c *gin.Context) {
|
||||
recv := vos.CommonTagQueryParam{}
|
||||
dangerous(c.ShouldBindJSON(&recv))
|
||||
|
||||
dataSource, err := backend.GetDataSourceFor("")
|
||||
if err != nil {
|
||||
logger.Warningf("could not find datasource")
|
||||
renderMessage(c, err)
|
||||
return
|
||||
}
|
||||
if recv.TagKey == "" {
|
||||
renderMessage(c, errors.New("missing tagkey"))
|
||||
return
|
||||
}
|
||||
resp := dataSource.QueryTagValues(recv)
|
||||
renderData(c, resp, nil)
|
||||
}
|
||||
|
||||
func GetMetrics(c *gin.Context) {
|
||||
recv := vos.MetricQueryParam{}
|
||||
dangerous(c.ShouldBindJSON(&recv))
|
||||
|
||||
dataSource, err := backend.GetDataSourceFor("")
|
||||
if err != nil {
|
||||
logger.Warningf("could not find datasource")
|
||||
renderMessage(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
resp := dataSource.QueryMetrics(recv)
|
||||
logger.Debugf("[GetMetrics][recv:%+v][resp:%+v]", recv, resp)
|
||||
res := &vos.MetricDesQueryResp{
|
||||
Metrics: make([]vos.MetricsWithDescription, 0),
|
||||
}
|
||||
|
||||
for _, metric := range resp.Metrics {
|
||||
t := vos.MetricsWithDescription{
|
||||
Name: metric,
|
||||
}
|
||||
|
||||
description, exists := cache.MetricDescMapper.Get(metric)
|
||||
if exists {
|
||||
t.Description = description.(string)
|
||||
}
|
||||
|
||||
res.Metrics = append(res.Metrics, t)
|
||||
}
|
||||
|
||||
renderData(c, res, nil)
|
||||
}
|
||||
|
||||
func GetTagPairs(c *gin.Context) {
|
||||
recv := vos.CommonTagQueryParam{}
|
||||
dangerous(c.ShouldBindJSON(&recv))
|
||||
|
||||
dataSource, err := backend.GetDataSourceFor("")
|
||||
if err != nil {
|
||||
logger.Warningf("could not find datasource")
|
||||
renderMessage(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
resp := dataSource.QueryTagPairs(recv)
|
||||
renderData(c, resp, nil)
|
||||
}
|
||||
|
||||
func GetData(c *gin.Context) {
|
||||
dataSource, err := backend.GetDataSourceFor("")
|
||||
if err != nil {
|
||||
logger.Warningf("could not find datasource")
|
||||
renderMessage(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
var input vos.DataQueryParam
|
||||
dangerous(c.ShouldBindJSON(&input))
|
||||
resp := dataSource.QueryData(input)
|
||||
renderData(c, resp, nil)
|
||||
}
|
|
@ -0,0 +1,168 @@
|
|||
package http
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"github.com/didi/nightingale/v5/config"
|
||||
"github.com/didi/nightingale/v5/models"
|
||||
)
|
||||
|
||||
func userGets(c *gin.Context) {
|
||||
limit := queryInt(c, "limit", defaultLimit)
|
||||
query := queryStr(c, "query", "")
|
||||
|
||||
total, err := models.UserTotal(query)
|
||||
dangerous(err)
|
||||
|
||||
list, err := models.UserGets(query, limit, offset(c, limit))
|
||||
dangerous(err)
|
||||
|
||||
admin := loginUser(c).Role == "Admin"
|
||||
|
||||
renderData(c, gin.H{
|
||||
"list": list,
|
||||
"total": total,
|
||||
"admin": admin,
|
||||
}, nil)
|
||||
}
|
||||
|
||||
type userAddForm struct {
|
||||
Username string `json:"username" binding:"required"`
|
||||
Password string `json:"password" binding:"required"`
|
||||
Nickname string `json:"nickname"`
|
||||
Phone string `json:"phone"`
|
||||
Email string `json:"email"`
|
||||
Portrait string `json:"portrait"`
|
||||
Role string `json:"role"`
|
||||
Contacts json.RawMessage `json:"contacts"`
|
||||
}
|
||||
|
||||
func userAddPost(c *gin.Context) {
|
||||
var f userAddForm
|
||||
bind(c, &f)
|
||||
|
||||
password, err := models.CryptoPass(f.Password)
|
||||
dangerous(err)
|
||||
|
||||
now := time.Now().Unix()
|
||||
username := loginUsername(c)
|
||||
|
||||
u := models.User{
|
||||
Username: f.Username,
|
||||
Password: password,
|
||||
Nickname: f.Nickname,
|
||||
Phone: f.Phone,
|
||||
Email: f.Email,
|
||||
Portrait: f.Portrait,
|
||||
Role: f.Role,
|
||||
Contacts: f.Contacts,
|
||||
CreateAt: now,
|
||||
UpdateAt: now,
|
||||
CreateBy: username,
|
||||
UpdateBy: username,
|
||||
}
|
||||
|
||||
if u.Role == "" {
|
||||
u.Role = "Standard"
|
||||
}
|
||||
|
||||
renderMessage(c, u.Add())
|
||||
}
|
||||
|
||||
func userProfileGet(c *gin.Context) {
|
||||
renderData(c, User(urlParamInt64(c, "id")), nil)
|
||||
}
|
||||
|
||||
type userProfileForm struct {
|
||||
Nickname string `json:"nickname"`
|
||||
Phone string `json:"phone"`
|
||||
Email string `json:"email"`
|
||||
Portrait string `json:"portrait"`
|
||||
Role string `json:"role"`
|
||||
Status int `json:"status"`
|
||||
Contacts json.RawMessage `json:"contacts"`
|
||||
}
|
||||
|
||||
func userProfilePut(c *gin.Context) {
|
||||
var f userProfileForm
|
||||
bind(c, &f)
|
||||
|
||||
target := User(urlParamInt64(c, "id"))
|
||||
target.Nickname = f.Nickname
|
||||
target.Phone = f.Phone
|
||||
target.Email = f.Email
|
||||
target.Portrait = f.Portrait
|
||||
target.Role = f.Role
|
||||
target.Status = f.Status
|
||||
target.Contacts = f.Contacts
|
||||
target.UpdateAt = time.Now().Unix()
|
||||
target.UpdateBy = loginUsername(c)
|
||||
renderMessage(
|
||||
c,
|
||||
target.Update(
|
||||
"nickname",
|
||||
"phone",
|
||||
"email",
|
||||
"portrait",
|
||||
"role",
|
||||
"status",
|
||||
"contacts",
|
||||
"update_at",
|
||||
"update_by",
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
type userPasswordForm struct {
|
||||
Password string `json:"password" binding:"required"`
|
||||
}
|
||||
|
||||
func userPasswordPut(c *gin.Context) {
|
||||
var f userPasswordForm
|
||||
bind(c, &f)
|
||||
|
||||
target := User(urlParamInt64(c, "id"))
|
||||
|
||||
cryptoPass, err := models.CryptoPass(f.Password)
|
||||
dangerous(err)
|
||||
|
||||
target.Password = cryptoPass
|
||||
target.UpdateAt = time.Now().Unix()
|
||||
target.UpdateBy = loginUsername(c)
|
||||
renderMessage(c, target.Update("password", "update_at", "update_by"))
|
||||
}
|
||||
|
||||
type userStatusForm struct {
|
||||
Status int `json:"status"`
|
||||
}
|
||||
|
||||
func userStatusPut(c *gin.Context) {
|
||||
var f userStatusForm
|
||||
bind(c, &f)
|
||||
|
||||
target := User(urlParamInt64(c, "id"))
|
||||
target.Status = f.Status
|
||||
target.UpdateAt = time.Now().Unix()
|
||||
target.UpdateBy = loginUsername(c)
|
||||
renderMessage(c, target.Update("status", "update_at", "update_by"))
|
||||
}
|
||||
|
||||
func userDel(c *gin.Context) {
|
||||
id := urlParamInt64(c, "id")
|
||||
target, err := models.UserGet("id=?", id)
|
||||
dangerous(err)
|
||||
|
||||
if target == nil {
|
||||
renderMessage(c, nil)
|
||||
return
|
||||
}
|
||||
|
||||
renderMessage(c, target.Del())
|
||||
}
|
||||
|
||||
func contactChannelsGet(c *gin.Context) {
|
||||
renderData(c, config.Config.ContactKeys, nil)
|
||||
}
|
|
@ -0,0 +1,173 @@
|
|||
package http
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"github.com/didi/nightingale/v5/models"
|
||||
)
|
||||
|
||||
func userGroupListGet(c *gin.Context) {
|
||||
limit := queryInt(c, "limit", defaultLimit)
|
||||
query := queryStr(c, "query", "")
|
||||
|
||||
total, err := models.UserGroupTotal(query)
|
||||
dangerous(err)
|
||||
|
||||
list, err := models.UserGroupGets(query, limit, offset(c, limit))
|
||||
dangerous(err)
|
||||
|
||||
renderData(c, gin.H{
|
||||
"list": list,
|
||||
"total": total,
|
||||
}, nil)
|
||||
}
|
||||
|
||||
// 与我相关的用户组,我创建的,或者我是其中一员
|
||||
// 这个量不大,搜索和分页都放在前端来做,后端搞起来比较麻烦
|
||||
func userGroupMineGet(c *gin.Context) {
|
||||
list, err := loginUser(c).MyUserGroups()
|
||||
renderData(c, list, err)
|
||||
}
|
||||
|
||||
type userGroupForm struct {
|
||||
Name string `json:"name"`
|
||||
Note string `json:"note"`
|
||||
}
|
||||
|
||||
func userGroupAdd(c *gin.Context) {
|
||||
var f userGroupForm
|
||||
bind(c, &f)
|
||||
|
||||
me := loginUser(c)
|
||||
|
||||
ug := models.UserGroup{
|
||||
Name: f.Name,
|
||||
Note: f.Note,
|
||||
CreateBy: me.Username,
|
||||
UpdateBy: me.Username,
|
||||
}
|
||||
|
||||
dangerous(ug.Add())
|
||||
|
||||
// 顺便把创建者也作为团队的一员,失败了也没关系,用户会重新添加成员
|
||||
models.UserGroupMemberAdd(ug.Id, me.Id)
|
||||
|
||||
renderMessage(c, nil)
|
||||
}
|
||||
|
||||
func userGroupPut(c *gin.Context) {
|
||||
var f userGroupForm
|
||||
bind(c, &f)
|
||||
|
||||
me := loginUser(c)
|
||||
ug := UserGroup(urlParamInt64(c, "id"))
|
||||
|
||||
can, err := me.CanModifyUserGroup(ug)
|
||||
dangerous(err)
|
||||
|
||||
if !can {
|
||||
bomb(http.StatusForbidden, "forbidden")
|
||||
}
|
||||
|
||||
if ug.Name != f.Name {
|
||||
// 如果name发生变化,需要检查这个新name是否与别的group重名
|
||||
num, err := models.UserGroupCount("name=? and id<>?", f.Name, ug.Id)
|
||||
dangerous(err)
|
||||
|
||||
if num > 0 {
|
||||
bomb(200, "UserGroup %s already exists", f.Name)
|
||||
}
|
||||
}
|
||||
|
||||
ug.Name = f.Name
|
||||
ug.Note = f.Note
|
||||
ug.UpdateBy = me.Username
|
||||
ug.UpdateAt = time.Now().Unix()
|
||||
|
||||
renderMessage(c, ug.Update("name", "note", "update_at", "update_by"))
|
||||
}
|
||||
|
||||
// 不但返回UserGroup的信息,也把成员信息返回,成员不会特别多,所以,
|
||||
// 成员全部返回,由前端分页、查询
|
||||
func userGroupGet(c *gin.Context) {
|
||||
ug := UserGroup(urlParamInt64(c, "id"))
|
||||
|
||||
ids, err := ug.MemberIds()
|
||||
dangerous(err)
|
||||
|
||||
users, err := models.UserGetsByIds(ids)
|
||||
|
||||
renderData(c, gin.H{
|
||||
"users": users,
|
||||
"user_group": ug,
|
||||
}, err)
|
||||
}
|
||||
|
||||
func userGroupMemberAdd(c *gin.Context) {
|
||||
var f idsForm
|
||||
bind(c, &f)
|
||||
f.Validate()
|
||||
|
||||
me := loginUser(c)
|
||||
ug := UserGroup(urlParamInt64(c, "id"))
|
||||
|
||||
can, err := me.CanModifyUserGroup(ug)
|
||||
dangerous(err)
|
||||
|
||||
if !can {
|
||||
bomb(http.StatusForbidden, "forbidden")
|
||||
}
|
||||
|
||||
dangerous(ug.AddMembers(f.Ids))
|
||||
|
||||
// 用户组的成员发生变化,相当于更新了用户组
|
||||
// 如果更新失败了直接忽略,不是啥大事
|
||||
ug.UpdateAt = time.Now().Unix()
|
||||
ug.UpdateBy = me.Username
|
||||
ug.Update("update_at", "update_by")
|
||||
|
||||
renderMessage(c, nil)
|
||||
}
|
||||
|
||||
func userGroupMemberDel(c *gin.Context) {
|
||||
var f idsForm
|
||||
bind(c, &f)
|
||||
f.Validate()
|
||||
|
||||
me := loginUser(c)
|
||||
ug := UserGroup(urlParamInt64(c, "id"))
|
||||
|
||||
can, err := me.CanModifyUserGroup(ug)
|
||||
dangerous(err)
|
||||
|
||||
if !can {
|
||||
bomb(http.StatusForbidden, "forbidden")
|
||||
}
|
||||
|
||||
dangerous(ug.DelMembers(f.Ids))
|
||||
|
||||
// 用户组的成员发生变化,相当于更新了用户组
|
||||
// 如果更新失败了直接忽略,不是啥大事
|
||||
ug.UpdateAt = time.Now().Unix()
|
||||
ug.UpdateBy = me.Username
|
||||
ug.Update("update_at", "update_by")
|
||||
|
||||
renderMessage(c, nil)
|
||||
}
|
||||
|
||||
func userGroupDel(c *gin.Context) {
|
||||
me := loginUser(c)
|
||||
ug := UserGroup(urlParamInt64(c, "id"))
|
||||
|
||||
can, err := me.CanModifyUserGroup(ug)
|
||||
dangerous(err)
|
||||
|
||||
if !can {
|
||||
bomb(http.StatusForbidden, "forbidden")
|
||||
}
|
||||
|
||||
renderMessage(c, ug.Del())
|
||||
}
|
|
@ -18,11 +18,11 @@ import (
|
|||
"fmt"
|
||||
"math"
|
||||
|
||||
"github.com/didi/nightingale/v4/src/common/dataobj"
|
||||
"github.com/didi/nightingale/v5/vos"
|
||||
)
|
||||
|
||||
type Function interface {
|
||||
Compute(vs []*dataobj.HistoryData) (leftValue dataobj.JsonFloat, isTriggered bool)
|
||||
Compute(vs []*vos.HPoint) (leftValue vos.JsonFloat, isTriggered bool)
|
||||
}
|
||||
|
||||
type MaxFunction struct {
|
||||
|
@ -32,7 +32,7 @@ type MaxFunction struct {
|
|||
RightValue float64
|
||||
}
|
||||
|
||||
func (f MaxFunction) Compute(vs []*dataobj.HistoryData) (leftValue dataobj.JsonFloat, isTriggered bool) {
|
||||
func (f MaxFunction) Compute(vs []*vos.HPoint) (leftValue vos.JsonFloat, isTriggered bool) {
|
||||
count := len(vs)
|
||||
if count < 1 {
|
||||
return
|
||||
|
@ -57,7 +57,7 @@ type MinFunction struct {
|
|||
RightValue float64
|
||||
}
|
||||
|
||||
func (f MinFunction) Compute(vs []*dataobj.HistoryData) (leftValue dataobj.JsonFloat, isTriggered bool) {
|
||||
func (f MinFunction) Compute(vs []*vos.HPoint) (leftValue vos.JsonFloat, isTriggered bool) {
|
||||
count := len(vs)
|
||||
if count < 1 {
|
||||
return
|
||||
|
@ -83,7 +83,7 @@ type AllFunction struct {
|
|||
RightValue float64
|
||||
}
|
||||
|
||||
func (f AllFunction) Compute(vs []*dataobj.HistoryData) (leftValue dataobj.JsonFloat, isTriggered bool) {
|
||||
func (f AllFunction) Compute(vs []*vos.HPoint) (leftValue vos.JsonFloat, isTriggered bool) {
|
||||
count := len(vs)
|
||||
if count < 1 {
|
||||
return
|
||||
|
@ -107,13 +107,13 @@ type SumFunction struct {
|
|||
RightValue float64
|
||||
}
|
||||
|
||||
func (f SumFunction) Compute(vs []*dataobj.HistoryData) (leftValue dataobj.JsonFloat, isTriggered bool) {
|
||||
func (f SumFunction) Compute(vs []*vos.HPoint) (leftValue vos.JsonFloat, isTriggered bool) {
|
||||
count := len(vs)
|
||||
if count < 1 {
|
||||
return
|
||||
}
|
||||
|
||||
sum := dataobj.JsonFloat(0.0)
|
||||
sum := vos.JsonFloat(0.0)
|
||||
for i := 0; i < count; i++ {
|
||||
sum += vs[i].Value
|
||||
}
|
||||
|
@ -130,19 +130,19 @@ type AvgFunction struct {
|
|||
RightValue float64
|
||||
}
|
||||
|
||||
func (f AvgFunction) Compute(vs []*dataobj.HistoryData) (leftValue dataobj.JsonFloat, isTriggered bool) {
|
||||
func (f AvgFunction) Compute(vs []*vos.HPoint) (leftValue vos.JsonFloat, isTriggered bool) {
|
||||
vsLen := len(vs)
|
||||
if vsLen < 1 {
|
||||
return
|
||||
}
|
||||
|
||||
sum := dataobj.JsonFloat(0.0)
|
||||
sum := vos.JsonFloat(0.0)
|
||||
|
||||
for i := 0; i < vsLen; i++ {
|
||||
sum += vs[i].Value
|
||||
}
|
||||
|
||||
leftValue = sum / dataobj.JsonFloat(vsLen)
|
||||
leftValue = sum / vos.JsonFloat(vsLen)
|
||||
isTriggered = checkIsTriggered(leftValue, f.Operator, f.RightValue)
|
||||
return
|
||||
}
|
||||
|
@ -153,7 +153,7 @@ type StddevFunction struct {
|
|||
Limit int
|
||||
}
|
||||
|
||||
func (f StddevFunction) Compute(vs []*dataobj.HistoryData) (leftValue dataobj.JsonFloat, isTriggered bool) {
|
||||
func (f StddevFunction) Compute(vs []*vos.HPoint) (leftValue vos.JsonFloat, isTriggered bool) {
|
||||
var sum float64
|
||||
vsLen := len(vs)
|
||||
if vsLen < 1 {
|
||||
|
@ -188,7 +188,7 @@ type DiffFunction struct {
|
|||
}
|
||||
|
||||
// 只要有一个点的diff触发阈值,就报警
|
||||
func (f DiffFunction) Compute(vs []*dataobj.HistoryData) (leftValue dataobj.JsonFloat, isTriggered bool) {
|
||||
func (f DiffFunction) Compute(vs []*vos.HPoint) (leftValue vos.JsonFloat, isTriggered bool) {
|
||||
vsLen := len(vs)
|
||||
if vsLen < 1 {
|
||||
return
|
||||
|
@ -217,7 +217,7 @@ type PDiffFunction struct {
|
|||
RightValue float64
|
||||
}
|
||||
|
||||
func (f PDiffFunction) Compute(vs []*dataobj.HistoryData) (leftValue dataobj.JsonFloat, isTriggered bool) {
|
||||
func (f PDiffFunction) Compute(vs []*vos.HPoint) (leftValue vos.JsonFloat, isTriggered bool) {
|
||||
vsLen := len(vs)
|
||||
if vsLen < 1 {
|
||||
return
|
||||
|
@ -248,7 +248,7 @@ type HappenFunction struct {
|
|||
RightValue float64
|
||||
}
|
||||
|
||||
func (f HappenFunction) Compute(vs []*dataobj.HistoryData) (leftValue dataobj.JsonFloat, isTriggered bool) {
|
||||
func (f HappenFunction) Compute(vs []*vos.HPoint) (leftValue vos.JsonFloat, isTriggered bool) {
|
||||
for n, i := 0, 0; i < len(vs); i++ {
|
||||
if checkIsTriggered(vs[i].Value, f.Operator, f.RightValue) {
|
||||
n++
|
||||
|
@ -262,19 +262,6 @@ func (f HappenFunction) Compute(vs []*dataobj.HistoryData) (leftValue dataobj.Js
|
|||
return
|
||||
}
|
||||
|
||||
type NodataFunction struct {
|
||||
Function
|
||||
}
|
||||
|
||||
func (f NodataFunction) Compute(vs []*dataobj.HistoryData) (leftValue dataobj.JsonFloat, isTriggered bool) {
|
||||
for _, value := range vs {
|
||||
if !math.IsNaN(float64(value.Value)) {
|
||||
return value.Value, false
|
||||
}
|
||||
}
|
||||
return dataobj.JsonFloat(math.NaN()), true
|
||||
}
|
||||
|
||||
type CAvgAbsFunction struct {
|
||||
Function
|
||||
Limit int
|
||||
|
@ -283,20 +270,20 @@ type CAvgAbsFunction struct {
|
|||
CompareValue float64
|
||||
}
|
||||
|
||||
func (f CAvgAbsFunction) Compute(vs []*dataobj.HistoryData) (leftValue dataobj.JsonFloat, isTriggered bool) {
|
||||
func (f CAvgAbsFunction) Compute(vs []*vos.HPoint) (leftValue vos.JsonFloat, isTriggered bool) {
|
||||
vsLen := len(vs)
|
||||
if vsLen < 1 {
|
||||
return
|
||||
}
|
||||
|
||||
sum := dataobj.JsonFloat(0.0)
|
||||
sum := vos.JsonFloat(0.0)
|
||||
|
||||
for i := 0; i < vsLen; i++ {
|
||||
sum += vs[i].Value
|
||||
}
|
||||
|
||||
value := sum / dataobj.JsonFloat(vsLen)
|
||||
leftValue = dataobj.JsonFloat(math.Abs(float64(value) - float64(f.CompareValue)))
|
||||
value := sum / vos.JsonFloat(vsLen)
|
||||
leftValue = vos.JsonFloat(math.Abs(float64(value) - float64(f.CompareValue)))
|
||||
|
||||
isTriggered = checkIsTriggered(leftValue, f.Operator, f.RightValue)
|
||||
return
|
||||
|
@ -310,18 +297,18 @@ type CAvgFunction struct {
|
|||
CompareValue float64
|
||||
}
|
||||
|
||||
func (f CAvgFunction) Compute(vs []*dataobj.HistoryData) (leftValue dataobj.JsonFloat, isTriggered bool) {
|
||||
func (f CAvgFunction) Compute(vs []*vos.HPoint) (leftValue vos.JsonFloat, isTriggered bool) {
|
||||
vsLen := len(vs)
|
||||
if vsLen < 1 {
|
||||
return
|
||||
}
|
||||
|
||||
sum := dataobj.JsonFloat(0.0)
|
||||
sum := vos.JsonFloat(0.0)
|
||||
for i := 0; i < vsLen; i++ {
|
||||
sum += vs[i].Value
|
||||
}
|
||||
|
||||
leftValue = sum/dataobj.JsonFloat(vsLen) - dataobj.JsonFloat(f.CompareValue)
|
||||
leftValue = sum/vos.JsonFloat(vsLen) - vos.JsonFloat(f.CompareValue)
|
||||
|
||||
isTriggered = checkIsTriggered(leftValue, f.Operator, f.RightValue)
|
||||
return
|
||||
|
@ -335,19 +322,19 @@ type CAvgRateAbsFunction struct {
|
|||
CompareValue float64
|
||||
}
|
||||
|
||||
func (f CAvgRateAbsFunction) Compute(vs []*dataobj.HistoryData) (leftValue dataobj.JsonFloat, isTriggered bool) {
|
||||
func (f CAvgRateAbsFunction) Compute(vs []*vos.HPoint) (leftValue vos.JsonFloat, isTriggered bool) {
|
||||
vsLen := len(vs)
|
||||
if vsLen < 1 {
|
||||
return
|
||||
}
|
||||
|
||||
sum := dataobj.JsonFloat(0.0)
|
||||
sum := vos.JsonFloat(0.0)
|
||||
for i := 0; i < vsLen; i++ {
|
||||
sum += vs[i].Value
|
||||
}
|
||||
|
||||
value := sum / dataobj.JsonFloat(vsLen)
|
||||
leftValue = dataobj.JsonFloat(math.Abs((float64(value)-float64(f.CompareValue))/f.CompareValue)) * 100.00
|
||||
value := sum / vos.JsonFloat(vsLen)
|
||||
leftValue = vos.JsonFloat(math.Abs((float64(value)-float64(f.CompareValue))/f.CompareValue)) * 100.00
|
||||
|
||||
isTriggered = checkIsTriggered(leftValue, f.Operator, f.RightValue)
|
||||
return
|
||||
|
@ -361,19 +348,19 @@ type CAvgRateFunction struct {
|
|||
CompareValue float64
|
||||
}
|
||||
|
||||
func (f CAvgRateFunction) Compute(vs []*dataobj.HistoryData) (leftValue dataobj.JsonFloat, isTriggered bool) {
|
||||
func (f CAvgRateFunction) Compute(vs []*vos.HPoint) (leftValue vos.JsonFloat, isTriggered bool) {
|
||||
vsLen := len(vs)
|
||||
if vsLen < 1 {
|
||||
return
|
||||
}
|
||||
|
||||
sum := dataobj.JsonFloat(0.0)
|
||||
sum := vos.JsonFloat(0.0)
|
||||
for i := 0; i < vsLen; i++ {
|
||||
sum += vs[i].Value
|
||||
}
|
||||
|
||||
value := sum / dataobj.JsonFloat(vsLen)
|
||||
leftValue = (value - dataobj.JsonFloat(f.CompareValue)) / dataobj.JsonFloat(math.Abs(f.CompareValue)) * 100.00
|
||||
value := sum / vos.JsonFloat(vsLen)
|
||||
leftValue = (value - vos.JsonFloat(f.CompareValue)) / vos.JsonFloat(math.Abs(f.CompareValue)) * 100.00
|
||||
|
||||
isTriggered = checkIsTriggered(leftValue, f.Operator, f.RightValue)
|
||||
return
|
||||
|
@ -404,8 +391,6 @@ func ParseFuncFromString(str string, span []interface{}, operator string, rightV
|
|||
fn = &PDiffFunction{Limit: limit, Operator: operator, RightValue: rightValue}
|
||||
case "happen":
|
||||
fn = &HappenFunction{Limit: limit, Num: span[1].(int), Operator: operator, RightValue: rightValue}
|
||||
case "nodata":
|
||||
fn = &NodataFunction{}
|
||||
case "c_avg":
|
||||
fn = &CAvgFunction{Limit: limit, CompareValue: span[1].(float64), Operator: operator, RightValue: rightValue}
|
||||
case "c_avg_abs":
|
||||
|
@ -421,7 +406,7 @@ func ParseFuncFromString(str string, span []interface{}, operator string, rightV
|
|||
return
|
||||
}
|
||||
|
||||
func checkIsTriggered(leftValue dataobj.JsonFloat, operator string, rightValue float64) (isTriggered bool) {
|
||||
func checkIsTriggered(leftValue vos.JsonFloat, operator string, rightValue float64) (isTriggered bool) {
|
||||
switch operator {
|
||||
case "=", "==":
|
||||
isTriggered = math.Abs(float64(leftValue)-rightValue) < 0.0001
|
|
@ -0,0 +1,513 @@
|
|||
// Copyright 2017 Xiaomi, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package judge
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/toolkits/pkg/logger"
|
||||
"github.com/toolkits/pkg/str"
|
||||
|
||||
"github.com/didi/nightingale/v5/cache"
|
||||
"github.com/didi/nightingale/v5/models"
|
||||
"github.com/didi/nightingale/v5/vos"
|
||||
)
|
||||
|
||||
var (
|
||||
bufferPool = sync.Pool{New: func() interface{} { return new(bytes.Buffer) }}
|
||||
|
||||
EVENT_ALERT = "alert"
|
||||
EVENT_RECOVER = "recovery"
|
||||
)
|
||||
|
||||
func Send(points []*vos.MetricPoint) {
|
||||
for i := range points {
|
||||
alertRules := getMatchAlertRules(points[i])
|
||||
|
||||
rulesCount := len(alertRules)
|
||||
if rulesCount == 0 {
|
||||
// 这个监控数据没有关联任何告警策略,省事了不用处理
|
||||
continue
|
||||
}
|
||||
logger.Debugf("[point_match_alertRules][point:%+v][alertRuleNum:%+v]", points[i], rulesCount)
|
||||
// 不同的告警规则,alert_duration字段大小不同,找到最大的,按照最大的值来缓存历史数据
|
||||
var maxAliveDuration = 0
|
||||
for j := range alertRules {
|
||||
if maxAliveDuration < alertRules[j].AlertDuration {
|
||||
maxAliveDuration = alertRules[j].AlertDuration
|
||||
}
|
||||
}
|
||||
if len(points[i].PK) < 2 {
|
||||
logger.Debugf("[point:%+v] len(pk)<2", points[i])
|
||||
continue
|
||||
}
|
||||
|
||||
ll := PointCaches[points[i].PK[0:2]].PutPoint(points[i], int64(maxAliveDuration))
|
||||
|
||||
for j := range alertRules {
|
||||
go ToJudge(ll, alertRules[j], points[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getMatchAlertRules(point *vos.MetricPoint) []*models.AlertRule {
|
||||
alertRules := cache.AlertRulesByMetric.GetBy(point.Metric)
|
||||
matchRules := make([]*models.AlertRule, 0, len(alertRules))
|
||||
|
||||
for i := range alertRules {
|
||||
if alertRules[i].Type == models.PULL {
|
||||
continue
|
||||
}
|
||||
|
||||
if matchAlertRule(point, alertRules[i]) {
|
||||
matchRules = append(matchRules, alertRules[i])
|
||||
}
|
||||
}
|
||||
|
||||
return matchRules
|
||||
}
|
||||
|
||||
func matchAlertRule(item *vos.MetricPoint, alertRule *models.AlertRule) bool {
|
||||
//TODO 过滤方式待优化
|
||||
for _, filter := range alertRule.PushExpr.ResFilters {
|
||||
if !valueMatch(item.Ident, filter.Func, filter.Params) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
for _, filter := range alertRule.PushExpr.TagFilters {
|
||||
value, exists := item.TagsMap[filter.Key]
|
||||
if !exists {
|
||||
return false
|
||||
}
|
||||
|
||||
if !valueMatch(value, filter.Func, filter.Params) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func valueMatch(value, f string, params []string) bool {
|
||||
switch f {
|
||||
|
||||
case "InClasspath":
|
||||
for i := range params {
|
||||
if cache.ResClasspath.Exists(value, params[i]) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
case "NotInClasspath":
|
||||
for i := range params {
|
||||
if cache.ResClasspath.Exists(value, params[i]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
case "InClasspathPrefix":
|
||||
classpaths := cache.ResClasspath.GetValues(value)
|
||||
for _, classpath := range classpaths {
|
||||
for i := range params {
|
||||
if strings.HasPrefix(classpath, params[i]) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
case "NotInClasspathPrefix":
|
||||
classpaths := cache.ResClasspath.GetValues(value)
|
||||
for _, classpath := range classpaths {
|
||||
for i := range params {
|
||||
if strings.HasPrefix(classpath, params[i]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
case "InList":
|
||||
for i := range params {
|
||||
if value == params[i] {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
case "NotInList":
|
||||
for i := range params {
|
||||
if value == params[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
case "InResourceList":
|
||||
for i := range params {
|
||||
if value == params[i] {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
case "NotInResourceList":
|
||||
for i := range params {
|
||||
if value == params[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
case "HasPrefixString":
|
||||
for i := range params {
|
||||
if strings.HasPrefix(value, params[i]) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
case "NoPrefixString":
|
||||
for i := range params {
|
||||
if strings.HasPrefix(value, params[i]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
case "HasSuffixString":
|
||||
for i := range params {
|
||||
if strings.HasSuffix(value, params[i]) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
case "NoSuffixString":
|
||||
for i := range params {
|
||||
if strings.HasSuffix(value, params[i]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
case "ContainsString":
|
||||
for i := range params {
|
||||
if strings.Contains(value, params[i]) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
case "NotContainsString":
|
||||
for i := range params {
|
||||
if strings.Contains(value, params[i]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
case "MatchRegexp":
|
||||
for i := range params {
|
||||
r, _ := regexp.Compile(params[i])
|
||||
if r.MatchString(value) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
case "NotMatchRegexp":
|
||||
for i := range params {
|
||||
r, _ := regexp.Compile(params[i])
|
||||
if r.MatchString(value) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func ToJudge(linkedList *SafeLinkedList, stra *models.AlertRule, val *vos.MetricPoint) {
|
||||
logger.Debugf("[ToJudge.start][stra:%+v][val:%+v]", stra, val)
|
||||
now := val.Time
|
||||
|
||||
hps := linkedList.HistoryPoints(now - int64(stra.AlertDuration))
|
||||
if len(hps) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
historyArr := []vos.HistoryPoints{}
|
||||
statusArr := []bool{}
|
||||
eventInfo := ""
|
||||
value := ""
|
||||
|
||||
if len(stra.PushExpr.Exps) == 1 {
|
||||
for _, expr := range stra.PushExpr.Exps {
|
||||
history, info, lastValue, status := Judge(stra, expr, hps, val, now)
|
||||
statusArr = append(statusArr, status)
|
||||
|
||||
if value == "" {
|
||||
value = fmt.Sprintf("%s: %s", expr.Metric, lastValue)
|
||||
} else {
|
||||
value += fmt.Sprintf("; %s: %s", expr.Metric, lastValue)
|
||||
}
|
||||
|
||||
historyArr = append(historyArr, history)
|
||||
eventInfo += info
|
||||
}
|
||||
} else { //与条件
|
||||
for _, expr := range stra.PushExpr.Exps {
|
||||
|
||||
respData, err := GetData(stra, expr, val, now)
|
||||
if err != nil {
|
||||
logger.Errorf("stra:%+v get query data err:%v", stra, err)
|
||||
return
|
||||
}
|
||||
if len(respData) <= 0 {
|
||||
logger.Errorf("stra:%+v get query data respData:%v err", stra, respData)
|
||||
return
|
||||
}
|
||||
|
||||
history, info, lastValue, status := Judge(stra, expr, respData, val, now)
|
||||
|
||||
statusArr = append(statusArr, status)
|
||||
if value == "" {
|
||||
value = fmt.Sprintf("%s: %s", expr.Metric, lastValue)
|
||||
} else {
|
||||
value += fmt.Sprintf("; %s: %s", expr.Metric, lastValue)
|
||||
}
|
||||
|
||||
historyArr = append(historyArr, history)
|
||||
if eventInfo == "" {
|
||||
eventInfo = info
|
||||
} else {
|
||||
eventInfo += fmt.Sprintf(" & %s", info)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bs, err := json.Marshal(historyArr)
|
||||
if err != nil {
|
||||
logger.Errorf("Marshal history:%+v err:%v", historyArr, err)
|
||||
}
|
||||
|
||||
event := &models.AlertEvent{
|
||||
RuleId: stra.Id,
|
||||
RuleName: stra.Name,
|
||||
RuleNote: stra.Note,
|
||||
HashId: str.MD5(fmt.Sprintf("%d_%s", stra.Id, val.PK)),
|
||||
ResIdent: val.Ident,
|
||||
Priority: stra.Priority,
|
||||
HistoryPoints: bs,
|
||||
TriggerTime: now,
|
||||
Values: value,
|
||||
NotifyChannels: stra.NotifyChannels,
|
||||
NotifyGroups: stra.NotifyGroups,
|
||||
NotifyUsers: stra.NotifyUsers,
|
||||
RunbookUrl: stra.RunbookUrl,
|
||||
ReadableExpression: eventInfo,
|
||||
TagMap: val.TagsMap,
|
||||
}
|
||||
logger.Debugf("[ToJudge.event.create][type=push][stra:%+v][val:%+v][event:%+v]", stra, val, event)
|
||||
sendEventIfNeed(statusArr, event, stra)
|
||||
}
|
||||
|
||||
func Judge(stra *models.AlertRule, exp models.Exp, historyData []*vos.HPoint, firstItem *vos.MetricPoint, now int64) (history vos.HistoryPoints, info string, lastValue string, status bool) {
|
||||
|
||||
var leftValue vos.JsonFloat
|
||||
if exp.Func == "stddev" {
|
||||
info = fmt.Sprintf(" %s (%s,%ds) %v", exp.Metric, exp.Func, stra.AlertDuration, exp.Params)
|
||||
} else if exp.Func == "happen" {
|
||||
info = fmt.Sprintf(" %s (%s,%ds) %v %s %v", exp.Metric, exp.Func, stra.AlertDuration, exp.Params, exp.Optr, exp.Threshold)
|
||||
} else {
|
||||
info = fmt.Sprintf(" %s(%s,%ds) %s %v", exp.Metric, exp.Func, stra.AlertDuration, exp.Optr, exp.Threshold)
|
||||
}
|
||||
|
||||
leftValue, status = judgeItemWithStrategy(stra, historyData, exp, firstItem, now)
|
||||
|
||||
lastValue = "null"
|
||||
if !math.IsNaN(float64(leftValue)) {
|
||||
lastValue = strconv.FormatFloat(float64(leftValue), 'f', -1, 64)
|
||||
}
|
||||
|
||||
history = vos.HistoryPoints{
|
||||
Metric: exp.Metric,
|
||||
Tags: firstItem.TagsMap,
|
||||
Points: historyData,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func judgeItemWithStrategy(stra *models.AlertRule, historyData []*vos.HPoint, exp models.Exp, firstItem *vos.MetricPoint, now int64) (leftValue vos.JsonFloat, isTriggered bool) {
|
||||
straFunc := exp.Func
|
||||
|
||||
var straParam []interface{}
|
||||
|
||||
straParam = append(straParam, stra.AlertDuration)
|
||||
|
||||
switch straFunc {
|
||||
case "happen", "stddev":
|
||||
if len(exp.Params) < 1 {
|
||||
logger.Errorf("stra:%d exp:%+v stra param is null", stra.Id, exp)
|
||||
return
|
||||
}
|
||||
straParam = append(straParam, exp.Params[0])
|
||||
case "c_avg", "c_avg_abs", "c_avg_rate", "c_avg_rate_abs":
|
||||
if len(exp.Params) < 1 {
|
||||
logger.Errorf("stra:%d exp:%+v stra param is null", stra.Id, exp)
|
||||
return
|
||||
}
|
||||
|
||||
hisD, err := GetData(stra, exp, firstItem, now-int64(exp.Params[0]))
|
||||
if err != nil {
|
||||
logger.Errorf("stra:%v %+v get compare data err:%v", stra.Id, exp, err)
|
||||
return
|
||||
}
|
||||
|
||||
if len(hisD) != 1 {
|
||||
logger.Errorf("stra:%d %+v get compare data err, respItems:%v", stra.Id, exp, hisD)
|
||||
return
|
||||
}
|
||||
|
||||
var sum float64
|
||||
for _, i := range hisD {
|
||||
sum += float64(i.Value)
|
||||
}
|
||||
|
||||
//环比数据的平均值
|
||||
straParam = append(straParam, sum/float64(len(hisD)))
|
||||
}
|
||||
|
||||
fn, err := ParseFuncFromString(straFunc, straParam, exp.Optr, exp.Threshold)
|
||||
if err != nil {
|
||||
logger.Errorf("stra:%d %+v parse func fail: %v", stra.Id, exp, err)
|
||||
return
|
||||
}
|
||||
|
||||
return fn.Compute(historyData)
|
||||
}
|
||||
|
||||
func GetData(stra *models.AlertRule, exp models.Exp, firstItem *vos.MetricPoint, now int64) ([]*vos.HPoint, error) {
|
||||
var respData []*vos.HPoint
|
||||
var err error
|
||||
|
||||
//多查一些数据,防止由于查询不到最新点,导致点数不够
|
||||
start := now - int64(stra.AlertDuration) - 2
|
||||
// 这里的参数肯定只有一个
|
||||
queryParam, err := NewQueryRequest(firstItem.Ident, exp.Metric, firstItem.TagsMap, start, now)
|
||||
|
||||
if err != nil {
|
||||
return respData, err
|
||||
}
|
||||
respData = Query(queryParam)
|
||||
logger.Debugf("[exp:%+v][queryParam:%+v][respData:%+v]\n", exp, queryParam, respData)
|
||||
return respData, err
|
||||
}
|
||||
|
||||
// 虽然最近的数据确实产生了事件(产生事件很频繁),但是未必一定要发送,只有告警/恢复状态发生变化的时候才需发送
|
||||
func sendEventIfNeed(status []bool, event *models.AlertEvent, stra *models.AlertRule) {
|
||||
isTriggered := true
|
||||
for _, s := range status {
|
||||
isTriggered = isTriggered && s
|
||||
}
|
||||
|
||||
now := time.Now().Unix()
|
||||
lastEvent, exists := LastEvents.Get(event.HashId)
|
||||
|
||||
switch event.IsPromePull {
|
||||
case 0:
|
||||
// push型的 && 与条件型的
|
||||
if exists && lastEvent.IsPromePull == 1 {
|
||||
// 之前内存中的事件是pull型的,先清空内存中的事件
|
||||
LastEvents.Del(event.HashId)
|
||||
}
|
||||
|
||||
if isTriggered {
|
||||
// 新告警或者上次是恢复事件,都需要立即发送
|
||||
if !exists || lastEvent.IsRecov() {
|
||||
event.MarkAlert()
|
||||
SendEvent(event)
|
||||
}
|
||||
} else {
|
||||
// 上次是告警事件,现在恢复了,自然需要通知
|
||||
if exists && lastEvent.IsAlert() {
|
||||
event.MarkRecov()
|
||||
SendEvent(event)
|
||||
}
|
||||
}
|
||||
case 1:
|
||||
// pull型的,产生的事件一定是触发了阈值的,即这个case里不存在recovery的场景,recovery的场景用resolve_timeout的cron来处理
|
||||
if exists && lastEvent.IsPromePull == 0 {
|
||||
// 之前内存中的事件是push型的,先清空内存中的事件
|
||||
LastEvents.Del(event.HashId)
|
||||
}
|
||||
|
||||
// 1. 第一次来,并且AlertDuration=0,直接发送
|
||||
// 2. 触发累计到AlertDuration时长后触发一条
|
||||
if !exists {
|
||||
// 这是个新事件,之前未曾产生过的
|
||||
if stra.AlertDuration == 0 {
|
||||
// 代表prometheus rule for 配置为0,直接发送
|
||||
event.LastSend = true
|
||||
event.MarkAlert()
|
||||
SendEvent(event)
|
||||
} else {
|
||||
// 只有一条事件,显然无法满足for AlertDuration的时间,放到内存里等待
|
||||
LastEvents.Set(event.HashId, event)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 内存里有事件,虽然AlertDuration是0但是上次没有发过(可能是中间调整过AlertDuration,比如从某个大于0的值调整为0)
|
||||
if stra.AlertDuration == 0 && !lastEvent.LastSend {
|
||||
event.LastSend = true
|
||||
event.MarkAlert()
|
||||
SendEvent(event)
|
||||
return
|
||||
}
|
||||
|
||||
// 内存里有事件,AlertDuration也是大于0的,需要判断Prometheus里的for的逻辑
|
||||
if now-lastEvent.TriggerTime < int64(stra.AlertDuration) {
|
||||
// 距离上次告警的时间小于告警统计周期,即不满足for的条件,不产生告警通知
|
||||
return
|
||||
}
|
||||
|
||||
logger.Debugf("[lastEvent.LastSend:%+v][event.LastSend:%+v][now:%+v][lastEvent.TriggerTime:%+v][stra.AlertDuration:%+v][now-lastEvent.TriggerTime:%+v]\n",
|
||||
lastEvent.LastSend,
|
||||
event.LastSend,
|
||||
now,
|
||||
lastEvent.TriggerTime,
|
||||
stra.AlertDuration,
|
||||
now-lastEvent.TriggerTime,
|
||||
)
|
||||
|
||||
// 满足for的条件了,应产生事件,但是未必一定要发送,上次没发送或者上次是恢复这次才发送,即保证只发一条
|
||||
if !lastEvent.LastSend || lastEvent.IsRecov() {
|
||||
event.LastSend = true
|
||||
event.MarkAlert()
|
||||
SendEvent(event)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func SendEvent(event *models.AlertEvent) {
|
||||
// update last event
|
||||
LastEvents.Set(event.HashId, event)
|
||||
ok := EventQueue.PushFront(event)
|
||||
if !ok {
|
||||
logger.Errorf("push event:%v err", event)
|
||||
}
|
||||
logger.Debugf("[SendEvent.event.success][type:%+v][event:%+v]", event.IsPromePull, event)
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue