github.com/muhammadn/cortex@v1.9.1-0.20220510110439-46bb7000d03d/pkg/ruler/client_pool.go (about) 1 package ruler 2 3 import ( 4 "time" 5 6 "github.com/go-kit/log" 7 "github.com/grafana/dskit/grpcclient" 8 "github.com/grafana/dskit/ring/client" 9 "github.com/grafana/dskit/services" 10 "github.com/pkg/errors" 11 "github.com/prometheus/client_golang/prometheus" 12 "github.com/prometheus/client_golang/prometheus/promauto" 13 "google.golang.org/grpc" 14 "google.golang.org/grpc/health/grpc_health_v1" 15 ) 16 17 // ClientsPool is the interface used to get the client from the pool for a specified address. 18 type ClientsPool interface { 19 services.Service 20 // GetClientFor returns the ruler client for the given address. 21 GetClientFor(addr string) (RulerClient, error) 22 } 23 24 type rulerClientsPool struct { 25 *client.Pool 26 } 27 28 func (p *rulerClientsPool) GetClientFor(addr string) (RulerClient, error) { 29 c, err := p.Pool.GetClientFor(addr) 30 if err != nil { 31 return nil, err 32 } 33 return c.(RulerClient), nil 34 } 35 36 func newRulerClientPool(clientCfg grpcclient.Config, logger log.Logger, reg prometheus.Registerer) ClientsPool { 37 // We prefer sane defaults instead of exposing further config options. 38 poolCfg := client.PoolConfig{ 39 CheckInterval: time.Minute, 40 HealthCheckEnabled: true, 41 HealthCheckTimeout: 10 * time.Second, 42 } 43 44 clientsCount := promauto.With(reg).NewGauge(prometheus.GaugeOpts{ 45 Name: "cortex_ruler_clients", 46 Help: "The current number of ruler clients in the pool.", 47 }) 48 49 return &rulerClientsPool{ 50 client.NewPool("ruler", poolCfg, nil, newRulerClientFactory(clientCfg, reg), clientsCount, logger), 51 } 52 } 53 54 func newRulerClientFactory(clientCfg grpcclient.Config, reg prometheus.Registerer) client.PoolFactory { 55 requestDuration := promauto.With(reg).NewHistogramVec(prometheus.HistogramOpts{ 56 Name: "cortex_ruler_client_request_duration_seconds", 57 Help: "Time spent executing requests to the ruler.", 58 Buckets: prometheus.ExponentialBuckets(0.008, 4, 7), 59 }, []string{"operation", "status_code"}) 60 61 return func(addr string) (client.PoolClient, error) { 62 return dialRulerClient(clientCfg, addr, requestDuration) 63 } 64 } 65 66 func dialRulerClient(clientCfg grpcclient.Config, addr string, requestDuration *prometheus.HistogramVec) (*rulerExtendedClient, error) { 67 opts, err := clientCfg.DialOption(grpcclient.Instrument(requestDuration)) 68 if err != nil { 69 return nil, err 70 } 71 72 conn, err := grpc.Dial(addr, opts...) 73 if err != nil { 74 return nil, errors.Wrapf(err, "failed to dial ruler %s", addr) 75 } 76 77 return &rulerExtendedClient{ 78 RulerClient: NewRulerClient(conn), 79 HealthClient: grpc_health_v1.NewHealthClient(conn), 80 conn: conn, 81 }, nil 82 } 83 84 type rulerExtendedClient struct { 85 RulerClient 86 grpc_health_v1.HealthClient 87 conn *grpc.ClientConn 88 } 89 90 func (c *rulerExtendedClient) Close() error { 91 return c.conn.Close() 92 } 93 94 func (c *rulerExtendedClient) String() string { 95 return c.RemoteAddress() 96 } 97 98 func (c *rulerExtendedClient) RemoteAddress() string { 99 return c.conn.Target() 100 }