github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/swarmkit/manager/metrics/collector.go (about)

     1  package metrics
     2  
     3  import (
     4  	"context"
     5  
     6  	"strings"
     7  
     8  	"github.com/docker/go-events"
     9  	metrics "github.com/docker/go-metrics"
    10  	"github.com/docker/swarmkit/api"
    11  	"github.com/docker/swarmkit/manager/state/store"
    12  )
    13  
    14  var (
    15  	ns = metrics.NewNamespace("swarm", "manager", nil)
    16  
    17  	// counts of the various objects in swarmkit
    18  	nodesMetric metrics.LabeledGauge
    19  	tasksMetric metrics.LabeledGauge
    20  
    21  	// none of these objects have state, so they're just regular gauges
    22  	servicesMetric metrics.Gauge
    23  	networksMetric metrics.Gauge
    24  	secretsMetric  metrics.Gauge
    25  	configsMetric  metrics.Gauge
    26  )
    27  
    28  func init() {
    29  	nodesMetric = ns.NewLabeledGauge("nodes", "The number of nodes", "", "state")
    30  	tasksMetric = ns.NewLabeledGauge("tasks", "The number of tasks in the cluster object store", metrics.Total, "state")
    31  	servicesMetric = ns.NewGauge("services", "The number of services in the cluster object store", metrics.Total)
    32  	networksMetric = ns.NewGauge("networks", "The number of networks in the cluster object store", metrics.Total)
    33  	secretsMetric = ns.NewGauge("secrets", "The number of secrets in the cluster object store", metrics.Total)
    34  	configsMetric = ns.NewGauge("configs", "The number of configs in the cluster object store", metrics.Total)
    35  
    36  	resetMetrics()
    37  
    38  	metrics.Register(ns)
    39  }
    40  
    41  // Collector collects swarmkit metrics
    42  type Collector struct {
    43  	store *store.MemoryStore
    44  
    45  	// stopChan signals to the state machine to stop running.
    46  	stopChan chan struct{}
    47  	// doneChan is closed when the state machine terminates.
    48  	doneChan chan struct{}
    49  }
    50  
    51  // NewCollector creates a new metrics collector
    52  func NewCollector(store *store.MemoryStore) *Collector {
    53  	return &Collector{
    54  		store:    store,
    55  		stopChan: make(chan struct{}),
    56  		doneChan: make(chan struct{}),
    57  	}
    58  }
    59  
    60  // Run contains the collector event loop
    61  func (c *Collector) Run(ctx context.Context) error {
    62  	defer close(c.doneChan)
    63  
    64  	watcher, cancel, err := store.ViewAndWatch(c.store, func(readTx store.ReadTx) error {
    65  		nodes, err := store.FindNodes(readTx, store.All)
    66  		if err != nil {
    67  			return err
    68  		}
    69  		tasks, err := store.FindTasks(readTx, store.All)
    70  		if err != nil {
    71  			return err
    72  		}
    73  		services, err := store.FindServices(readTx, store.All)
    74  		if err != nil {
    75  			return err
    76  		}
    77  		networks, err := store.FindNetworks(readTx, store.All)
    78  		if err != nil {
    79  			return err
    80  		}
    81  		secrets, err := store.FindSecrets(readTx, store.All)
    82  		if err != nil {
    83  			return err
    84  		}
    85  		configs, err := store.FindConfigs(readTx, store.All)
    86  		if err != nil {
    87  			return err
    88  		}
    89  
    90  		for _, obj := range nodes {
    91  			c.handleEvent(obj.EventCreate())
    92  		}
    93  		for _, obj := range tasks {
    94  			c.handleEvent(obj.EventCreate())
    95  		}
    96  		for _, obj := range services {
    97  			c.handleEvent(obj.EventCreate())
    98  		}
    99  		for _, obj := range networks {
   100  			c.handleEvent(obj.EventCreate())
   101  		}
   102  		for _, obj := range secrets {
   103  			c.handleEvent(obj.EventCreate())
   104  		}
   105  		for _, obj := range configs {
   106  			c.handleEvent(obj.EventCreate())
   107  		}
   108  
   109  		return nil
   110  	})
   111  	if err != nil {
   112  		return err
   113  	}
   114  	defer cancel()
   115  
   116  	for {
   117  		select {
   118  		case event := <-watcher:
   119  			c.handleEvent(event)
   120  		case <-c.stopChan:
   121  			return nil
   122  		}
   123  	}
   124  }
   125  
   126  // Stop stops the collector.
   127  func (c *Collector) Stop() {
   128  	close(c.stopChan)
   129  	<-c.doneChan
   130  
   131  	// Clean the metrics on exit.
   132  	resetMetrics()
   133  }
   134  
   135  // resetMetrics resets all metrics to their default (base) value
   136  func resetMetrics() {
   137  	for _, state := range api.NodeStatus_State_name {
   138  		nodesMetric.WithValues(strings.ToLower(state)).Set(0)
   139  	}
   140  	for _, state := range api.TaskState_name {
   141  		tasksMetric.WithValues(strings.ToLower(state)).Set(0)
   142  	}
   143  	servicesMetric.Set(0)
   144  	networksMetric.Set(0)
   145  	secretsMetric.Set(0)
   146  	configsMetric.Set(0)
   147  
   148  }
   149  
   150  // handleEvent handles a single incoming cluster event.
   151  func (c *Collector) handleEvent(event events.Event) {
   152  	switch event.(type) {
   153  	case api.EventNode:
   154  		c.handleNodeEvent(event)
   155  	case api.EventTask:
   156  		c.handleTaskEvent(event)
   157  	case api.EventService:
   158  		c.handleServiceEvent(event)
   159  	case api.EventNetwork:
   160  		c.handleNetworkEvent(event)
   161  	case api.EventSecret:
   162  		c.handleSecretsEvent(event)
   163  	case api.EventConfig:
   164  		c.handleConfigsEvent(event)
   165  	}
   166  }
   167  
   168  func (c *Collector) handleNodeEvent(event events.Event) {
   169  	var prevNode, newNode *api.Node
   170  
   171  	switch v := event.(type) {
   172  	case api.EventCreateNode:
   173  		prevNode, newNode = nil, v.Node
   174  	case api.EventUpdateNode:
   175  		prevNode, newNode = v.OldNode, v.Node
   176  	case api.EventDeleteNode:
   177  		prevNode, newNode = v.Node, nil
   178  	}
   179  
   180  	// Skip updates if nothing changed.
   181  	if prevNode != nil && newNode != nil && prevNode.Status.State == newNode.Status.State {
   182  		return
   183  	}
   184  
   185  	if prevNode != nil {
   186  		nodesMetric.WithValues(strings.ToLower(prevNode.Status.State.String())).Dec(1)
   187  	}
   188  	if newNode != nil {
   189  		nodesMetric.WithValues(strings.ToLower(newNode.Status.State.String())).Inc(1)
   190  	}
   191  }
   192  
   193  func (c *Collector) handleTaskEvent(event events.Event) {
   194  	var prevTask, newTask *api.Task
   195  
   196  	switch v := event.(type) {
   197  	case api.EventCreateTask:
   198  		prevTask, newTask = nil, v.Task
   199  	case api.EventUpdateTask:
   200  		prevTask, newTask = v.OldTask, v.Task
   201  	case api.EventDeleteTask:
   202  		prevTask, newTask = v.Task, nil
   203  	}
   204  
   205  	// Skip updates if nothing changed.
   206  	if prevTask != nil && newTask != nil && prevTask.Status.State == newTask.Status.State {
   207  		return
   208  	}
   209  
   210  	if prevTask != nil {
   211  		tasksMetric.WithValues(
   212  			strings.ToLower(prevTask.Status.State.String()),
   213  		).Dec(1)
   214  	}
   215  	if newTask != nil {
   216  		tasksMetric.WithValues(
   217  			strings.ToLower(newTask.Status.State.String()),
   218  		).Inc(1)
   219  	}
   220  }
   221  
   222  func (c *Collector) handleServiceEvent(event events.Event) {
   223  	switch event.(type) {
   224  	case api.EventCreateService:
   225  		servicesMetric.Inc(1)
   226  	case api.EventDeleteService:
   227  		servicesMetric.Dec(1)
   228  	}
   229  }
   230  
   231  func (c *Collector) handleNetworkEvent(event events.Event) {
   232  	switch event.(type) {
   233  	case api.EventCreateNetwork:
   234  		networksMetric.Inc(1)
   235  	case api.EventDeleteNetwork:
   236  		networksMetric.Dec(1)
   237  	}
   238  }
   239  
   240  func (c *Collector) handleSecretsEvent(event events.Event) {
   241  	switch event.(type) {
   242  	case api.EventCreateSecret:
   243  		secretsMetric.Inc(1)
   244  	case api.EventDeleteSecret:
   245  		secretsMetric.Dec(1)
   246  	}
   247  }
   248  
   249  func (c *Collector) handleConfigsEvent(event events.Event) {
   250  	switch event.(type) {
   251  	case api.EventCreateConfig:
   252  		configsMetric.Inc(1)
   253  	case api.EventDeleteConfig:
   254  		configsMetric.Dec(1)
   255  	}
   256  }