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

View file

@ -1,46 +1,46 @@
package main package main
import ( import (
"fmt" "github.com/prometheus/client_golang/prometheus"
"net/http"
"github.com/gorilla/mux"
) )
// Healthy is a health check interface.
type Healthy interface {
Status() error
}
const ( const (
healthyState = "NeoFS S3 Gateway is " namespace = "neofs_s3_gw"
hdrContentType = "Content-Type" stateSubsystem = "state"
defaultContentType = "text/plain; charset=utf-8"
) )
//nolint:deadcode,unused // TODO type GateMetrics struct {
func attachHealthy(r *mux.Router, h Healthy) { stateMetrics
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) type stateMetrics struct {
w.WriteHeader(code) healthCheck prometheus.Gauge
_, _ = fmt.Fprintln(w, healthyState+msg) }
})
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))
} }