Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Making redis monitoring a little prettier. #1944

Merged
merged 1 commit into from Oct 23, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 2 additions & 6 deletions cmd/bosun/database/config_data.go
Expand Up @@ -6,8 +6,6 @@ import (

"github.com/garyburd/redigo/redis"

"bosun.org/collect"
"bosun.org/opentsdb"
"bosun.org/slog"
)

Expand All @@ -23,8 +21,7 @@ func (d *dataAccess) Configs() ConfigDataAccess {
const configLifetime = 60 * 24 * 14 // 2 weeks

func (d *dataAccess) SaveTempConfig(text string) (string, error) {
defer collect.StartTimer("redis", opentsdb.TagSet{"op": "SaveTempConfig"})()
conn := d.GetConnection()
conn := d.Get()
defer conn.Close()

sig := md5.Sum([]byte(text))
Expand All @@ -38,8 +35,7 @@ func (d *dataAccess) SaveTempConfig(text string) (string, error) {
}

func (d *dataAccess) GetTempConfig(hash string) (string, error) {
defer collect.StartTimer("redis", opentsdb.TagSet{"op": "GetTempConfig"})()
conn := d.GetConnection()
conn := d.Get()
defer conn.Close()

key := "tempConfig:" + hash
Expand Down
38 changes: 33 additions & 5 deletions cmd/bosun/database/database.go
Expand Up @@ -5,6 +5,8 @@ package database

import (
"log"
"runtime"
"strings"
"time"

"bosun.org/collect"
Expand Down Expand Up @@ -90,13 +92,39 @@ func StartLedis(dataDir string, bind string) (stop func(), err error) {
return app.Close, nil
}

//interface so things can get a raw connection (mostly tests), but still discourage it.
type Connector interface {
GetConnection() redis.Conn
//RedisConnector is a simple interface so things can get a raw connection (mostly tests), but still discourage it.
// makes dataAccess interchangable with redis.Pool
type RedisConnector interface {
Get() redis.Conn
}

func (d *dataAccess) GetConnection() redis.Conn {
return d.pool.Get()
//simple wrapper around a redis conn. Uses close to also stop and submit a simple timer for bosun stats on operations.
type connWrapper struct {
redis.Conn
closer func()
}

func (c *connWrapper) Close() error {
err := c.Conn.Close()
c.closer()
return err
}

func (d *dataAccess) Get() redis.Conn {
closer := collect.StartTimer("redis", opentsdb.TagSet{"op": myCallerName()})
return &connWrapper{
Conn: d.pool.Get(),
closer: closer,
}
}

//gets name of function that called the currently executing function.
func myCallerName() string {
fpcs := make([]uintptr, 1)
runtime.Callers(3, fpcs)
fun := runtime.FuncForPC(fpcs[0])
nameSplit := strings.Split(fun.Name(), ".")
return nameSplit[len(nameSplit)-1]
}

func newPool(server, password string, database int, isRedis bool, maxActive int, wait bool) *redis.Pool {
Expand Down
28 changes: 9 additions & 19 deletions cmd/bosun/database/error_data.go
@@ -1,9 +1,7 @@
package database

import (
"bosun.org/collect"
"bosun.org/models"
"bosun.org/opentsdb"
"encoding/json"
"fmt"
"github.com/garyburd/redigo/redis"
Expand Down Expand Up @@ -43,16 +41,14 @@ const (
)

func (d *dataAccess) MarkAlertSuccess(name string) error {
defer collect.StartTimer("redis", opentsdb.TagSet{"op": "MarkAlertSuccess"})()
conn := d.GetConnection()
conn := d.Get()
defer conn.Close()
_, err := conn.Do("SREM", failingAlerts, name)
return err
}

func (d *dataAccess) MarkAlertFailure(name string, msg string) error {
defer collect.StartTimer("redis", opentsdb.TagSet{"op": "MarkAlertFailure"})()
conn := d.GetConnection()
conn := d.Get()
defer conn.Close()

failing, err := d.IsAlertFailing(name)
Expand Down Expand Up @@ -103,8 +99,7 @@ func (d *dataAccess) MarkAlertFailure(name string, msg string) error {
}

func (d *dataAccess) GetFailingAlertCounts() (int, int, error) {
defer collect.StartTimer("redis", opentsdb.TagSet{"op": "GetFailingAlertCounts"})()
conn := d.GetConnection()
conn := d.Get()
defer conn.Close()
failing, err := redis.Int(conn.Do("SCARD", failingAlerts))
if err != nil {
Expand All @@ -118,8 +113,7 @@ func (d *dataAccess) GetFailingAlertCounts() (int, int, error) {
}

func (d *dataAccess) GetFailingAlerts() (map[string]bool, error) {
defer collect.StartTimer("redis", opentsdb.TagSet{"op": "GetFailingAlertCounts"})()
conn := d.GetConnection()
conn := d.Get()
defer conn.Close()
alerts, err := redis.Strings(conn.Do("SMEMBERS", failingAlerts))
if err != nil {
Expand All @@ -132,8 +126,7 @@ func (d *dataAccess) GetFailingAlerts() (map[string]bool, error) {
return r, nil
}
func (d *dataAccess) IsAlertFailing(name string) (bool, error) {
defer collect.StartTimer("redis", opentsdb.TagSet{"op": "IsAlertFailing"})()
conn := d.GetConnection()
conn := d.Get()
defer conn.Close()
return redis.Bool(conn.Do("SISMEMBER", failingAlerts, name))
}
Expand All @@ -142,7 +135,7 @@ func errorListKey(name string) string {
return fmt.Sprintf("errors:%s", name)
}
func (d *dataAccess) getLastErrorEvent(name string) (*models.AlertError, error) {
conn := d.GetConnection()
conn := d.Get()
defer conn.Close()
str, err := redis.Bytes(conn.Do("LINDEX", errorListKey(name), "0"))
if err != nil {
Expand All @@ -159,8 +152,7 @@ func (d *dataAccess) getLastErrorEvent(name string) (*models.AlertError, error)
}

func (d *dataAccess) GetFullErrorHistory() (map[string][]*models.AlertError, error) {
defer collect.StartTimer("redis", opentsdb.TagSet{"op": "GetFullErrorHistory"})()
conn := d.GetConnection()
conn := d.Get()
defer conn.Close()

alerts, err := redis.Strings(conn.Do("SMEMBERS", alertsWithErrors))
Expand Down Expand Up @@ -188,8 +180,7 @@ func (d *dataAccess) GetFullErrorHistory() (map[string][]*models.AlertError, err
}

func (d *dataAccess) ClearAlert(name string) error {
defer collect.StartTimer("redis", opentsdb.TagSet{"op": "ClearAlert"})()
conn := d.GetConnection()
conn := d.Get()
defer conn.Close()

_, err := conn.Do("SREM", alertsWithErrors, name)
Expand All @@ -216,8 +207,7 @@ func (d *dataAccess) ClearAlert(name string) error {
//Things could forseeably get a bit inconsistent if concurrent changes happen in just the wrong way.
//Clear all should do a more thourogh cleanup to fully reset things.
func (d *dataAccess) ClearAll() error {
defer collect.StartTimer("redis", opentsdb.TagSet{"op": "ClearAll"})()
conn := d.GetConnection()
conn := d.Get()
defer conn.Close()

alerts, err := redis.Strings(conn.Do("SMEMBERS", alertsWithErrors))
Expand Down
11 changes: 3 additions & 8 deletions cmd/bosun/database/metric_metadata.go
Expand Up @@ -2,11 +2,8 @@ package database

import (
"fmt"
"time"

"bosun.org/collect"
"bosun.org/opentsdb"
"github.com/garyburd/redigo/redis"
"time"
)

/*
Expand All @@ -30,19 +27,17 @@ func (d *dataAccess) Metadata() MetadataDataAccess {
}

func (d *dataAccess) PutMetricMetadata(metric string, field string, value string) error {
defer collect.StartTimer("redis", opentsdb.TagSet{"op": "PutMetricMeta"})()
if field != "desc" && field != "unit" && field != "rate" {
return fmt.Errorf("Unknown metric metadata field: %s", field)
}
conn := d.GetConnection()
conn := d.Get()
defer conn.Close()
_, err := conn.Do("HMSET", metricMetaKey(metric), field, value, "lastTouched", time.Now().UTC().Unix())
return err
}

func (d *dataAccess) GetMetricMetadata(metric string) (*MetricMetadata, error) {
defer collect.StartTimer("redis", opentsdb.TagSet{"op": "GetMetricMeta"})()
conn := d.GetConnection()
conn := d.Get()
defer conn.Close()
v, err := redis.Values(conn.Do("HGETALL", metricMetaKey(metric)))
if err != nil {
Expand Down
17 changes: 5 additions & 12 deletions cmd/bosun/database/notification_data.go
Expand Up @@ -7,9 +7,7 @@ import (

"github.com/garyburd/redigo/redis"

"bosun.org/collect"
"bosun.org/models"
"bosun.org/opentsdb"
"bosun.org/slog"
)

Expand Down Expand Up @@ -48,8 +46,7 @@ func (d *dataAccess) Notifications() NotificationDataAccess {
}

func (d *dataAccess) InsertNotification(ak models.AlertKey, notification string, dueAt time.Time) error {
defer collect.StartTimer("redis", opentsdb.TagSet{"op": "InsertNotification"})()
conn := d.GetConnection()
conn := d.Get()
defer conn.Close()

_, err := conn.Do("ZADD", pendingNotificationsKey, dueAt.UTC().Unix(), fmt.Sprintf("%s:%s", ak, notification))
Expand All @@ -61,8 +58,7 @@ func (d *dataAccess) InsertNotification(ak models.AlertKey, notification string,
}

func (d *dataAccess) GetDueNotifications() (map[models.AlertKey]map[string]time.Time, error) {
defer collect.StartTimer("redis", opentsdb.TagSet{"op": "GetDueNotifications"})()
conn := d.GetConnection()
conn := d.Get()
defer conn.Close()
m, err := redis.Int64Map(conn.Do("ZRANGEBYSCORE", pendingNotificationsKey, 0, time.Now().UTC().Unix(), "WITHSCORES"))
if err != nil {
Expand All @@ -84,17 +80,15 @@ func (d *dataAccess) GetDueNotifications() (map[models.AlertKey]map[string]time.
}

func (d *dataAccess) ClearNotificationsBefore(t time.Time) error {
defer collect.StartTimer("redis", opentsdb.TagSet{"op": "ClearNotificationsBefore"})()
conn := d.GetConnection()
conn := d.Get()
defer conn.Close()

_, err := conn.Do("ZREMRANGEBYSCORE", pendingNotificationsKey, 0, t.UTC().Unix())
return slog.Wrap(err)
}

func (d *dataAccess) ClearNotifications(ak models.AlertKey) error {
defer collect.StartTimer("redis", opentsdb.TagSet{"op": "ClearNotifications"})()
conn := d.GetConnection()
conn := d.Get()
defer conn.Close()

nots, err := redis.Strings(conn.Do("SMEMBERS", notsByAlertKeyKey(ak)))
Expand All @@ -116,8 +110,7 @@ func (d *dataAccess) ClearNotifications(ak models.AlertKey) error {
}

func (d *dataAccess) GetNextNotificationTime() (time.Time, error) {
defer collect.StartTimer("redis", opentsdb.TagSet{"op": "GetNextNotificationTime"})()
conn := d.GetConnection()
conn := d.Get()
defer conn.Close()

m, err := redis.Int64Map(conn.Do("ZRANGE", pendingNotificationsKey, 0, 0, "WITHSCORES"))
Expand Down