Expose watermill metrics through the default metrics endpoint

This commit is contained in:
kolaente 2021-01-31 23:03:41 +01:00
parent 51024a595d
commit be40033886
Signed by: konrad
GPG Key ID: F40E70337AB24C9B
7 changed files with 54 additions and 14 deletions

View File

@ -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

1
go.sum
View File

@ -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=

View File

@ -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)
})
}

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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) {