prometheusを変更してデータベースストレージアラーム規則と収集目標を実現
データベースからのアラート・ルールとサービス・ターゲット・グループの取得
prometheus自身の警報規則とサービス発見戦略はファイル配置に基づいて不便であり、非K 8 Sサービス監視に対しては常に配置ファイルを操作する必要があり、管理システムのプラットフォーム化建設に不利である.実現構想:関連配置情報をMySQLに記憶し、新しいロジックを加え、ファイルのロード配置を保留すると同時に、MySQL中の情報をロードし、
MySQL構成
次の環境変数を使用してMySQLメタ情報を定義します.
gorm実装を用いるため,コードに依存を導入する必要がある.
テーブル構造の定義
アラーム規則テーブル構造定義
コードロジック
github.com/prometheus/prometheus/rules/manager.go LoadGroupメソッドが戻る前に次のコードを追加します.
jobおよびtargerコード
データベースから情報を取得してstatic config構成を生成する
構造定義
コードロジック
main.go reloadConfig中
prometheus自身の警報規則とサービス発見戦略はファイル配置に基づいて不便であり、非K 8 Sサービス監視に対しては常に配置ファイルを操作する必要があり、管理システムのプラットフォーム化建設に不利である.実現構想:関連配置情報をMySQLに記憶し、新しいロジックを加え、ファイルのロード配置を保留すると同時に、MySQL中の情報をロードし、
static_config
及びalert_rule
を動的に生成し、アラーム及び監視目標の配置UI化を実現する.MySQL構成
次の環境変数を使用してMySQLメタ情報を定義します.
MYSQL_HOST # /ip
MYSQL_PORT #
MYSQL_USER #
MYSQL_PWD #
MYSQL_DB #
gorm実装を用いるため,コードに依存を導入する必要がある.
"github.com/jinzhu/gorm"
_ "github.com/go-sql-driver/mysql"
テーブル構造の定義
アラーム規則テーブル構造定義
type AlertRule struct {
ID uint `gorm:"primary_key"`
CreatedAt time.Time
UpdatedAt time.Time
Group string `json:"group,omitempty"` //
Alert string `json:"alert,omitempty"` //
Expr string `json:"expr,omitempty"` //
For string `json:"for,omitempty"` //
Labels JSON `sql:"type:json" json:"labels,omitempty"`// label
Annotations JSON `sql:"type:json" json:"annotations,omitempty"` //
}
func (self *AlertRule) TableName() string {
return "alert_rule"
}
type JSON []map[string]string
func (c JSON) Value() (driver.Value, error) {
b, err := json.Marshal(c)
return string(b), err
}
func (c *JSON) Scan(input interface{}) error {
return json.Unmarshal(input.([]byte), c)
}
コードロジック
github.com/prometheus/prometheus/rules/manager.go LoadGroupメソッドが戻る前に次のコードを追加します.
//
var rules []AlertRule
db_url:=fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=true&loc=Local",os.Getenv("MYSQL_USER"),os.Getenv("MYSQL_PWD"),os.Getenv("MYSQL_HOST"),os.Getenv("MYSQL_PORT"),os.Getenv("MYSQL_DB"))
db,err:=gorm.Open("mysql", fmt)
if err!=nil {
level.Error(m.logger).Log( "init db error: ",err)
}else {
level.Info(m.logger).Log("get db connection success")
}
//
err=db.Model(&AlertRule{}).Scan(&rules).Error
if err!=nil {
level.Error(m.logger).Log(err)
}else {
level.Info(m.logger).Log("get rules success")
}
defer func(db *gorm.DB) {
err:=db.Close()
if err!=nil {
level.Error(m.logger).Log("close db error: ",err)
}
}(db)
arules := make(map[string][]Rule)
for _,v:=range rules {
expr, err := promql.ParseExpr(v.Expr)
if err != nil {
return nil, []error{err}
}
var lbs=labels.Labels{labels.Label{
Name: "product",
Value: v.Group,
}}
for _,v:=range v.Labels {
lbs=append(lbs,labels.Label{
v["key"],v["value"],
})
}
var ans=labels.Labels{}
for _,v:=range v.Annotations {
ans=append(ans,labels.Label{
v["key"],v["value"],
})
}
arules[v.Group]= append(arules[v.Group], NewAlertingRule(v.Alert,expr,interval,lbs,ans,nil,shouldRestore,log.With(m.logger, "alert", v.Alert)))
}
level.Info(m.logger).Log(arules)
for k,v:=range arules {
rules:=make([]Rule,0,len(v))
rules=v[0:len(v)]
groups[groupKey(k,"rule.yaml")]=NewGroup(k,"rule.yaml",interval, rules,shouldRestore,m.opts)
}
jobおよびtargerコード
データベースから情報を取得してstatic config構成を生成する
構造定義
type AlertSdRule struct {
ID uint `gorm:"primary_key"`
CreatedAt time.Time `json:"create_at"`
UpdatedAt time.Time `json:"update_at"`
Target string `gorm:"type:varchar(200);not null" json:"target"`
Labels JSON `sql:"type:json" json:"type"`
GroupId int `gorm:"type:integer;not null" json:"group_id"`
Describe string `gorm:"type:varchar(200);not null" json:"describe"`
}
func (self *AlertSdRule) TableName() string {
return "alert_sd_rule"
}
type AlertSdGroup struct {
ID uint `gorm:"primary_key"`
CreatedAt time.Time `json:"create_at"`
UpdatedAt time.Time `json:"update_at"`
Name string `gorm:"type:varchar(200);not null" json:"name"`
MetricsPath string `gorm:"type:varchar(200);not null" json:"metrics_path"`
Labels JSON `sql:"type:json" json:"labels"`
Scheme string `gorm:"type:varchar(200);not null" json:"scheme"`
Interval int `gorm:"type:integer;not null" json:"interval"`
Timeout int `gorm:"type:integer;not null" json:"timeout"`
Describe string `gorm:"type:varchar(200);not null" json:"describe"`
AuthUser string `gorm:"type:varchar(200)" json:"auth_user"`
AuthPassword string `gorm:"type:varchar(200)" json:"auth_password"`
AuthToken string `gorm:"type:varchar(200)" json:"auth_token"`
}
func (self *AlertSdGroup) TableName() string {
return "alert_sd_group"
}
type JSON []map[string]string
func (c JSON) Value() (driver.Value, error) {
b, err := json.Marshal(c)
return string(b), err
}
func (c *JSON) Scan(input interface{}) error {
return json.Unmarshal(input.([]byte), c)
}
コードロジック
main.go reloadConfig中
//
db_url:=fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=true&loc=Local",os.Getenv("MYSQL_USER"),os.Getenv("MYSQL_PWD"),os.Getenv("MYSQL_HOST"),os.Getenv("MYSQL_PORT"),os.Getenv("MYSQL_DB"))
conn, err := gorm.Open("mysql", db_url)
if err != nil {
panic(err)
}
var groups []AlertSdGroup
// JOB
err = conn.Model(&AlertSdGroup{}).Scan(&groups).Error
if err != nil {
panic(err)
}
for _, group := range groups {
var rules []AlertSdRule
// job targets
err = conn.Model(&AlertSdRule{}).Where("group_id = ?", group.ID).Scan(&rules).Error
if err != nil {
panic(err)
}
var targetgroups = []*targetgroup.Group{}
for _, rule := range rules {
var labels model.LabelSet = map[model.LabelName]model.LabelValue{}
for _, label := range group.Labels {
key := model.LabelName(label["key"])
value := model.LabelValue(label["value"])
labels[key] = value
}
for _, label := range rule.Labels {
key := model.LabelName(label["key"])
value := model.LabelValue(label["value"])
labels[key] = value
}
targetgroups = append(targetgroups, &targetgroup.Group{
Targets: []model.LabelSet{
model.LabelSet{
"__address__": model.LabelValue(rule.Target),
},
},
Labels: labels,
Source: fmt.Sprint(rule.ID),
})
}
// scrapeConfig
scrapeConfig := &config.ScrapeConfig{
JobName: group.Name,
Scheme: group.Scheme,
ScrapeInterval: model.Duration(time.Duration(group.Interval) * time.Second),
ScrapeTimeout: model.Duration(time.Duration(group.Timeout) * time.Second),
MetricsPath: group.MetricsPath,
HTTPClientConfig: config_util.HTTPClientConfig{
TLSConfig: config_util.TLSConfig{
InsecureSkipVerify: true,
},
},
ServiceDiscoveryConfig: sd_config.ServiceDiscoveryConfig{
StaticConfigs: targetgroups,
},
}
// scrapeConfig
if group.AuthUser != "" && group.AuthPassword != "" {
scrapeConfig.HTTPClientConfig.BasicAuth = &config_util.BasicAuth{
Username: group.AuthUser,
Password: config_util.Secret(group.AuthPassword),
}
} else if group.AuthToken != "" {
scrapeConfig.HTTPClientConfig.BearerToken = config_util.Secret(group.AuthToken)
}
conf.ScrapeConfigs = append(conf.ScrapeConfigs, scrapeConfig)
}