Skip to content

Commit 13359aa

Browse files
authored
chore: drop github per user rate limit tracking (coder#12286)
* chore: drop github per user rate limit tracking Rate limits for authenticated requests are per user. This would be an excessive number of prometheus labels, so we only track the unauthorized limit.
1 parent 90db668 commit 13359aa

File tree

3 files changed

+28
-19
lines changed

3 files changed

+28
-19
lines changed

coderd/promoauth/github.go

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,32 @@ type rateLimits struct {
1616
Resource string
1717
}
1818

19-
// githubRateLimits checks the returned response headers and
19+
// githubRateLimits returns rate limit information from a GitHub response.
20+
// GitHub rate limits are on a per-user basis, and tracking each user as
21+
// a prometheus label might be too much. So only track rate limits for
22+
// unauthorized responses.
23+
//
24+
// Unauthorized responses have a much stricter rate limit of 60 per hour.
25+
// Tracking this is vital to ensure we do not hit the limit.
2026
func githubRateLimits(resp *http.Response, err error) (rateLimits, bool) {
2127
if err != nil || resp == nil {
2228
return rateLimits{}, false
2329
}
2430

31+
// Only track 401 responses which indicates we are using the 60 per hour
32+
// rate limit.
33+
if resp.StatusCode != http.StatusUnauthorized {
34+
return rateLimits{}, false
35+
}
36+
2537
p := headerParser{header: resp.Header}
2638
// See
2739
// https://docs.github.com/en/rest/using-the-rest-api/rate-limits-for-the-rest-api?apiVersion=2022-11-28#checking-the-status-of-your-rate-limit
2840
limits := rateLimits{
2941
Limit: p.int("x-ratelimit-limit"),
3042
Remaining: p.int("x-ratelimit-remaining"),
3143
Used: p.int("x-ratelimit-used"),
32-
Resource: p.string("x-ratelimit-resource"),
44+
Resource: p.string("x-ratelimit-resource") + "-unauthorized",
3345
}
3446

3547
if limits.Limit == 0 &&
@@ -50,18 +62,6 @@ func githubRateLimits(resp *http.Response, err error) (rateLimits, bool) {
5062
}
5163
limits.Reset = resetAt
5264

53-
// Unauthorized requests have their own rate limit, so we should
54-
// track them separately.
55-
if resp.StatusCode == http.StatusUnauthorized {
56-
limits.Resource += "-unauthorized"
57-
}
58-
59-
// A 401 or 429 means too many requests. This might mess up the
60-
// "resource" string because we could hit the unauthorized limit,
61-
// and we do not want that to override the authorized one.
62-
// However, in testing, it seems a 401 is always a 401, even if
63-
// the limit is hit.
64-
6565
if len(p.errors) > 0 {
6666
// If we are missing any headers, then do not try and guess
6767
// what the rate limits are.

coderd/promoauth/oauth2_test.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,15 @@ func TestGithubRateLimits(t *testing.T) {
179179
}
180180
}
181181

182+
// Ignore the well known, required for setup
183+
if !strings.Contains(r.URL.String(), ".well-known") {
184+
// GitHub rate limits only are instrumented for unauthenticated calls. So emulate
185+
// that here. We cannot actually use invalid credentials because the fake IDP
186+
// will throw a test error, as it only expects things to work. And we want to use
187+
// a real idp to emulate the right http calls to be instrumented.
188+
rw.WriteHeader(http.StatusUnauthorized)
189+
return
190+
}
182191
next.ServeHTTP(rw, r)
183192
})
184193
}))
@@ -195,13 +204,13 @@ func TestGithubRateLimits(t *testing.T) {
195204
// Do a single oauth2 call
196205
ctx := testutil.Context(t, testutil.WaitShort)
197206
ctx = context.WithValue(ctx, oauth2.HTTPClient, idp.HTTPClient(nil))
198-
_, err := cfg.Exchange(ctx, idp.CreateAuthCode(t, "foo"))
199-
require.NoError(t, err)
207+
_, err := cfg.Exchange(ctx, "invalid")
208+
require.Error(t, err, "expected unauthorized exchange")
200209

201210
// Verify
202211
labels := prometheus.Labels{
203212
"name": "test",
204-
"resource": "core",
213+
"resource": "core-unauthorized",
205214
}
206215
pass := true
207216
if !c.ExpectNoMetrics {

scripts/metricsdocgen/metrics

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ coderd_oauth2_external_requests_rate_limit_reset_in_seconds{name="primary-github
1212
coderd_oauth2_external_requests_rate_limit_reset_in_seconds{name="secondary-github",resource="core"} 121.82186601
1313
# HELP coderd_oauth2_external_requests_rate_limit_total The total number of allowed requests per interval.
1414
# TYPE coderd_oauth2_external_requests_rate_limit_total gauge
15-
coderd_oauth2_external_requests_rate_limit_total{name="primary-github",resource="core"} 5000
16-
coderd_oauth2_external_requests_rate_limit_total{name="secondary-github",resource="core"} 5000
15+
coderd_oauth2_external_requests_rate_limit_total{name="primary-github",resource="core-unauthorized"} 5000
16+
coderd_oauth2_external_requests_rate_limit_total{name="secondary-github",resource="core-unauthorized"} 5000
1717
# HELP coderd_oauth2_external_requests_rate_limit_used The number of requests made in this interval.
1818
# TYPE coderd_oauth2_external_requests_rate_limit_used gauge
1919
coderd_oauth2_external_requests_rate_limit_used{name="primary-github",resource="core"} 148

0 commit comments

Comments
 (0)