From be40033886499396cc313dcf3c62817136b881bf Mon Sep 17 00:00:00 2001 From: kolaente Date: Sun, 31 Jan 2021 23:03:41 +0100 Subject: [PATCH] Expose watermill metrics through the default metrics endpoint --- config.yml.sample | 4 ++-- go.sum | 1 + pkg/events/events.go | 7 +++++- pkg/events/listeners.go | 1 + pkg/metrics/metrics.go | 49 ++++++++++++++++++++++++++++++++--------- pkg/models/listeners.go | 4 ++++ pkg/routes/metrics.go | 2 +- 7 files changed, 54 insertions(+), 14 deletions(-) diff --git a/config.yml.sample b/config.yml.sample index 714a04aec..9851e4e72 100644 --- a/config.yml.sample +++ b/config.yml.sample @@ -137,9 +137,9 @@ log: # Echo has its own logging which usually is unnessecary, which is why it is disabled by default. Possible values are stdout, stderr, file or off to disable standard logging. echo: "off" # Whether or not to log events. Useful for debugging. Possible values are stdout, stderr, file or off to disable events logging. - events: "stdout" + events: "stdout" # The log level for event log messages. Possible values (case-insensitive) are ERROR, INFO, DEBUG. - eventslevel: "info" + eventslevel: "info" ratelimit: # whether or not to enable the rate limit diff --git a/go.sum b/go.sum index 67538bb13..6b472d4a5 100644 --- a/go.sum +++ b/go.sum @@ -218,6 +218,7 @@ github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM= github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= +github.com/go-chi/chi v4.0.2+incompatible h1:maB6vn6FqCxrpz4FqWdh4+lwpyZIQS7YEAUcHlgXVRs= github.com/go-chi/chi v4.0.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= diff --git a/pkg/events/events.go b/pkg/events/events.go index bc034e175..aebfbc837 100644 --- a/pkg/events/events.go +++ b/pkg/events/events.go @@ -22,7 +22,9 @@ import ( "time" "code.vikunja.io/api/pkg/log" + vmetrics "code.vikunja.io/api/pkg/metrics" "github.com/ThreeDotsLabs/watermill" + "github.com/ThreeDotsLabs/watermill/components/metrics" "github.com/ThreeDotsLabs/watermill/message" "github.com/ThreeDotsLabs/watermill/message/router/middleware" "github.com/ThreeDotsLabs/watermill/pubsub/gochannel" @@ -55,6 +57,9 @@ func InitEvents() (err error) { middleware.Recoverer, ) + metricsBuilder := metrics.NewPrometheusMetricsBuilder(vmetrics.GetRegistry(), "", "") + metricsBuilder.AddPrometheusRouterMetrics(router) + pubsub = gochannel.NewGoChannel( gochannel.Config{ OutputChannelBuffer: 1024, @@ -64,7 +69,7 @@ func InitEvents() (err error) { for topic, funcs := range listeners { for _, handler := range funcs { - router.AddNoPublisherHandler(topic+"."+watermill.NewShortUUID(), topic, pubsub, func(msg *message.Message) error { + router.AddNoPublisherHandler(topic+"."+handler.Name(), topic, pubsub, func(msg *message.Message) error { return handler.Handle(msg.Payload) }) } diff --git a/pkg/events/listeners.go b/pkg/events/listeners.go index 846995426..3368c9a07 100644 --- a/pkg/events/listeners.go +++ b/pkg/events/listeners.go @@ -20,6 +20,7 @@ import "github.com/ThreeDotsLabs/watermill/message" type Listener interface { Handle(payload message.Payload) error + Name() string } var listeners map[string][]Listener diff --git a/pkg/metrics/metrics.go b/pkg/metrics/metrics.go index 5f51b038c..da5240182 100644 --- a/pkg/metrics/metrics.go +++ b/pkg/metrics/metrics.go @@ -41,6 +41,18 @@ const ( TeamCountKey = `teamcount` ) +var registry *prometheus.Registry + +func GetRegistry() *prometheus.Registry { + if registry == nil { + registry = prometheus.NewRegistry() + registry.MustRegister(prometheus.NewProcessCollector(prometheus.ProcessCollectorOpts{})) + registry.MustRegister(prometheus.NewGoCollector()) + } + + return registry +} + // InitMetrics Initializes the metrics func InitMetrics() { // init active users, sometimes we'll have garbage from previous runs in redis instead @@ -48,50 +60,67 @@ func InitMetrics() { log.Fatalf("Could not set initial count for active users, error was %s", err) } + GetRegistry() + // Register total list count metric - promauto.NewGaugeFunc(prometheus.GaugeOpts{ + err := registry.Register(promauto.NewGaugeFunc(prometheus.GaugeOpts{ Name: "vikunja_list_count", Help: "The number of lists on this instance", }, func() float64 { count, _ := GetCount(ListCountKey) return float64(count) - }) + })) + if err != nil { + log.Criticalf("Could not register metrics for %s: %s", ListCountKey, err) + } // Register total user count metric - promauto.NewGaugeFunc(prometheus.GaugeOpts{ + err = registry.Register(promauto.NewGaugeFunc(prometheus.GaugeOpts{ Name: "vikunja_user_count", Help: "The total number of users on this instance", }, func() float64 { count, _ := GetCount(UserCountKey) return float64(count) - }) + })) + if err != nil { + log.Criticalf("Could not register metrics for %s: %s", UserCountKey, err) + } // Register total Namespaces count metric - promauto.NewGaugeFunc(prometheus.GaugeOpts{ + err = registry.Register(promauto.NewGaugeFunc(prometheus.GaugeOpts{ Name: "vikunja_namespcae_count", Help: "The total number of namespaces on this instance", }, func() float64 { count, _ := GetCount(NamespaceCountKey) return float64(count) - }) + })) + if err != nil { + log.Criticalf("Could not register metrics for %s: %s", NamespaceCountKey, err) + } // Register total Tasks count metric - promauto.NewGaugeFunc(prometheus.GaugeOpts{ + err = registry.Register(promauto.NewGaugeFunc(prometheus.GaugeOpts{ Name: "vikunja_task_count", Help: "The total number of tasks on this instance", }, func() float64 { count, _ := GetCount(TaskCountKey) return float64(count) - }) + })) + if err != nil { + log.Criticalf("Could not register metrics for %s: %s", TaskCountKey, err) + } // Register total user count metric - promauto.NewGaugeFunc(prometheus.GaugeOpts{ + err = registry.Register(promauto.NewGaugeFunc(prometheus.GaugeOpts{ Name: "vikunja_team_count", Help: "The total number of teams on this instance", }, func() float64 { count, _ := GetCount(TeamCountKey) return float64(count) - }) + })) + if err != nil { + log.Criticalf("Could not register metrics for %s: %s", TeamCountKey, err) + } } // GetCount returns the current count from redis diff --git a/pkg/models/listeners.go b/pkg/models/listeners.go index 21264f309..fce83ad3e 100644 --- a/pkg/models/listeners.go +++ b/pkg/models/listeners.go @@ -30,6 +30,10 @@ func RegisterListeners() { type SendTaskCreatedNotification struct { } +func (s *SendTaskCreatedNotification) Name() string { + return "task.created.notification" +} + func (s *SendTaskCreatedNotification) Handle(payload message.Payload) (err error) { event := &TaskCreatedEvent{} err = json.Unmarshal(payload, event) diff --git a/pkg/routes/metrics.go b/pkg/routes/metrics.go index 2c1045f00..c6ca0f1c2 100644 --- a/pkg/routes/metrics.go +++ b/pkg/routes/metrics.go @@ -71,7 +71,7 @@ func setupMetrics(a *echo.Group) { } } - a.GET("/metrics", echo.WrapHandler(promhttp.Handler())) + a.GET("/metrics", echo.WrapHandler(promhttp.HandlerFor(metrics.GetRegistry(), promhttp.HandlerOpts{}))) } func setupMetricsMiddleware(a *echo.Group) {