Add API time on GitOps errors to ease troubleshooting (#43000)

This would have helped some troubleshooting on customer workflows
failing due to long response times.
(We had a long running `spec/fleets` API request for customer-numa.)

Sample of logging after I added a `300s` sleep to
`/api/latest/fleet/config`:
```
[+] would've applied EULA
[+] would've applied certificate authorities
Error: applying fleet config: PATCH /api/latest/fleet/config: do request: Patch "https://localhost:8080/api/latest/fleet/config?dry_run=true&overwrite=true": stream error: stream ID 49; INTERNAL_ERROR; received from peer (API time: 1m40.002s)
```
Another sample error after bringing Fleet down during a GitOps run:
```
[+] would've applied 4 software packages for fleet Conditional access FTW
Error: applying software installers for fleet "Conditional access FTW": GET /api/latest/fleet/software/batch/395942cc-69c9-49f9-93d3-f1120e0b9e34: do request: Get "https://localhost:8080/api/latest/fleet/software/batch/395942cc-69c9-49f9-93d3-f1120e0b9e34?dry_run=true&fleet_name=Conditional+access+test+team&overwrite=true": dial tcp [::1]:8080: connect: connection refused (API time: 2ms)
```
This commit is contained in:
Lucas Manuel Rodriguez 2026-04-06 10:58:41 -03:00 committed by GitHub
parent 7ba762ebec
commit 34f9d9852c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 10 additions and 4 deletions

View file

@ -0,0 +1 @@
* Added "API time" to GitOps output on API errors.

View file

@ -2042,7 +2042,7 @@ spec:
_, err := RunAppNoChecks([]string{"apply", "-f", interval})
assert.Error(t, err)
require.Equal(t, expectedErrMsg, err.Error())
require.Contains(t, err.Error(), expectedErrMsg)
}
func TestApplyQueries(t *testing.T) {

View file

@ -18,7 +18,7 @@ func RunAppForTest(t *testing.T, args []string) string {
func RunAppCheckErr(t *testing.T, args []string, errorMsg string) string {
w, err := RunAppNoChecks(args)
require.Error(t, err)
require.Equal(t, errorMsg, err.Error())
require.Contains(t, err.Error(), errorMsg)
return w.String()
}

View file

@ -276,11 +276,16 @@ func (l *logRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
}
func (c *Client) authenticatedRequestWithQuery(params interface{}, verb string, path string, responseDest interface{}, query string) error {
start := time.Now()
response, err := c.AuthenticatedDo(verb, path, query, params)
if err != nil {
return fmt.Errorf("%s %s: %w", verb, path, err)
return fmt.Errorf("%s %s: %w (API time: %s)", verb, path, err, time.Since(start).Truncate(time.Millisecond))
}
return c.ParseResponse(verb, path, response, responseDest)
if err := c.ParseResponse(verb, path, response, responseDest); err != nil {
// ParseResponse already adds verb and path to the err.
return fmt.Errorf("%w (API time: %s)", err, time.Since(start).Truncate(time.Millisecond))
}
return nil
}
func (c *Client) authenticatedRequest(params interface{}, verb string, path string, responseDest interface{}) error {