// Package healthcheck provides health status reporting for the server. package healthcheck import ( "context" "log/slog" "time" "git.eeqj.de/sneak/chat/internal/config" "git.eeqj.de/sneak/chat/internal/db" "git.eeqj.de/sneak/chat/internal/globals" "git.eeqj.de/sneak/chat/internal/logger" "go.uber.org/fx" ) // Params defines the dependencies for creating a Healthcheck. type Params struct { fx.In Globals *globals.Globals Config *config.Config Logger *logger.Logger Database *db.Database } // Healthcheck tracks server uptime and provides health status. type Healthcheck struct { // StartupTime records when the server started. StartupTime time.Time log *slog.Logger params *Params } // New creates a new Healthcheck instance. func New( lifecycle fx.Lifecycle, params Params, ) (*Healthcheck, error) { hcheck := &Healthcheck{ //nolint:exhaustruct // StartupTime set in OnStart params: ¶ms, log: params.Logger.Get(), } lifecycle.Append(fx.Hook{ OnStart: func(_ context.Context) error { hcheck.StartupTime = time.Now() return nil }, OnStop: func(_ context.Context) error { return nil }, }) return hcheck, nil } // Response is the JSON response returned by the health endpoint. 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"` Maintenance bool `json:"maintenanceMode"` } // Healthcheck returns the current health status of the server. func (hcheck *Healthcheck) Healthcheck() *Response { return &Response{ Status: "ok", Now: time.Now().UTC().Format(time.RFC3339Nano), UptimeSeconds: int64(hcheck.uptime().Seconds()), UptimeHuman: hcheck.uptime().String(), Appname: hcheck.params.Globals.Appname, Version: hcheck.params.Globals.Version, Maintenance: hcheck.params.Config.MaintenanceMode, } } func (hcheck *Healthcheck) uptime() time.Duration { return time.Since(hcheck.StartupTime) }