mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
104 lines
2.3 KiB
Go
104 lines
2.3 KiB
Go
package metrics
|
|
|
|
import (
|
|
"context"
|
|
|
|
"strings"
|
|
|
|
metrics "github.com/docker/go-metrics"
|
|
"github.com/docker/swarmkit/api"
|
|
"github.com/docker/swarmkit/manager/state/store"
|
|
)
|
|
|
|
var (
|
|
ns = metrics.NewNamespace("swarm", "manager", nil)
|
|
nodesMetric metrics.LabeledGauge
|
|
)
|
|
|
|
func init() {
|
|
nodesMetric = ns.NewLabeledGauge("nodes", "The number of nodes", "", "state")
|
|
for _, state := range api.NodeStatus_State_name {
|
|
nodesMetric.WithValues(strings.ToLower(state)).Set(0)
|
|
}
|
|
metrics.Register(ns)
|
|
}
|
|
|
|
// Collector collects swarmkit metrics
|
|
type Collector struct {
|
|
store *store.MemoryStore
|
|
|
|
// stopChan signals to the state machine to stop running.
|
|
stopChan chan struct{}
|
|
// doneChan is closed when the state machine terminates.
|
|
doneChan chan struct{}
|
|
}
|
|
|
|
// NewCollector creates a new metrics collector
|
|
func NewCollector(store *store.MemoryStore) *Collector {
|
|
return &Collector{
|
|
store: store,
|
|
stopChan: make(chan struct{}),
|
|
doneChan: make(chan struct{}),
|
|
}
|
|
}
|
|
|
|
func (c *Collector) updateNodeState(prevNode, newNode *api.Node) {
|
|
// Skip updates if nothing changed.
|
|
if prevNode != nil && newNode != nil && prevNode.Status.State == newNode.Status.State {
|
|
return
|
|
}
|
|
|
|
if prevNode != nil {
|
|
nodesMetric.WithValues(strings.ToLower(prevNode.Status.State.String())).Dec(1)
|
|
}
|
|
if newNode != nil {
|
|
nodesMetric.WithValues(strings.ToLower(newNode.Status.State.String())).Inc(1)
|
|
}
|
|
}
|
|
|
|
// Run contains the collector event loop
|
|
func (c *Collector) Run(ctx context.Context) error {
|
|
defer close(c.doneChan)
|
|
|
|
watcher, cancel, err := store.ViewAndWatch(c.store, func(readTx store.ReadTx) error {
|
|
nodes, err := store.FindNodes(readTx, store.All)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
for _, node := range nodes {
|
|
c.updateNodeState(nil, node)
|
|
}
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer cancel()
|
|
|
|
for {
|
|
select {
|
|
case event := <-watcher:
|
|
switch v := event.(type) {
|
|
case api.EventCreateNode:
|
|
c.updateNodeState(nil, v.Node)
|
|
case api.EventUpdateNode:
|
|
c.updateNodeState(v.OldNode, v.Node)
|
|
case api.EventDeleteNode:
|
|
c.updateNodeState(v.Node, nil)
|
|
}
|
|
case <-c.stopChan:
|
|
return nil
|
|
}
|
|
}
|
|
}
|
|
|
|
// Stop stops the collector.
|
|
func (c *Collector) Stop() {
|
|
close(c.stopChan)
|
|
<-c.doneChan
|
|
|
|
// Clean the metrics on exit.
|
|
for _, state := range api.NodeStatus_State_name {
|
|
nodesMetric.WithValues(strings.ToLower(state)).Set(0)
|
|
}
|
|
}
|