Files
moby/daemon/internal/metrics/metrics.go
Sebastiaan van Stijn 1fd87e9fdf api/types/container: make ContainerState a concrete type
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-11-10 16:08:12 +01:00

136 lines
4.7 KiB
Go

package metrics
import (
"sync"
gometrics "github.com/docker/go-metrics"
"github.com/prometheus/client_golang/prometheus"
)
var (
metricsNS = gometrics.NewNamespace("engine", "daemon", nil)
// ContainerActions tracks the time taken to process container operations
ContainerActions = metricsNS.NewLabeledTimer("container_actions", "The number of seconds it takes to process each container action", "action")
// NetworkActions tracks the time taken to process network operations
NetworkActions = metricsNS.NewLabeledTimer("network_actions", "The number of seconds it takes to process each network action", "action")
// HostInfoFunctions tracks the time taken to gather host information
HostInfoFunctions = metricsNS.NewLabeledTimer("host_info_functions", "The number of seconds it takes to call functions gathering info about the host", "function")
ImageActions = metricsNS.NewLabeledTimer("image_actions", "The number of seconds it takes to process each image action", "action")
// EngineInfo provides information about the engine and its environment
EngineInfo = metricsNS.NewLabeledGauge("engine", "The information related to the engine and the OS it is running on", gometrics.Unit("info"),
"version",
"commit",
"architecture",
"graphdriver",
"kernel",
"os",
"os_type",
"os_version",
"daemon_id",
)
// EngineCPUs tracks the number of CPUs available to the engine
EngineCPUs = metricsNS.NewGauge("engine_cpus", "The number of cpus that the host system of the engine has", gometrics.Unit("cpus"))
// EngineMemory tracks the amount of memory available to the engine
EngineMemory = metricsNS.NewGauge("engine_memory", "The number of bytes of memory that the host system of the engine has", gometrics.Bytes)
// HealthChecksCounter tracks the total number of health checks
HealthChecksCounter = metricsNS.NewCounter("health_checks", "The total number of health checks")
// HealthChecksFailedCounter tracks the number of failed health checks
HealthChecksFailedCounter = metricsNS.NewCounter("health_checks_failed", "The total number of failed health checks")
// HealthCheckStartDuration tracks the time taken to prepare health checks
HealthCheckStartDuration = metricsNS.NewTimer("health_check_start_duration", "The number of seconds it takes to prepare to run health checks")
// StateCtr tracks container states
StateCtr = newStateCounter(metricsNS, metricsNS.NewDesc("container_states", "The count of containers in various states", gometrics.Unit("containers"), "state"))
// EventsCounter tracks the number of events logged
EventsCounter = metricsNS.NewCounter("events", "The number of events logged")
// EventSubscribers tracks the number of current subscribers to events
EventSubscribers = metricsNS.NewGauge("events_subscribers", "The number of current subscribers to events", gometrics.Total)
)
func init() {
for _, a := range []string{
"start",
"changes",
"commit",
"create",
"delete",
} {
ContainerActions.WithValues(a).Update(0)
}
gometrics.Register(metricsNS)
}
func StartTimer(t gometrics.Timer) func() {
return gometrics.StartTimer(t)
}
// StateCounter tracks container states
type StateCounter struct {
mu sync.RWMutex
states map[string]string
desc *prometheus.Desc
}
func newStateCounter(ns *gometrics.Namespace, desc *prometheus.Desc) *StateCounter {
c := &StateCounter{
states: make(map[string]string),
desc: desc,
}
ns.Add(c)
return c
}
// Get returns the count of containers in running, paused, and stopped states
func (ctr *StateCounter) Get() (running int, paused int, stopped int) {
ctr.mu.RLock()
defer ctr.mu.RUnlock()
// FIXME(thaJeztah): there's no "container.StateStopped"; should we align these states with actual states?
for _, state := range ctr.states {
switch state {
case "running":
running++
case "paused":
paused++
case "stopped":
stopped++
}
}
return running, paused, stopped
}
// Set updates the state for a container
func (ctr *StateCounter) Set(id, label string) {
ctr.mu.Lock()
defer ctr.mu.Unlock()
ctr.states[id] = label
}
// Delete removes a container's state
func (ctr *StateCounter) Delete(id string) {
ctr.mu.Lock()
defer ctr.mu.Unlock()
delete(ctr.states, id)
}
// Describe implements prometheus.Collector
func (ctr *StateCounter) Describe(ch chan<- *prometheus.Desc) {
ch <- ctr.desc
}
// Collect implements prometheus.Collector
func (ctr *StateCounter) Collect(ch chan<- prometheus.Metric) {
running, paused, stopped := ctr.Get()
ch <- prometheus.MustNewConstMetric(ctr.desc, prometheus.GaugeValue, float64(running), "running")
ch <- prometheus.MustNewConstMetric(ctr.desc, prometheus.GaugeValue, float64(paused), "paused")
ch <- prometheus.MustNewConstMetric(ctr.desc, prometheus.GaugeValue, float64(stopped), "stopped")
}