in registry/handlers/app.go [871:1004]
func (app *App) RegisterHealthChecks(healthRegistries ...*health.Registry) error {
logger := dcontext.GetLogger(app)
if len(healthRegistries) > 1 {
return fmt.Errorf("RegisterHealthChecks called with more than one registry")
}
// Allow for dependency injection:
if len(healthRegistries) > 0 {
app.healthRegistry = healthRegistries[0]
} else {
app.healthRegistry = health.DefaultRegistry
}
app.registerShutdownFunc(
func(app *App, errCh chan error, l dlog.Logger) {
l.Info("closing healthchecks registry")
err := app.healthRegistry.Shutdown()
if err != nil {
err = fmt.Errorf("healthchecks registry shutdown: %w", err)
} else {
l.Info("healthchecks registry has been shut down")
}
errCh <- err
},
)
if app.Config.Health.StorageDriver.Enabled {
interval := app.Config.Health.StorageDriver.Interval
if interval == 0 {
interval = defaultCheckInterval
}
storageDriverCheck := func() error {
_, err := app.driver.Stat(app, "/")
if errors.As(err, new(storagedriver.PathNotFoundError)) {
err = nil // pass this through, backend is responding, but this path doesn't exist.
}
if err != nil {
logger.Errorf("storage driver health check: %v", err)
}
return err
}
logger.WithFields(
dlog.Fields{
"threshold": app.Config.Health.StorageDriver.Threshold,
"interval_s": interval.Seconds(),
},
).Info("configuring storage health check")
if app.Config.Health.StorageDriver.Threshold != 0 {
app.healthRegistry.RegisterPeriodicThresholdFunc("storagedriver_"+app.Config.Storage.Type(), interval, app.Config.Health.StorageDriver.Threshold, storageDriverCheck)
} else {
app.healthRegistry.RegisterPeriodicFunc("storagedriver_"+app.Config.Storage.Type(), interval, storageDriverCheck)
}
}
if app.Config.Health.Database.Enabled {
if !app.Config.Database.Enabled {
logger.Warn("ignoring database health checks settings as metadata database is not enabled")
} else {
interval := app.Config.Health.Database.Interval
if interval == 0 {
interval = defaultCheckInterval
}
timeout := app.Config.Health.Database.Timeout
if timeout == 0 {
timeout = defaultDBCheckTimeout
}
check := checks.DBChecker(app.Context, timeout, app.db)
logger.WithFields(
dlog.Fields{
"timeout": timeout.String(),
"interval_s": interval.Seconds(),
},
).Info("configuring database health check")
if app.Config.Health.Database.Threshold != 0 {
app.healthRegistry.RegisterPeriodicThresholdFunc("database_connection", interval, app.Config.Health.Database.Threshold, check)
} else {
app.healthRegistry.RegisterPeriodicFunc("database_connection", interval, check)
}
}
}
for _, fileChecker := range app.Config.Health.FileCheckers {
interval := fileChecker.Interval
if interval == 0 {
interval = defaultCheckInterval
}
dcontext.GetLogger(app).Infof("configuring file health check path=%s, interval=%d", fileChecker.File, interval/time.Second)
app.healthRegistry.Register(fileChecker.File, health.PeriodicChecker(checks.FileChecker(fileChecker.File), interval))
}
for _, httpChecker := range app.Config.Health.HTTPCheckers {
interval := httpChecker.Interval
if interval == 0 {
interval = defaultCheckInterval
}
statusCode := httpChecker.StatusCode
if statusCode == 0 {
statusCode = 200
}
checker := checks.HTTPChecker(httpChecker.URI, statusCode, httpChecker.Timeout, httpChecker.Headers)
if httpChecker.Threshold != 0 {
dcontext.GetLogger(app).Infof("configuring HTTP health check uri=%s, interval=%d, threshold=%d", httpChecker.URI, interval/time.Second, httpChecker.Threshold)
app.healthRegistry.Register(httpChecker.URI, health.PeriodicThresholdChecker(checker, interval, httpChecker.Threshold))
} else {
dcontext.GetLogger(app).Infof("configuring HTTP health check uri=%s, interval=%d", httpChecker.URI, interval/time.Second)
app.healthRegistry.Register(httpChecker.URI, health.PeriodicChecker(checker, interval))
}
}
for _, tcpChecker := range app.Config.Health.TCPCheckers {
interval := tcpChecker.Interval
if interval == 0 {
interval = defaultCheckInterval
}
checker := checks.TCPChecker(tcpChecker.Addr, tcpChecker.Timeout)
if tcpChecker.Threshold != 0 {
dcontext.GetLogger(app).Infof("configuring TCP health check addr=%s, interval=%d, threshold=%d", tcpChecker.Addr, interval/time.Second, tcpChecker.Threshold)
app.healthRegistry.Register(tcpChecker.Addr, health.PeriodicThresholdChecker(checker, interval, tcpChecker.Threshold))
} else {
dcontext.GetLogger(app).Infof("configuring TCP health check addr=%s, interval=%d", tcpChecker.Addr, interval/time.Second)
app.healthRegistry.Register(tcpChecker.Addr, health.PeriodicChecker(checker, interval))
}
}
return nil
}