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  }