forked from pneymrl2f/nightingale
parent
7a2b07eebd
commit
6e3ad3dd6b
@ -0,0 +1,38 @@
|
||||
.PHONY: start build
|
||||
|
||||
NOW = $(shell date -u '+%Y%m%d%I%M%S')
|
||||
|
||||
RELEASE_VERSION = 5.1.0
|
||||
|
||||
APP = n9e
|
||||
SERVER_BIN = ${APP}
|
||||
# RELEASE_ROOT = release
|
||||
# RELEASE_SERVER = release/${APP}
|
||||
# GIT_COUNT = $(shell git rev-list --all --count)
|
||||
# GIT_HASH = $(shell git rev-parse --short HEAD)
|
||||
# RELEASE_TAG = $(RELEASE_VERSION).$(GIT_COUNT).$(GIT_HASH)
|
||||
|
||||
all: build
|
||||
|
||||
build:
|
||||
@go build -ldflags "-w -s -X main.VERSION=$(RELEASE_VERSION)" -o $(SERVER_BIN) ./src
|
||||
|
||||
# start:
|
||||
# @go run -ldflags "-X main.VERSION=$(RELEASE_TAG)" ./cmd/${APP}/main.go web -c ./configs/config.toml -m ./configs/model.conf --menu ./configs/menu.yaml
|
||||
|
||||
# swagger:
|
||||
# @swag init --parseDependency --generalInfo ./cmd/${APP}/main.go --output ./internal/app/swagger
|
||||
|
||||
# wire:
|
||||
# @wire gen ./internal/app
|
||||
|
||||
# test:
|
||||
# cd ./internal/app/test && go test -v
|
||||
|
||||
# clean:
|
||||
# rm -rf data release $(SERVER_BIN) internal/app/test/data cmd/${APP}/data
|
||||
|
||||
# pack: build
|
||||
# rm -rf $(RELEASE_ROOT) && mkdir -p $(RELEASE_SERVER)
|
||||
# cp -r $(SERVER_BIN) configs $(RELEASE_SERVER)
|
||||
# cd $(RELEASE_ROOT) && tar -cvf $(APP).tar ${APP} && rm -rf ${APP}
|
@ -1,9 +0,0 @@
|
||||
package alert
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
func Start(ctx context.Context) {
|
||||
go popEvent()
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,89 +0,0 @@
|
||||
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 // 查询一段时间
|
||||
QueryDataInstant(ql string) []*vos.DataQueryInstanceResp // 查询一个时间点数据 等同于prometheus instant_query
|
||||
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
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,9 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# release version
|
||||
version=5.0.0-rc7-1
|
||||
|
||||
#export GO111MODULE=on
|
||||
#export GOPROXY=https://goproxy.cn
|
||||
go build -ldflags "-X github.com/didi/nightingale/v5/config.Version=${version}" -o n9e-server main.go
|
||||
|
@ -1,33 +0,0 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type AlertMuteMap struct {
|
||||
sync.RWMutex
|
||||
Data map[string][]Filter
|
||||
}
|
||||
type Filter struct {
|
||||
ClasspathPrefix string
|
||||
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
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
cmap "github.com/orcaman/concurrent-map"
|
||||
)
|
||||
|
||||
var MetricDescMapper = cmap.New()
|
@ -1,27 +0,0 @@
|
||||
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
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
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
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
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
|
||||
}
|
@ -1,76 +0,0 @@
|
||||
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
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
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) GetById(id int64) *models.User {
|
||||
s.RLock()
|
||||
defer s.RUnlock()
|
||||
|
||||
return s.Data[id]
|
||||
}
|
||||
|
||||
func (s *UserMap) SetAll(users map[int64]*models.User) {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
s.Data = users
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/didi/nightingale/v5/models"
|
||||
)
|
||||
|
||||
type UserGroupMap struct {
|
||||
sync.RWMutex
|
||||
Data map[int64]*models.UserGroup
|
||||
}
|
||||
|
||||
var UserGroupCache = &UserGroupMap{Data: make(map[int64]*models.UserGroup)}
|
||||
|
||||
func (s *UserGroupMap) GetBy(id int64) *models.UserGroup {
|
||||
s.RLock()
|
||||
defer s.RUnlock()
|
||||
|
||||
return s.Data[id]
|
||||
}
|
||||
|
||||
func (s *UserGroupMap) GetByIds(ids []int64) []*models.UserGroup {
|
||||
s.RLock()
|
||||
defer s.RUnlock()
|
||||
var userGroups []*models.UserGroup
|
||||
for _, id := range ids {
|
||||
if s.Data[id] == nil {
|
||||
continue
|
||||
}
|
||||
userGroups = append(userGroups, s.Data[id])
|
||||
}
|
||||
|
||||
return userGroups
|
||||
}
|
||||
|
||||
func (s *UserGroupMap) SetAll(userGroups map[int64]*models.UserGroup) {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
s.Data = userGroups
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
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
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
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": "告警事件不存在",
|
||||
"Alert rule %s already exists": "告警规则(%s)已存在",
|
||||
"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)格式不合法",
|
||||
"Regexp %s matching failed": "正则表达式 %s 匹配失败",
|
||||
"Regexp %s matched, but cannot get substring()": "主正则 %s 匹配成功,但无法匹配到子串",
|
||||
"TagKey or TagValue contains illegal characters[:,/=\r\n\t]": "标签KEY或者标签值包含非法字符串[:,/=\r\n\t]",
|
||||
"Resource cannot delete in preset classpath": "预置分组不能删除资源",
|
||||
"No such resource %s": "不存在该资源(%s)",
|
||||
}
|
||||
langDict = map[string]map[string]string{
|
||||
"zh": dict,
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
i18n.DictRegister(langDict)
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue