Skip to content

Commit

Permalink
health: add warming-up warnable
Browse files Browse the repository at this point in the history
Updates #4136

Creates and exposes a 'fake' warnable that persists for the first 5 seconds of lifetime of the backend. This is used to silence spurious warnings while the backend is starting up.
  • Loading branch information
agottardo committed Jun 20, 2024
1 parent 24976b5 commit e672be5
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 0 deletions.
12 changes: 12 additions & 0 deletions health/health.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ type Tracker struct {
derpMap *tailcfg.DERPMap // last DERP map from control, could be nil if never received one
lastMapRequestHeard time.Time // time we got a 200 from control for a MapRequest
ipnState string
ipnStateFirstSet time.Time // when ipnState was first set
ipnWantRunning bool
anyInterfaceUp opt.Bool // empty means unknown (assume true)
udp4Unbound bool
Expand Down Expand Up @@ -705,6 +706,12 @@ func (t *Tracker) SetIPNState(state string, wantRunning bool) {
t.mu.Lock()
defer t.mu.Unlock()
t.ipnState = state
if t.ipnStateFirstSet.IsZero() {
// The first time we see an IPNState getting set, it means the backend is starting up. We store this timestamp.
// We use it to silence some warnings that are expected during startup.
t.ipnStateFirstSet = time.Now()
t.setUnhealthyLocked(warmingUpWarnable, nil)
}
t.ipnWantRunning = wantRunning
t.selfCheckLocked()
}
Expand Down Expand Up @@ -858,6 +865,11 @@ var fakeErrForTesting = envknob.RegisterString("TS_DEBUG_FAKE_HEALTH_ERROR")
// updateBuiltinWarnablesLocked performs a number of checks on the state of the backend,
// and adds/removes Warnings from the Tracker as needed.
func (t *Tracker) updateBuiltinWarnablesLocked() {
if !t.ipnStateFirstSet.IsZero() && time.Now().After(t.ipnStateFirstSet.Add(5*time.Second)) {
// After more than 5 seconds after the first IPNState was set, we consider the backend to be warmed up.
t.setHealthyLocked(warmingUpWarnable)
}

if t.checkForUpdates {
if cv := t.latestVersion; cv != nil && !cv.RunningLatest && cv.LatestVersion != "" {
if cv.UrgentSecurityUpdate {
Expand Down
5 changes: 5 additions & 0 deletions health/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ func (w *Warnable) unhealthyState(ws *warningState) *UnhealthyState {
dependsOnWarnableCodes[i] = d.Code
}

// Here we tell the frontend that all Warnables depend on warmingUpWarnable. GUIs will silence all warnings until all
// their dependencies are healthy. This is a special case to prevent the GUI from showing a bunch of warnings when
// the backend is still warming up.
dependsOnWarnableCodes = append(dependsOnWarnableCodes, warmingUpWarnable.Code)

return &UnhealthyState{
WarnableCode: w.Code,
Severity: w.Severity,
Expand Down
7 changes: 7 additions & 0 deletions health/warnings.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,3 +212,10 @@ var controlHealthWarnable = Register(&Warnable{
return fmt.Sprintf("The coordination server is reporting an health issue: %v", args[ArgError])
},
})

var warmingUpWarnable = Register(&Warnable{
Code: "warming-up",
Title: "Tailscale is starting",
Severity: SeverityLow,
Text: StaticMessage("Tailscale is starting. Please wait."),
})

0 comments on commit e672be5

Please sign in to comment.