Преглед на файлове

Added healthcheck metrics.

Richard Crowley преди 14 години
родител
ревизия
b897f10231
променени са 5 файла, в които са добавени 118 реда и са изтрити 9 реда
  1. 30 5
      cmd/metrics/metrics.go
  2. 26 0
      healthcheck.go
  3. 36 2
      log.go
  4. 6 0
      registry.go
  5. 20 2
      syslog.go

+ 30 - 5
cmd/metrics/metrics.go

@@ -1,9 +1,10 @@
 package main
 
 import (
-//	"log"
+	"log"
 	"metrics"
-//	"os"
+	"os"
+	"rand"
 //	"syslog"
 	"time"
 )
@@ -48,10 +49,19 @@ func main() {
 		}()
 	}
 
+	hc := metrics.NewHealthcheck(func(h metrics.Healthcheck) {
+		if 0 < rand.Intn(2) {
+			h.Healthy()
+		} else {
+			h.Unhealthy(os.NewError("baz"))
+		}
+	})
+	r.RegisterHealthcheck("baz", hc)
+
 	s := metrics.NewExpDecaySample(1028, 0.015)
 //	s := metrics.NewUniformSample(1028)
 	h := metrics.NewHistogram(s)
-	r.RegisterHistogram("baz", h)
+	r.RegisterHistogram("bang", h)
 	for i := 0; i < fanout; i++ {
 		go func() {
 			for {
@@ -68,7 +78,7 @@ func main() {
 	}
 
 	m := metrics.NewMeter()
-	r.RegisterMeter("bang", m)
+	r.RegisterMeter("quux", m)
 	for i := 0; i < fanout; i++ {
 		go func() {
 			for {
@@ -84,7 +94,22 @@ func main() {
 		}()
 	}
 
-//	metrics.Log(r, 60, log.New(os.Stderr, "metrics: ", log.Lmicroseconds))
+	t := metrics.NewTimer()
+	r.RegisterTimer("hooah", t)
+	for i := 0; i < fanout; i++ {
+		go func() {
+			for {
+				t.Time(func() { time.Sleep(300e6) })
+			}
+		}()
+		go func() {
+			for {
+				t.Time(func() { time.Sleep(400e6) })
+			}
+		}()
+	}
+
+	metrics.Log(r, 60, log.New(os.Stderr, "metrics: ", log.Lmicroseconds))
 
 /*
 	w, err := syslog.Dial("unixgram", "/dev/log", syslog.LOG_INFO, "metrics")

+ 26 - 0
healthcheck.go

@@ -4,6 +4,32 @@ import "os"
 
 type Healthcheck interface {
 	Check()
+	Error() os.Error
 	Healthy()
 	Unhealthy(os.Error)
 }
+
+type healthcheck struct {
+	err os.Error
+	f func(Healthcheck)
+}
+
+func NewHealthcheck(f func(Healthcheck)) Healthcheck {
+	return &healthcheck{nil, f}
+}
+
+func (h *healthcheck) Check() {
+	h.f(h)
+}
+
+func (h *healthcheck) Error() os.Error {
+	return h.err
+}
+
+func (h *healthcheck) Healthy() {
+	h.err = nil
+}
+
+func (h *healthcheck) Unhealthy(err os.Error) {
+	h.err = err
+}

+ 36 - 2
log.go

@@ -13,8 +13,9 @@ func Log(r Registry, interval int, l *log.Logger) {
 		for name, g := range r.Gauges() {
 			l.Printf("gauge %s\n\tvalue:\t%9d\n", name, g.Value())
 		}
+		r.RunHealthchecks()
 		for name, h := range r.Healthchecks() {
-			l.Printf("healthcheck %s TODO\n", name, h)
+			l.Printf("healthcheck %s\n\terror: %v\n", name, h.Error())
 		}
 		for name, h := range r.Histograms() {
 			ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999})
@@ -62,7 +63,40 @@ func Log(r Registry, interval int, l *log.Logger) {
 			)
 		}
 		for name, t := range r.Timers() {
-			l.Printf("timer %s TODO\n", name, t)
+			ps := t.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999})
+			l.Printf(
+				`timer %s
+	count:	%9d
+	min:	%9d
+	max:	%9d
+	mean:	%12.2f
+	stddev:	%12.2f
+	median:	%12.2f
+	75%%:	%12.2f
+	95%%:	%12.2f
+	99%%:	%12.2f
+	99.9%%:	%12.2f
+	1-min:	%12.2f
+	5-min:	%12.2f
+	15-min:	%12.2f
+	mean:	%12.2f
+`,
+				name,
+				t.Count(),
+				t.Min(),
+				t.Max(),
+				t.Mean(),
+				t.StdDev(),
+				ps[0],
+				ps[1],
+				ps[2],
+				ps[3],
+				ps[4],
+				t.Rate1(),
+				t.Rate5(),
+				t.Rate15(),
+				t.RateMean(),
+			)
 		}
 		time.Sleep(int64(1e9) * int64(interval))
 	}

+ 6 - 0
registry.go

@@ -9,6 +9,8 @@ type Registry interface{
 	Meters() map[string]Meter
 	Timers() map[string]Timer
 
+	RunHealthchecks()
+
 	GetCounter(string) (Counter, bool)
 	GetGauge(string) (Gauge, bool)
 	GetHealthcheck(string) (Healthcheck, bool)
@@ -76,6 +78,10 @@ func (r *registry) Timers() map[string]Timer {
 	return r.timers
 }
 
+func (r *registry) RunHealthchecks() {
+	for _, h := range r.healthchecks { h.Check() }
+}
+
 func (r *registry) GetCounter(name string) (Counter, bool) {
 	c, ok := r.counters[name]
 	return c, ok

+ 20 - 2
syslog.go

@@ -14,8 +14,9 @@ func Syslog(r Registry, interval int, w *syslog.Writer) {
 		for name, g := range r.Gauges() {
 			w.Info(fmt.Sprintf("gauge %s: value: %d", name, g.Value()))
 		}
+		r.RunHealthchecks()
 		for name, h := range r.Healthchecks() {
-			w.Info(fmt.Sprintf("healthcheck %s: TODO", name, h))
+			w.Info(fmt.Sprintf("healthcheck %s: error: %v", name, h.Error()))
 		}
 		for name, h := range r.Histograms() {
 			ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999})
@@ -46,7 +47,24 @@ func Syslog(r Registry, interval int, w *syslog.Writer) {
 			))
 		}
 		for name, t := range r.Timers() {
-			w.Info(fmt.Sprintf("timer %s: TODO", name, t))
+			w.Info(fmt.Sprintf(
+				"timer %s: count: %d min: %d max: %d mean: %.2f stddev: %.2f median: %.2f 75%%: %.2f 95%%: %.2f 99%%: %.2f 99.9%%: %.2f 1-min: %.2f 5-min: %.2f 15-min: %.2f mean: %.2f",
+				name,
+				h.Count(),
+				h.Min(),
+				h.Max(),
+				h.Mean(),
+				h.StdDev(),
+				ps[0],
+				ps[1],
+				ps[2],
+				ps[3],
+				ps[4],
+				m.Rate1(),
+				m.Rate5(),
+				m.Rate15(),
+				m.RateMean(),
+			))
 		}
 		time.Sleep(int64(1e9) * int64(interval))
 	}