in health.go [111:161]
func (c *Connection) healthCheck(connID uint32) {
defer close(c.healthCheckDone)
opts := c.opts.HealthChecks
ticker := c.timeTicker(opts.Interval)
defer ticker.Stop()
consecutiveFailures := 0
for {
select {
case <-ticker.C:
case <-c.healthCheckCtx.Done():
return
}
ctx, cancel := context.WithTimeout(c.healthCheckCtx, opts.Timeout)
err := c.ping(ctx)
cancel()
c.healthCheckHistory.add(err == nil)
if err == nil {
if c.log.Enabled(LogLevelDebug) {
c.log.Debug("Performed successful active health check.")
}
consecutiveFailures = 0
continue
}
// If the health check failed because the connection closed or health
// checks were stopped, we don't need to log or close the connection.
if GetSystemErrorCode(err) == ErrCodeCancelled || err == ErrInvalidConnectionState {
c.log.WithFields(ErrField(err)).Debug("Health checker stopped.")
return
}
consecutiveFailures++
c.log.WithFields(LogFields{
{"consecutiveFailures", consecutiveFailures},
ErrField(err),
{"failuresToClose", opts.FailuresToClose},
}...).Warn("Failed active health check.")
if consecutiveFailures >= opts.FailuresToClose {
c.close(LogFields{
{"reason", "health check failure"},
ErrField(err),
}...)
return
}
}
}