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 }