diff --git a/orbit/cmd/desktop/desktop.go b/orbit/cmd/desktop/desktop.go index 7c92d5ce08..72b9f97207 100644 --- a/orbit/cmd/desktop/desktop.go +++ b/orbit/cmd/desktop/desktop.go @@ -158,12 +158,13 @@ func main() { log.Fatal().Err(err).Msg("unable to initialize request client") } client.WithInvalidTokenRetry(func() string { + log.Debug().Msg("refetching token from disk for API retry") newToken, err := tokenReader.Read() if err != nil { - log.Error().Err(err).Msg("refetch token") + log.Error().Err(err).Msg("refetch token from disk for API retry") return "" } - log.Debug().Msg("successfully refetched the token from disk") + log.Debug().Msg("successfully refetched the token from disk for API retry") return newToken }) diff --git a/orbit/cmd/orbit/orbit.go b/orbit/cmd/orbit/orbit.go index b330e5bd47..3b91e700f9 100644 --- a/orbit/cmd/orbit/orbit.go +++ b/orbit/cmd/orbit/orbit.go @@ -786,6 +786,7 @@ func main() { // check again when the token will expire, which will happen // before the next rotation check rotationTicker.Reset(remain) + log.Debug().Msgf("token will expire soon, checking again in: %s", remain) } case <-remoteCheckTicker.C: diff --git a/server/service/device_client.go b/server/service/device_client.go index 55ce3a4c34..4532d21b34 100644 --- a/server/service/device_client.go +++ b/server/service/device_client.go @@ -12,6 +12,7 @@ import ( "github.com/fleetdm/fleet/v4/pkg/retry" "github.com/fleetdm/fleet/v4/server/fleet" "github.com/fleetdm/fleet/v4/server/ptr" + "github.com/rs/zerolog/log" ) // Device client is used consume the `device/...` endpoints and meant to be used by Fleet Desktop @@ -47,6 +48,7 @@ func NewDeviceClient(addr string, insecureSkipVerify bool, rootCA string, fleetC // ErrUnauthenticated. The client will call this function to get a fresh token // and retry if it returns a different, non-empty token. func (dc *DeviceClient) WithInvalidTokenRetry(fn func() string) { + log.Debug().Msg("setting invalid token retry hook") dc.invalidTokenRetryFunc = fn } @@ -55,7 +57,7 @@ func (dc *DeviceClient) WithInvalidTokenRetry(fn func() string) { // (the pathFmt is used as-is as path). It will retry if the request fails due // to an invalid token and the invalidTokenRetryFunc field is set. func (dc *DeviceClient) request(verb, pathFmt, token, query string, params interface{}, responseDest interface{}) error { - const maxAttempts = 3 + const maxAttempts = 4 var attempt int for { attempt++ @@ -67,11 +69,18 @@ func (dc *DeviceClient) request(verb, pathFmt, token, query string, params inter reqErr := dc.requestAttempt(verb, path, query, params, responseDest) if attempt >= maxAttempts || dc.invalidTokenRetryFunc == nil || token == "-" || !errors.Is(reqErr, ErrUnauthenticated) { // no retry possible, return the result + if reqErr != nil { + log.Debug().Msgf("not retrying API error; attempt=%d, hook set=%t, token unset=%t, error is auth=%t", + attempt, dc.invalidTokenRetryFunc != nil, token == "-", errors.Is(reqErr, ErrUnauthenticated)) + } return reqErr } - time.Sleep(time.Duration(attempt) * time.Second) + delay := time.Duration(attempt) * time.Second + log.Debug().Msgf("retrying API error in %s", delay) + time.Sleep(delay) newToken := dc.invalidTokenRetryFunc() + log.Debug().Msgf("retrying API error; token is different=%t", newToken != "" && newToken != token) if newToken != "" { token = newToken } diff --git a/server/service/device_client_test.go b/server/service/device_client_test.go index 4895b31062..3ef3e8f3f6 100644 --- a/server/service/device_client_test.go +++ b/server/service/device_client_test.go @@ -162,6 +162,6 @@ func TestDeviceClientRetryInvalidToken(t *testing.T) { _, err = client.DesktopSummary("bad") require.Error(t, err) require.ErrorIs(t, err, ErrUnauthenticated) - require.Equal(t, int64(3), callCounts.Load()) + require.Equal(t, int64(4), callCounts.Load()) }) }