github.com/grafana/pyroscope@v1.18.0/pkg/distributor/rate_strategy.go (about) 1 // SPDX-License-Identifier: AGPL-3.0-only 2 // Provenance-includes-location: https://github.com/cortexproject/cortex/blob/master/pkg/distributor/ingestion_rate_strategy.go 3 // Provenance-includes-license: Apache-2.0 4 // Provenance-includes-copyright: The Cortex Authors. 5 6 package distributor 7 8 import ( 9 "golang.org/x/time/rate" 10 11 "github.com/grafana/dskit/limiter" 12 ) 13 14 // ReadLifecycler represents the read interface to the lifecycler. 15 type ReadLifecycler interface { 16 HealthyInstancesCount() int 17 } 18 19 type globalStrategy struct { 20 baseStrategy limiter.RateLimiterStrategy 21 ring ReadLifecycler 22 } 23 24 // newGlobalRateStrategy represents a ingestion rate limiting strategy that enforces the rate 25 // limiting globally, configuring a per-distributor local rate limiter as "ingestion_rate / N", 26 // where N is the number of distributor replicas (it's automatically adjusted if the 27 // number of replicas change). 28 // 29 // The global strategy requires the distributors to form their own ring, which 30 // is used to keep track of the current number of healthy distributor replicas. 31 func newGlobalRateStrategy(baseStrategy limiter.RateLimiterStrategy, ring ReadLifecycler) limiter.RateLimiterStrategy { 32 return &globalStrategy{ 33 baseStrategy: baseStrategy, 34 ring: ring, 35 } 36 } 37 38 func (s *globalStrategy) Limit(tenantID string) float64 { 39 numDistributors := s.ring.HealthyInstancesCount() 40 41 limit := s.baseStrategy.Limit(tenantID) 42 43 if numDistributors == 0 || limit == float64(rate.Inf) { 44 return limit 45 } 46 return limit / float64(numDistributors) 47 } 48 49 func (s *globalStrategy) Burst(tenantID string) int { 50 // The meaning of burst doesn't change for the global strategy, in order 51 // to keep it easier to understand for users / operators. 52 return s.baseStrategy.Burst(tenantID) 53 } 54 55 type ingestionRateStrategy struct { 56 limits Limits 57 } 58 59 func newIngestionRateStrategy(limits Limits) limiter.RateLimiterStrategy { 60 return &ingestionRateStrategy{ 61 limits: limits, 62 } 63 } 64 65 func (s *ingestionRateStrategy) Limit(tenantID string) float64 { 66 return s.limits.IngestionRateBytes(tenantID) 67 } 68 69 func (s *ingestionRateStrategy) Burst(tenantID string) int { 70 return s.limits.IngestionBurstSizeBytes(tenantID) 71 } 72 73 type infiniteStrategy struct{} 74 75 func newInfiniteRateStrategy() limiter.RateLimiterStrategy { 76 return &infiniteStrategy{} 77 } 78 79 func (s *infiniteStrategy) Limit(tenantID string) float64 { 80 return float64(rate.Inf) 81 } 82 83 func (s *infiniteStrategy) Burst(tenantID string) int { 84 // Burst is ignored when limit = rate.Inf 85 return 0 86 }