@@ -148,6 +148,14 @@ type Server struct {
148148
149149 // quit is used to notify that the server is to be closed.
150150 quit chan bool
151+
152+ // descs are metrics descriptions for use when the server's state
153+ // is collected by Prometheus.
154+ descs struct {
155+ has * prometheus.Desc
156+ wants * prometheus.Desc
157+ subclients * prometheus.Desc
158+ }
151159}
152160
153161type updater func (server * Server , retryNumber int ) (time.Duration , int )
@@ -473,6 +481,36 @@ func (server *Server) triggerElection(ctx context.Context) error {
473481 return nil
474482}
475483
484+ // New returns a new unconfigured server. parentAddr is the address of
485+ // a parent, pass the empty string to create a root server. This
486+ // function should be called only once, as it registers metrics.
487+ func New (ctx context.Context , id string , parentAddr string , leader election.Election , opts ... connection.Option ) (* Server , error ) {
488+ s , err := NewIntermediate (ctx , id , parentAddr , leader , opts ... )
489+ if err != nil {
490+ return nil , err
491+ }
492+
493+ return s , prometheus .Register (s )
494+ }
495+
496+ // Describe implements prometheus.Collector.
497+ func (server * Server ) Describe (ch chan <- * prometheus.Desc ) {
498+ ch <- server .descs .has
499+ ch <- server .descs .wants
500+ ch <- server .descs .subclients
501+ }
502+
503+ // Collect implements prometheus.Collector.
504+ func (server * Server ) Collect (ch chan <- prometheus.Metric ) {
505+ status := server .Status ()
506+
507+ for id , res := range status .Resources {
508+ ch <- prometheus .MustNewConstMetric (server .descs .has , prometheus .GaugeValue , res .SumHas , id )
509+ ch <- prometheus .MustNewConstMetric (server .descs .wants , prometheus .GaugeValue , res .SumWants , id )
510+ ch <- prometheus .MustNewConstMetric (server .descs .subclients , prometheus .GaugeValue , float64 (res .Count ), id )
511+ }
512+ }
513+
476514// NewIntermediate creates a server connected to the lower level server.
477515func NewIntermediate (ctx context.Context , id string , addr string , leader election.Election , opts ... connection.Option ) (* Server , error ) {
478516 var (
@@ -506,6 +544,28 @@ func NewIntermediate(ctx context.Context, id string, addr string, leader electio
506544 quit : make (chan bool ),
507545 }
508546
547+ const (
548+ namespace = "doorman"
549+ subsystem = "server"
550+ )
551+
552+ labelNames := []string {"resource" }
553+ server .descs .has = prometheus .NewDesc (
554+ prometheus .BuildFQName (namespace , subsystem , "has" ),
555+ "All capacity assigned to clients for a resource." ,
556+ labelNames , nil ,
557+ )
558+ server .descs .wants = prometheus .NewDesc (
559+ prometheus .BuildFQName (namespace , subsystem , "wants" ),
560+ "All capacity requested by clients for a resource." ,
561+ labelNames , nil ,
562+ )
563+ server .descs .subclients = prometheus .NewDesc (
564+ prometheus .BuildFQName (namespace , subsystem , "subclients" ),
565+ "Number of clients requesting this resource." ,
566+ labelNames , nil ,
567+ )
568+
509569 // For an intermediate server load the default config for "*"
510570 // resource. As for root server, this config will be loaded
511571 // from some external source..
@@ -524,11 +584,6 @@ func NewIntermediate(ctx context.Context, id string, addr string, leader electio
524584 return server , nil
525585}
526586
527- // New returns a new unconfigured server.
528- func New (ctx context.Context , id string , leader election.Election , opts ... connection.Option ) (* Server , error ) {
529- return NewIntermediate (ctx , id , "" , leader , opts ... )
530- }
531-
532587// run is the server's main loop. It takes care of requesting new resources,
533588// and managing ones already claimed. This is the only method that should be
534589// performing RPC.
0 commit comments