prom.go 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. package prom
  2. import (
  3. "context"
  4. "net/http"
  5. "net/url"
  6. "github.com/kubecost/cost-model/pkg/util"
  7. prometheus "github.com/prometheus/client_golang/api"
  8. )
  9. // NewRateLimitedClient creates a prometheus client which limits the number of concurrent outbound
  10. // prometheus requests.
  11. func NewRateLimitedClient(config prometheus.Config, maxConcurrency int, username, password string) (prometheus.Client, error) {
  12. c, err := prometheus.NewClient(config)
  13. if err != nil {
  14. return nil, err
  15. }
  16. limiter := util.NewSemaphore(maxConcurrency)
  17. return &RateLimitedPrometheusClient{
  18. client: c,
  19. limiter: limiter,
  20. username: username,
  21. password: password,
  22. }, nil
  23. }
  24. // Creates a new prometheus client which limits the total number of concurrent outbound requests
  25. // allowed at a given moment.
  26. type RateLimitedPrometheusClient struct {
  27. client prometheus.Client
  28. limiter *util.Semaphore
  29. username string
  30. password string
  31. }
  32. // Passthrough to the prometheus client API
  33. func (rlpc *RateLimitedPrometheusClient) URL(ep string, args map[string]string) *url.URL {
  34. return rlpc.client.URL(ep, args)
  35. }
  36. // Rate limit and passthrough to prometheus client API
  37. func (rlpc *RateLimitedPrometheusClient) Do(ctx context.Context, req *http.Request) (*http.Response, []byte, prometheus.Warnings, error) {
  38. if rlpc.username != "" {
  39. req.SetBasicAuth(rlpc.username, rlpc.password)
  40. }
  41. rlpc.limiter.Acquire()
  42. defer rlpc.limiter.Return()
  43. return rlpc.client.Do(ctx, req)
  44. }