[#600] Add health metric

Signed-off-by: Denis Kirillov <denis@nspcc.ru>
This commit is contained in:
Denis Kirillov 2022-07-21 17:42:24 +03:00 committed by Alex Vanin
parent 757600608c
commit 89d240d831
2 changed files with 55 additions and 38 deletions

View file

@ -35,6 +35,8 @@ type (
obj layer.Client
api api.Handler
metrics GateMetricsCollector
maxClients api.MaxClients
webDone chan struct{}
@ -45,6 +47,10 @@ type (
KeyFile string
CertFile string
}
GateMetricsCollector interface {
SetHealth(int32)
}
)
func newApp(ctx context.Context, l *zap.Logger, v *viper.Viper) *App {
@ -57,6 +63,8 @@ func newApp(ctx context.Context, l *zap.Logger, v *viper.Viper) *App {
obj layer.Client
nc *notifications.Controller
gateMetrics GateMetricsCollector
prmPool pool.InitParameters
reBalance = defaultRebalanceInterval
@ -180,6 +188,10 @@ func newApp(ctx context.Context, l *zap.Logger, v *viper.Viper) *App {
l.Fatal("could not initialize API handler", zap.Error(err))
}
if v.GetBool(cfgEnableMetrics) {
gateMetrics = newGateMetrics()
}
return &App{
ctr: ctr,
log: l,
@ -188,6 +200,8 @@ func newApp(ctx context.Context, l *zap.Logger, v *viper.Viper) *App {
tls: tls,
api: caller,
metrics: gateMetrics,
webDone: make(chan struct{}, 1),
wrkDone: make(chan struct{}, 1),
@ -215,6 +229,10 @@ func (a *App) Wait() {
zap.String("version", version.Version),
)
if a.metrics != nil {
a.metrics.SetHealth(1)
}
<-a.webDone // wait for web-server to be stopped
a.log.Info("application finished")
@ -238,7 +256,6 @@ func (a *App) Server(ctx context.Context) {
router := newS3Router()
// Attach app-specific routes:
// attachHealthy(router, a.cli)
attachMetrics(router, a.cfg, a.log)
attachProfiler(router, a.cfg, a.log)

View file

@ -1,46 +1,46 @@
package main
import (
"fmt"
"net/http"
"github.com/gorilla/mux"
"github.com/prometheus/client_golang/prometheus"
)
// Healthy is a health check interface.
type Healthy interface {
Status() error
}
const (
healthyState = "NeoFS S3 Gateway is "
hdrContentType = "Content-Type"
defaultContentType = "text/plain; charset=utf-8"
namespace = "neofs_s3_gw"
stateSubsystem = "state"
)
//nolint:deadcode,unused // TODO
func attachHealthy(r *mux.Router, h Healthy) {
healthy := r.PathPrefix(systemPath + "/-").
Subrouter().
StrictSlash(true)
healthy.HandleFunc("/ready", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set(hdrContentType, defaultContentType)
w.WriteHeader(http.StatusOK)
_, _ = fmt.Fprintln(w, healthyState+"ready")
})
healthy.HandleFunc("/healthy", func(w http.ResponseWriter, r *http.Request) {
code := http.StatusOK
msg := "healthy"
if err := h.Status(); err != nil {
msg = "unhealthy: " + err.Error()
code = http.StatusBadRequest
}
w.Header().Set(hdrContentType, defaultContentType)
w.WriteHeader(code)
_, _ = fmt.Fprintln(w, healthyState+msg)
})
type GateMetrics struct {
stateMetrics
}
type stateMetrics struct {
healthCheck prometheus.Gauge
}
func newGateMetrics() *GateMetrics {
stateMetric := newStateMetrics()
stateMetric.register()
return &GateMetrics{
stateMetrics: stateMetric,
}
}
func newStateMetrics() stateMetrics {
return stateMetrics{
healthCheck: prometheus.NewGauge(prometheus.GaugeOpts{
Namespace: namespace,
Subsystem: stateSubsystem,
Name: "health",
Help: "Current S3 gateway state",
}),
}
}
func (m stateMetrics) register() {
prometheus.MustRegister(m.healthCheck)
}
func (m stateMetrics) SetHealth(s int32) {
m.healthCheck.Set(float64(s))
}