check / check (push) Successful in 3m25s
MAINTENANCE_MODE did nothing but make the healthcheck JSON report maintenanceMode: true; no request was ever served differently, so an operator who set it expecting requests to be refused got nothing. It is removed from the configuration, the startup configuration log line, the healthcheck JSON, the README and the Settings page, together with the uncalled Server.MaintenanceMode method and the healthcheck's dependency on the configuration. A leftover value in an environment is ignored like any other unknown variable. Model: opus-5-5
83 rindas
1.9 KiB
Go
83 rindas
1.9 KiB
Go
// Package healthcheck provides application health status reporting.
|
|
package healthcheck
|
|
|
|
import (
|
|
"context"
|
|
"log/slog"
|
|
"time"
|
|
|
|
"go.uber.org/fx"
|
|
"sneak.berlin/go/webhooker/internal/database"
|
|
"sneak.berlin/go/webhooker/internal/globals"
|
|
"sneak.berlin/go/webhooker/internal/logger"
|
|
)
|
|
|
|
//nolint:revive // HealthcheckParams is a standard fx naming convention.
|
|
type HealthcheckParams struct {
|
|
fx.In
|
|
|
|
Globals *globals.Globals
|
|
Logger *logger.Logger
|
|
Database *database.Database
|
|
}
|
|
|
|
// Healthcheck tracks application uptime and reports health status.
|
|
type Healthcheck struct {
|
|
StartupTime time.Time
|
|
log *slog.Logger
|
|
params *HealthcheckParams
|
|
}
|
|
|
|
// New creates a Healthcheck that records the startup time on fx
|
|
// start.
|
|
func New(
|
|
lc fx.Lifecycle,
|
|
params HealthcheckParams,
|
|
) (*Healthcheck, error) {
|
|
s := new(Healthcheck)
|
|
s.params = ¶ms
|
|
s.log = params.Logger.Get()
|
|
|
|
lc.Append(fx.Hook{
|
|
OnStart: func(_ context.Context) error {
|
|
s.StartupTime = time.Now()
|
|
|
|
return nil
|
|
},
|
|
OnStop: func(_ context.Context) error {
|
|
return nil
|
|
},
|
|
})
|
|
|
|
return s, nil
|
|
}
|
|
|
|
// Healthcheck returns the current health status of the
|
|
// application.
|
|
func (s *Healthcheck) Healthcheck() *Response {
|
|
resp := &Response{
|
|
Status: "ok",
|
|
Now: time.Now().UTC().Format(time.RFC3339Nano),
|
|
UptimeSeconds: int64(s.uptime().Seconds()),
|
|
UptimeHuman: s.uptime().String(),
|
|
Appname: s.params.Globals.Appname,
|
|
Version: s.params.Globals.Version,
|
|
}
|
|
|
|
return resp
|
|
}
|
|
|
|
// Response contains the JSON-serialised health status.
|
|
type Response struct {
|
|
Status string `json:"status"`
|
|
Now string `json:"now"`
|
|
UptimeSeconds int64 `json:"uptimeSeconds"`
|
|
UptimeHuman string `json:"uptimeHuman"`
|
|
Version string `json:"version"`
|
|
Appname string `json:"appname"`
|
|
}
|
|
|
|
func (s *Healthcheck) uptime() time.Duration {
|
|
return time.Since(s.StartupTime)
|
|
}
|