diff --git a/pkg/api/routes.go b/pkg/api/routes.go index 14ebbc9..d3425e6 100644 --- a/pkg/api/routes.go +++ b/pkg/api/routes.go @@ -30,4 +30,9 @@ var routes = Routes{ "/healtz", healthz, }, + Route{ + "GET", + "/varz", + varz, + }, } diff --git a/pkg/api/varz.go b/pkg/api/varz.go new file mode 100644 index 0000000..fc745d0 --- /dev/null +++ b/pkg/api/varz.go @@ -0,0 +1,25 @@ +package api + +import ( + "expvar" + "fmt" + "net/http" + + "github.com/ncarlier/webhookd/pkg/config" +) + +func varz(conf *config.Config) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + fmt.Fprintf(w, "{\n") + first := true + expvar.Do(func(kv expvar.KeyValue) { + if !first { + fmt.Fprintf(w, ",\n") + } + first = false + fmt.Fprintf(w, "%q: %s", kv.Key, kv.Value) + }) + fmt.Fprintf(w, "\n}\n") + }) +} diff --git a/pkg/metric/metric.go b/pkg/metric/metric.go new file mode 100644 index 0000000..4c0a4eb --- /dev/null +++ b/pkg/metric/metric.go @@ -0,0 +1,35 @@ +package metric + +import ( + "expvar" + "runtime" + "time" +) + +var startTime = time.Now().UTC() + +func goroutines() interface{} { + return runtime.NumGoroutine() +} + +// uptime is an expvar.Func compliant wrapper for uptime info. +func uptime() interface{} { + uptime := time.Since(startTime) + return int64(uptime) +} + +var stats = expvar.NewMap("hookstats") + +var ( + // Requests count the number of request + Requests expvar.Int + // RequestsFailed count the number of failed request + RequestsFailed expvar.Int +) + +func init() { + stats.Set("requests", &Requests) + stats.Set("requests_failed", &RequestsFailed) + expvar.Publish("goroutines", expvar.Func(goroutines)) + expvar.Publish("uptime", expvar.Func(uptime)) +} diff --git a/pkg/worker/worker.go b/pkg/worker/worker.go index b3bdbcf..d2f34a5 100644 --- a/pkg/worker/worker.go +++ b/pkg/worker/worker.go @@ -3,6 +3,8 @@ package worker import ( "fmt" + "github.com/ncarlier/webhookd/pkg/metric" + "github.com/ncarlier/webhookd/pkg/logger" "github.com/ncarlier/webhookd/pkg/model" "github.com/ncarlier/webhookd/pkg/notification" @@ -42,8 +44,10 @@ func (w Worker) Start() { case work := <-w.Work: // Receive a work request. logger.Debug.Printf("Worker #%d received work request: %s#%d\n", w.ID, work.Name, work.ID) + metric.Requests.Add(1) err := run(&work) if err != nil { + metric.RequestsFailed.Add(1) work.MessageChan <- []byte(fmt.Sprintf("error: %s", err.Error())) } else { work.MessageChan <- []byte("done")