github.com/grafana/pyroscope@v1.18.0/pkg/querybackend/concurrency.go (about) 1 package querybackend 2 3 import ( 4 "context" 5 "fmt" 6 7 "github.com/go-kit/log" 8 "github.com/go-kit/log/level" 9 "github.com/platinummonkey/go-concurrency-limits/core" 10 gclGrpc "github.com/platinummonkey/go-concurrency-limits/grpc" 11 "github.com/platinummonkey/go-concurrency-limits/limit" 12 "github.com/platinummonkey/go-concurrency-limits/limiter" 13 "github.com/platinummonkey/go-concurrency-limits/strategy" 14 "google.golang.org/grpc" 15 "google.golang.org/grpc/codes" 16 ) 17 18 const ( 19 // gradient2 limit 20 minLimit = 50 21 maxLimit = 100 22 initialLimit = 50 23 smoothing = 0.2 24 longWindow = 600 25 26 // limiter 27 minWindowTime = 1 28 maxWindowTime = 1000 29 minRTTThreshold = 1e6 30 windowSize = 100 31 ) 32 33 var ( 34 queueSizeFn = func(limit int) int { 35 return 10 36 } 37 ) 38 39 func CreateConcurrencyInterceptor(logger log.Logger) (grpc.UnaryServerInterceptor, error) { 40 gclLog := newGclLogger(logger) 41 // TODO(aleks-p): Implement metric registry 42 serverLimit, err := limit.NewGradient2Limit("query-backend-concurrency-limit", minLimit, maxLimit, initialLimit, queueSizeFn, smoothing, longWindow, gclLog, nil) 43 if err != nil { 44 return nil, err 45 } 46 47 serverLimiter, err := limiter.NewDefaultLimiter(serverLimit, minWindowTime, maxWindowTime, minRTTThreshold, windowSize, strategy.NewSimpleStrategy(initialLimit), gclLog, nil) 48 if err != nil { 49 return nil, err 50 } 51 52 options := []gclGrpc.InterceptorOption{ 53 gclGrpc.WithName("gcl-interceptor"), 54 gclGrpc.WithLimiter(serverLimiter), 55 gclGrpc.WithLimitExceededResponseClassifier(func(ctx context.Context, method string, req interface{}, l core.Limiter) (interface{}, codes.Code, error) { 56 return nil, codes.ResourceExhausted, fmt.Errorf("concurrency limit exceeded") 57 })} 58 gclInterceptor := gclGrpc.UnaryServerInterceptor(options...) 59 60 return gclInterceptor, err 61 } 62 63 type gclLogger struct { 64 logger log.Logger 65 } 66 67 func (g gclLogger) Debugf(msg string, params ...interface{}) { 68 level.Debug(g.logger).Log("msg", fmt.Sprintf(msg, params...)) 69 } 70 71 func (g gclLogger) IsDebugEnabled() bool { 72 return true 73 } 74 75 func newGclLogger(logger log.Logger) *gclLogger { 76 return &gclLogger{logger: logger} 77 }