2015-10-06 09:41:34 +00:00
|
|
|
package provider
|
|
|
|
|
|
|
|
import (
|
|
|
|
"database/sql"
|
|
|
|
"encoding/json"
|
|
|
|
|
|
|
|
"github.com/cznic/ql"
|
|
|
|
"github.com/prometheus/common/model"
|
|
|
|
|
|
|
|
"github.com/prometheus/alertmanager/types"
|
|
|
|
)
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
ql.RegisterDriver()
|
|
|
|
}
|
|
|
|
|
|
|
|
type SQLSilences struct {
|
|
|
|
db *sql.DB
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *SQLSilences) Close() error {
|
|
|
|
return s.db.Close()
|
|
|
|
}
|
|
|
|
|
2015-10-06 10:36:33 +00:00
|
|
|
func NewSQLSilences(file string) (*SQLSilences, error) {
|
|
|
|
db, err := sql.Open("ql", file)
|
2015-10-06 09:41:34 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
tx, err := db.Begin()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if _, err := tx.Exec(createSilencesTable); err != nil {
|
|
|
|
tx.Rollback()
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
tx.Commit()
|
|
|
|
|
|
|
|
return &SQLSilences{db: db}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
const createSilencesTable = `
|
|
|
|
CREATE TABLE IF NOT EXISTS silences (
|
|
|
|
matchers string,
|
2015-10-06 10:10:42 +00:00
|
|
|
starts_at time,
|
2015-10-06 09:41:34 +00:00
|
|
|
ends_at time,
|
|
|
|
created_at time,
|
|
|
|
created_by string,
|
|
|
|
comment string
|
|
|
|
);
|
2015-10-06 11:56:02 +00:00
|
|
|
CREATE INDEX IF NOT EXISTS silences_start ON silences (starts_at);
|
|
|
|
CREATE INDEX IF NOT EXISTS silences_end ON silences (ends_at);
|
|
|
|
CREATE INDEX IF NOT EXISTS silences_id ON silences (id());
|
2015-10-06 09:41:34 +00:00
|
|
|
`
|
|
|
|
|
|
|
|
func (s *SQLSilences) Mutes(lset model.LabelSet) bool {
|
2015-10-06 10:23:48 +00:00
|
|
|
sils, err := s.All()
|
|
|
|
if err != nil {
|
|
|
|
log.Errorf("retrieving silences failed: %s", err)
|
|
|
|
// In doubt, do not silence anything.
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, sil := range sils {
|
|
|
|
if sil.Mutes(lset) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
2015-10-06 09:41:34 +00:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *SQLSilences) All() ([]*types.Silence, error) {
|
2015-10-06 10:10:42 +00:00
|
|
|
rows, err := s.db.Query(`SELECT id(), matchers, starts_at, ends_at, created_at, created_by, comment FROM silences ORDER BY starts_at DESC`)
|
2015-10-06 09:41:34 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
defer rows.Close()
|
|
|
|
|
|
|
|
var silences []*types.Silence
|
|
|
|
|
|
|
|
for rows.Next() {
|
|
|
|
var (
|
2015-10-06 11:56:02 +00:00
|
|
|
sil model.Silence
|
2015-10-06 10:10:42 +00:00
|
|
|
matchers string
|
2015-10-06 09:41:34 +00:00
|
|
|
)
|
|
|
|
|
2015-10-06 10:10:42 +00:00
|
|
|
if err := rows.Scan(&sil.ID, &matchers, &sil.StartsAt, &sil.EndsAt, &sil.CreatedAt, &sil.CreatedBy, &sil.Comment); err != nil {
|
2015-10-06 09:41:34 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := json.Unmarshal([]byte(matchers), &sil.Matchers); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2015-10-06 11:56:02 +00:00
|
|
|
silences = append(silences, types.NewSilence(&sil))
|
2015-10-06 09:41:34 +00:00
|
|
|
}
|
|
|
|
if err := rows.Err(); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return silences, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *SQLSilences) Set(sil *types.Silence) (uint64, error) {
|
2015-10-06 11:56:02 +00:00
|
|
|
mb, err := json.Marshal(sil.Silence.Matchers)
|
2015-10-06 09:41:34 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
|
|
|
|
tx, err := s.db.Begin()
|
|
|
|
if err != nil {
|
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
|
2015-10-06 10:10:42 +00:00
|
|
|
res, err := tx.Exec(`INSERT INTO silences VALUES ($1, $2, $3, $4, $5, $6)`,
|
2015-10-06 09:41:34 +00:00
|
|
|
string(mb),
|
|
|
|
sil.StartsAt,
|
|
|
|
sil.EndsAt,
|
2015-10-06 10:10:42 +00:00
|
|
|
sil.CreatedAt,
|
2015-10-06 09:41:34 +00:00
|
|
|
sil.CreatedBy,
|
|
|
|
sil.Comment,
|
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
tx.Rollback()
|
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
|
|
|
|
sid, err := res.LastInsertId()
|
|
|
|
if err != nil {
|
|
|
|
tx.Rollback()
|
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
|
|
|
|
tx.Commit()
|
|
|
|
|
|
|
|
return uint64(sid), nil
|
|
|
|
}
|
|
|
|
|
2015-10-06 10:23:48 +00:00
|
|
|
func (s *SQLSilences) Del(sid uint64) error {
|
|
|
|
tx, err := s.db.Begin()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if _, err := tx.Exec(`DELETE FROM silences WHERE id() == $1`, sid); err != nil {
|
|
|
|
tx.Rollback()
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
tx.Commit()
|
|
|
|
|
2015-10-06 09:41:34 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2015-10-06 10:23:48 +00:00
|
|
|
func (s *SQLSilences) Get(sid uint64) (*types.Silence, error) {
|
|
|
|
row := s.db.QueryRow(`SELECT id(), matchers, starts_at, ends_at, created_at, created_by, comment FROM silences WHERE id() == $1`, sid)
|
|
|
|
|
|
|
|
var (
|
2015-10-06 11:56:02 +00:00
|
|
|
sil model.Silence
|
2015-10-06 10:23:48 +00:00
|
|
|
matchers string
|
|
|
|
)
|
|
|
|
err := row.Scan(&sil.ID, &matchers, &sil.StartsAt, &sil.EndsAt, &sil.CreatedAt, &sil.CreatedBy, &sil.Comment)
|
|
|
|
if err == sql.ErrNoRows {
|
|
|
|
return nil, ErrNotFound
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if err := json.Unmarshal([]byte(matchers), &sil.Matchers); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2015-10-06 11:56:02 +00:00
|
|
|
return types.NewSilence(&sil), nil
|
2015-10-06 09:41:34 +00:00
|
|
|
}
|