Skip to content

Commit 25e2e24

Browse files
authored
chore(gensupport): add retry invocation headers (#1577)
Adds invocation ID and attempt count to x-goog-api-client header for simple and resumable uploads. Note that this will also add this information to chunk upload requests for individual chunks for BQ and other APIs that do uploads using gensupport as well. Hopefully this isn't an issue. Similar to googleapis/google-cloud-go#6013
1 parent c02e08c commit 25e2e24

4 files changed

Lines changed: 29 additions & 1 deletion

File tree

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ go 1.15
55
require (
66
cloud.google.com/go/compute v1.7.0
77
github.com/google/go-cmp v0.5.8
8+
github.com/google/uuid v1.1.2
89
github.com/googleapis/enterprise-certificate-proxy v0.1.0
910
github.com/googleapis/gax-go/v2 v2.4.0
1011
go.opencensus.io v0.23.0

go.sum

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLe
160160
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
161161
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
162162
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
163+
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
163164
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
164165
github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8=
165166
github.com/googleapis/enterprise-certificate-proxy v0.1.0 h1:zO8WHNx/MYiAKJ3d5spxZXZE6KHmIQGQcAzwUzV7qQw=

internal/gensupport/resumable.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,12 @@ import (
1010
"fmt"
1111
"io"
1212
"net/http"
13+
"strings"
1314
"sync"
1415
"time"
16+
17+
"github.com/google/uuid"
18+
"google.golang.org/api/internal"
1519
)
1620

1721
// ResumableUpload is used by the generated APIs to provide resumable uploads.
@@ -38,6 +42,11 @@ type ResumableUpload struct {
3842
// ChunkRetryDeadline configures the per-chunk deadline after which no further
3943
// retries should happen.
4044
ChunkRetryDeadline time.Duration
45+
46+
// Track current request invocation ID and attempt count for retry metric
47+
// headers.
48+
invocationID string
49+
attempts int
4150
}
4251

4352
// Progress returns the number of bytes uploaded at this point.
@@ -72,6 +81,10 @@ func (rx *ResumableUpload) doUploadRequest(ctx context.Context, data io.Reader,
7281
req.Header.Set("Content-Type", rx.MediaType)
7382
req.Header.Set("User-Agent", rx.UserAgent)
7483

84+
baseXGoogHeader := "gl-go/" + GoVersion() + " gdcl/" + internal.Version
85+
invocationHeader := fmt.Sprintf("gccl-invocation-id/%s gccl-attempt-count/%d", rx.invocationID, rx.attempts)
86+
req.Header.Set("X-Goog-Api-Client", strings.Join([]string{baseXGoogHeader, invocationHeader}, " "))
87+
7588
// Google's upload endpoint uses status code 308 for a
7689
// different purpose than the "308 Permanent Redirect"
7790
// since-standardized in RFC 7238. Because of the conflict in
@@ -178,9 +191,11 @@ func (rx *ResumableUpload) Upload(ctx context.Context) (resp *http.Response, err
178191
for {
179192
var pause time.Duration
180193

181-
// Each chunk gets its own initialized-at-zero backoff.
194+
// Each chunk gets its own initialized-at-zero backoff and invocation ID.
182195
bo := rx.Retry.backoff()
183196
quitAfter := time.After(retryDeadline)
197+
rx.attempts = 1
198+
rx.invocationID = uuid.New().String()
184199

185200
// Retry loop for a single chunk.
186201
for {
@@ -223,6 +238,7 @@ func (rx *ResumableUpload) Upload(ctx context.Context) (resp *http.Response, err
223238
break
224239
}
225240

241+
rx.attempts++
226242
pause = bo.Pause()
227243
if resp != nil && resp.Body != nil {
228244
resp.Body.Close()

internal/gensupport/send.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,12 @@ import (
88
"context"
99
"encoding/json"
1010
"errors"
11+
"fmt"
1112
"net/http"
13+
"strings"
1214
"time"
1315

16+
"github.com/google/uuid"
1417
"github.com/googleapis/gax-go/v2"
1518
)
1619

@@ -71,6 +74,9 @@ func sendAndRetry(ctx context.Context, client *http.Client, req *http.Request, r
7174

7275
var resp *http.Response
7376
var err error
77+
attempts := 1
78+
invocationID := uuid.New().String()
79+
baseXGoogHeader := req.Header.Get("X-Goog-Api-Client")
7480

7581
// Loop to retry the request, up to the context deadline.
7682
var pause time.Duration
@@ -109,6 +115,9 @@ func sendAndRetry(ctx context.Context, client *http.Client, req *http.Request, r
109115
}
110116
return resp, err
111117
}
118+
invocationHeader := fmt.Sprintf("gccl-invocation-id/%s gccl-attempt-count/%d", invocationID, attempts)
119+
xGoogHeader := strings.Join([]string{invocationHeader, baseXGoogHeader}, " ")
120+
req.Header.Set("X-Goog-Api-Client", xGoogHeader)
112121

113122
resp, err = client.Do(req.WithContext(ctx))
114123

@@ -123,6 +132,7 @@ func sendAndRetry(ctx context.Context, client *http.Client, req *http.Request, r
123132
if req.GetBody == nil || !errorFunc(status, err) {
124133
break
125134
}
135+
attempts++
126136
var errBody error
127137
req.Body, errBody = req.GetBody()
128138
if errBody != nil {

0 commit comments

Comments
 (0)