mirror of
https://github.com/coder/coder.git
synced 2025-07-03 16:13:58 +00:00
Currently, importing `codersdk` just to interact with the API requires importing tailscale, which causes builds to fail unless manually using our fork.
65 lines
1.5 KiB
Go
65 lines
1.5 KiB
Go
package healthcheck
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"golang.org/x/exp/slices"
|
|
|
|
"github.com/coder/coder/v2/coderd/database"
|
|
"github.com/coder/coder/v2/coderd/healthcheck/health"
|
|
"github.com/coder/coder/v2/codersdk/healthsdk"
|
|
)
|
|
|
|
const (
|
|
DatabaseDefaultThreshold = 15 * time.Millisecond
|
|
)
|
|
|
|
type DatabaseReport healthsdk.DatabaseReport
|
|
|
|
type DatabaseReportOptions struct {
|
|
DB database.Store
|
|
Threshold time.Duration
|
|
|
|
Dismissed bool
|
|
}
|
|
|
|
func (r *DatabaseReport) Run(ctx context.Context, opts *DatabaseReportOptions) {
|
|
r.Warnings = []health.Message{}
|
|
r.Severity = health.SeverityOK
|
|
r.Dismissed = opts.Dismissed
|
|
|
|
r.ThresholdMS = opts.Threshold.Milliseconds()
|
|
if r.ThresholdMS == 0 {
|
|
r.ThresholdMS = DatabaseDefaultThreshold.Milliseconds()
|
|
}
|
|
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
|
|
defer cancel()
|
|
|
|
pingCount := 5
|
|
pings := make([]time.Duration, 0, pingCount)
|
|
// Ping 5 times and average the latency.
|
|
for i := 0; i < pingCount; i++ {
|
|
pong, err := opts.DB.Ping(ctx)
|
|
if err != nil {
|
|
r.Error = health.Errorf(health.CodeDatabasePingFailed, "ping database: %s", err)
|
|
r.Severity = health.SeverityError
|
|
|
|
return
|
|
}
|
|
pings = append(pings, pong)
|
|
}
|
|
slices.Sort(pings)
|
|
|
|
// Take the median ping.
|
|
latency := pings[pingCount/2]
|
|
r.Latency = latency.String()
|
|
r.LatencyMS = latency.Milliseconds()
|
|
if r.LatencyMS >= r.ThresholdMS {
|
|
r.Severity = health.SeverityWarning
|
|
r.Warnings = append(r.Warnings, health.Messagef(health.CodeDatabasePingSlow, "median database ping above threshold"))
|
|
}
|
|
r.Healthy = true
|
|
r.Reachable = true
|
|
}
|