github.com/thanos-io/thanos@v0.32.5/pkg/info/info.go (about)

     1  // Copyright (c) The Thanos Authors.
     2  // Licensed under the Apache License 2.0.
     3  
     4  package info
     5  
     6  import (
     7  	"context"
     8  
     9  	"github.com/thanos-io/thanos/pkg/info/infopb"
    10  	"github.com/thanos-io/thanos/pkg/store/labelpb"
    11  	"google.golang.org/grpc"
    12  )
    13  
    14  // InfoServer implements the corresponding protobuf interface
    15  // to provide information on which APIs are exposed by the given
    16  // component.
    17  type InfoServer struct {
    18  	infopb.UnimplementedInfoServer
    19  
    20  	component string
    21  
    22  	getLabelSet           func() []labelpb.ZLabelSet
    23  	getStoreInfo          func() *infopb.StoreInfo
    24  	getExemplarsInfo      func() *infopb.ExemplarsInfo
    25  	getRulesInfo          func() *infopb.RulesInfo
    26  	getTargetsInfo        func() *infopb.TargetsInfo
    27  	getMetricMetadataInfo func() *infopb.MetricMetadataInfo
    28  	getQueryAPIInfo       func() *infopb.QueryAPIInfo
    29  }
    30  
    31  // NewInfoServer creates a new server instance for given component
    32  // and with the specified options.
    33  func NewInfoServer(
    34  	component string,
    35  	options ...ServerOptionFunc,
    36  ) *InfoServer {
    37  	srv := &InfoServer{
    38  		component: component,
    39  		// By default, do not return info for any API.
    40  		getLabelSet:           func() []labelpb.ZLabelSet { return nil },
    41  		getStoreInfo:          func() *infopb.StoreInfo { return nil },
    42  		getExemplarsInfo:      func() *infopb.ExemplarsInfo { return nil },
    43  		getRulesInfo:          func() *infopb.RulesInfo { return nil },
    44  		getTargetsInfo:        func() *infopb.TargetsInfo { return nil },
    45  		getMetricMetadataInfo: func() *infopb.MetricMetadataInfo { return nil },
    46  		getQueryAPIInfo:       func() *infopb.QueryAPIInfo { return nil },
    47  	}
    48  
    49  	for _, o := range options {
    50  		o(srv)
    51  	}
    52  
    53  	return srv
    54  }
    55  
    56  // ServerOptionFunc represents a functional option to configure info server.
    57  type ServerOptionFunc func(*InfoServer)
    58  
    59  // WithLabelSetFunc determines the function that should be executed to obtain
    60  // the label set information. If no function is provided, the default empty
    61  // label set is returned. Only the first function from the list is considered.
    62  func WithLabelSetFunc(getLabelSet ...func() []labelpb.ZLabelSet) ServerOptionFunc {
    63  	if len(getLabelSet) == 0 {
    64  		return func(s *InfoServer) {
    65  			s.getLabelSet = func() []labelpb.ZLabelSet { return []labelpb.ZLabelSet{} }
    66  		}
    67  	}
    68  
    69  	return func(s *InfoServer) {
    70  		s.getLabelSet = getLabelSet[0]
    71  	}
    72  }
    73  
    74  // WithStoreInfoFunc determines the function that should be executed to obtain
    75  // the store information. If no function is provided, the default empty
    76  // store info is returned. Only the first function from the list is considered.
    77  func WithStoreInfoFunc(getStoreInfo ...func() *infopb.StoreInfo) ServerOptionFunc {
    78  	if len(getStoreInfo) == 0 {
    79  		return func(s *InfoServer) {
    80  			s.getStoreInfo = func() *infopb.StoreInfo { return &infopb.StoreInfo{} }
    81  		}
    82  	}
    83  
    84  	return func(s *InfoServer) {
    85  		s.getStoreInfo = getStoreInfo[0]
    86  	}
    87  }
    88  
    89  // WithRulesInfoFunc determines the function that should be executed to obtain
    90  // the rules information. If no function is provided, the default empty
    91  // rules info is returned. Only the first function from the list is considered.
    92  func WithRulesInfoFunc(getRulesInfo ...func() *infopb.RulesInfo) ServerOptionFunc {
    93  	if len(getRulesInfo) == 0 {
    94  		return func(s *InfoServer) {
    95  			s.getRulesInfo = func() *infopb.RulesInfo { return &infopb.RulesInfo{} }
    96  		}
    97  	}
    98  
    99  	return func(s *InfoServer) {
   100  		s.getRulesInfo = getRulesInfo[0]
   101  	}
   102  }
   103  
   104  // WithExemplarsInfoFunc determines the function that should be executed to obtain
   105  // the exemplars information. If no function is provided, the default empty
   106  // exemplars info is returned. Only the first function from the list is considered.
   107  func WithExemplarsInfoFunc(getExemplarsInfo ...func() *infopb.ExemplarsInfo) ServerOptionFunc {
   108  	if len(getExemplarsInfo) == 0 {
   109  		return func(s *InfoServer) {
   110  			s.getExemplarsInfo = func() *infopb.ExemplarsInfo { return &infopb.ExemplarsInfo{} }
   111  		}
   112  	}
   113  
   114  	return func(s *InfoServer) {
   115  		s.getExemplarsInfo = getExemplarsInfo[0]
   116  	}
   117  }
   118  
   119  // WithTargetsInfoFunc determines the function that should be executed to obtain
   120  // the targets information. If no function is provided, the default empty
   121  // targets info is returned. Only the first function from the list is considered.
   122  func WithTargetsInfoFunc(getTargetsInfo ...func() *infopb.TargetsInfo) ServerOptionFunc {
   123  	if len(getTargetsInfo) == 0 {
   124  		return func(s *InfoServer) {
   125  			s.getTargetsInfo = func() *infopb.TargetsInfo { return &infopb.TargetsInfo{} }
   126  		}
   127  	}
   128  
   129  	return func(s *InfoServer) {
   130  		s.getTargetsInfo = getTargetsInfo[0]
   131  	}
   132  }
   133  
   134  // WithTargetsInfoFunc determines the function that should be executed to obtain
   135  // the targets information. If no function is provided, the default empty
   136  // targets info is returned. Only the first function from the list is considered.
   137  func WithMetricMetadataInfoFunc(getMetricMetadataInfo ...func() *infopb.MetricMetadataInfo) ServerOptionFunc {
   138  	if len(getMetricMetadataInfo) == 0 {
   139  		return func(s *InfoServer) {
   140  			s.getMetricMetadataInfo = func() *infopb.MetricMetadataInfo { return &infopb.MetricMetadataInfo{} }
   141  		}
   142  	}
   143  
   144  	return func(s *InfoServer) {
   145  		s.getMetricMetadataInfo = getMetricMetadataInfo[0]
   146  	}
   147  }
   148  
   149  // WithQueryAPIInfoFunc determines the function that should be executed to obtain
   150  // the query information. If no function is provided, the default empty
   151  // query info is returned. Only the first function from the list is considered.
   152  func WithQueryAPIInfoFunc(queryInfo ...func() *infopb.QueryAPIInfo) ServerOptionFunc {
   153  	if len(queryInfo) == 0 {
   154  		return func(s *InfoServer) {
   155  			s.getQueryAPIInfo = func() *infopb.QueryAPIInfo { return &infopb.QueryAPIInfo{} }
   156  		}
   157  	}
   158  
   159  	return func(s *InfoServer) {
   160  		s.getQueryAPIInfo = queryInfo[0]
   161  	}
   162  }
   163  
   164  // RegisterInfoServer registers the info server.
   165  func RegisterInfoServer(infoSrv infopb.InfoServer) func(*grpc.Server) {
   166  	return func(s *grpc.Server) {
   167  		infopb.RegisterInfoServer(s, infoSrv)
   168  	}
   169  }
   170  
   171  // Info returns the information about label set and available APIs exposed by the component.
   172  func (srv *InfoServer) Info(ctx context.Context, req *infopb.InfoRequest) (*infopb.InfoResponse, error) {
   173  	return &infopb.InfoResponse{
   174  		LabelSets:      srv.getLabelSet(),
   175  		ComponentType:  srv.component,
   176  		Store:          srv.getStoreInfo(),
   177  		Exemplars:      srv.getExemplarsInfo(),
   178  		Rules:          srv.getRulesInfo(),
   179  		Targets:        srv.getTargetsInfo(),
   180  		MetricMetadata: srv.getMetricMetadataInfo(),
   181  		Query:          srv.getQueryAPIInfo(),
   182  	}, nil
   183  }