Add metrics for GitHub API rate limit (#312)
This commit is contained in:
parent
2623140c9a
commit
4f3f2fb60d
|
|
@ -11,6 +11,7 @@ import (
|
||||||
|
|
||||||
"github.com/bradleyfalzon/ghinstallation"
|
"github.com/bradleyfalzon/ghinstallation"
|
||||||
"github.com/google/go-github/v33/github"
|
"github.com/google/go-github/v33/github"
|
||||||
|
"github.com/summerwind/actions-runner-controller/github/metrics"
|
||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -34,15 +35,9 @@ type Client struct {
|
||||||
|
|
||||||
// NewClient creates a Github Client
|
// NewClient creates a Github Client
|
||||||
func (c *Config) NewClient() (*Client, error) {
|
func (c *Config) NewClient() (*Client, error) {
|
||||||
var (
|
var transport http.RoundTripper
|
||||||
httpClient *http.Client
|
|
||||||
client *github.Client
|
|
||||||
)
|
|
||||||
githubBaseURL := "https://github.com/"
|
|
||||||
if len(c.Token) > 0 {
|
if len(c.Token) > 0 {
|
||||||
httpClient = oauth2.NewClient(context.Background(), oauth2.StaticTokenSource(
|
transport = oauth2.NewClient(context.Background(), oauth2.StaticTokenSource(&oauth2.Token{AccessToken: c.Token})).Transport
|
||||||
&oauth2.Token{AccessToken: c.Token},
|
|
||||||
))
|
|
||||||
} else {
|
} else {
|
||||||
tr, err := ghinstallation.NewKeyFromFile(http.DefaultTransport, c.AppID, c.AppInstallationID, c.AppPrivateKey)
|
tr, err := ghinstallation.NewKeyFromFile(http.DefaultTransport, c.AppID, c.AppInstallationID, c.AppPrivateKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -55,9 +50,13 @@ func (c *Config) NewClient() (*Client, error) {
|
||||||
}
|
}
|
||||||
tr.BaseURL = githubAPIURL
|
tr.BaseURL = githubAPIURL
|
||||||
}
|
}
|
||||||
httpClient = &http.Client{Transport: tr}
|
transport = tr
|
||||||
}
|
}
|
||||||
|
transport = metrics.Transport{Transport: transport}
|
||||||
|
httpClient := &http.Client{Transport: transport}
|
||||||
|
|
||||||
|
var client *github.Client
|
||||||
|
var githubBaseURL string
|
||||||
if len(c.EnterpriseURL) > 0 {
|
if len(c.EnterpriseURL) > 0 {
|
||||||
var err error
|
var err error
|
||||||
client, err = github.NewEnterpriseClient(c.EnterpriseURL, c.EnterpriseURL, httpClient)
|
client, err = github.NewEnterpriseClient(c.EnterpriseURL, c.EnterpriseURL, httpClient)
|
||||||
|
|
@ -67,6 +66,7 @@ func (c *Config) NewClient() (*Client, error) {
|
||||||
githubBaseURL = fmt.Sprintf("%s://%s%s", client.BaseURL.Scheme, client.BaseURL.Host, strings.TrimSuffix(client.BaseURL.Path, "api/v3/"))
|
githubBaseURL = fmt.Sprintf("%s://%s%s", client.BaseURL.Scheme, client.BaseURL.Host, strings.TrimSuffix(client.BaseURL.Path, "api/v3/"))
|
||||||
} else {
|
} else {
|
||||||
client = github.NewClient(httpClient)
|
client = github.NewClient(httpClient)
|
||||||
|
githubBaseURL = "https://github.com/"
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Client{
|
return &Client{
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
// Package metrics provides monitoring of the GitHub related metrics.
|
||||||
|
//
|
||||||
|
// This depends on the metrics exporter of kubebuilder.
|
||||||
|
// See https://book.kubebuilder.io/reference/metrics.html for details.
|
||||||
|
package metrics
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
|
"sigs.k8s.io/controller-runtime/pkg/metrics"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
metrics.Registry.MustRegister(metricRateLimit, metricRateLimitRemaining)
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
// https://docs.github.com/en/rest/overview/resources-in-the-rest-api#rate-limiting
|
||||||
|
metricRateLimit = prometheus.NewGauge(
|
||||||
|
prometheus.GaugeOpts{
|
||||||
|
Name: "github_rate_limit",
|
||||||
|
Help: "The maximum number of requests you're permitted to make per hour",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
metricRateLimitRemaining = prometheus.NewGauge(
|
||||||
|
prometheus.GaugeOpts{
|
||||||
|
Name: "github_rate_limit_remaining",
|
||||||
|
Help: "The number of requests remaining in the current rate limit window",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// https://docs.github.com/en/rest/overview/resources-in-the-rest-api#rate-limiting
|
||||||
|
headerRateLimit = "X-RateLimit-Limit"
|
||||||
|
headerRateLimitRemaining = "X-RateLimit-Remaining"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Transport wraps a transport with metrics monitoring
|
||||||
|
type Transport struct {
|
||||||
|
Transport http.RoundTripper
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t Transport) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||||
|
resp, err := t.Transport.RoundTrip(req)
|
||||||
|
if resp != nil {
|
||||||
|
parseResponse(resp)
|
||||||
|
}
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseResponse(resp *http.Response) {
|
||||||
|
rateLimit, err := strconv.Atoi(resp.Header.Get(headerRateLimit))
|
||||||
|
if err == nil {
|
||||||
|
metricRateLimit.Set(float64(rateLimit))
|
||||||
|
}
|
||||||
|
rateLimitRemaining, err := strconv.Atoi(resp.Header.Get(headerRateLimitRemaining))
|
||||||
|
if err == nil {
|
||||||
|
metricRateLimitRemaining.Set(float64(rateLimitRemaining))
|
||||||
|
}
|
||||||
|
}
|
||||||
1
go.mod
1
go.mod
|
|
@ -11,6 +11,7 @@ require (
|
||||||
github.com/kelseyhightower/envconfig v1.4.0
|
github.com/kelseyhightower/envconfig v1.4.0
|
||||||
github.com/onsi/ginkgo v1.8.0
|
github.com/onsi/ginkgo v1.8.0
|
||||||
github.com/onsi/gomega v1.5.0
|
github.com/onsi/gomega v1.5.0
|
||||||
|
github.com/prometheus/client_golang v0.9.2
|
||||||
github.com/stretchr/testify v1.4.0 // indirect
|
github.com/stretchr/testify v1.4.0 // indirect
|
||||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45
|
||||||
k8s.io/api v0.0.0-20190918155943-95b840bb6a1f
|
k8s.io/api v0.0.0-20190918155943-95b840bb6a1f
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue