123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191 |
- package daemon // import "github.com/docker/docker/daemon"
- import (
- "context"
- "sync"
- "github.com/containerd/log"
- "github.com/docker/docker/errdefs"
- "github.com/docker/docker/pkg/plugingetter"
- "github.com/docker/docker/pkg/plugins"
- metrics "github.com/docker/go-metrics"
- "github.com/pkg/errors"
- "github.com/prometheus/client_golang/prometheus"
- )
- const metricsPluginType = "MetricsCollector"
- var (
- metricsNS = metrics.NewNamespace("engine", "daemon", nil)
- containerActions = metricsNS.NewLabeledTimer("container_actions", "The number of seconds it takes to process each container action", "action")
- networkActions = metricsNS.NewLabeledTimer("network_actions", "The number of seconds it takes to process each network action", "action")
- hostInfoFunctions = metricsNS.NewLabeledTimer("host_info_functions", "The number of seconds it takes to call functions gathering info about the host", "function")
- engineInfo = metricsNS.NewLabeledGauge("engine", "The information related to the engine and the OS it is running on", metrics.Unit("info"),
- "version",
- "commit",
- "architecture",
- "graphdriver",
- "kernel",
- "os",
- "os_type",
- "os_version",
- "daemon_id", // ID is a randomly generated unique identifier (e.g. UUID4)
- )
- engineCpus = metricsNS.NewGauge("engine_cpus", "The number of cpus that the host system of the engine has", metrics.Unit("cpus"))
- engineMemory = metricsNS.NewGauge("engine_memory", "The number of bytes of memory that the host system of the engine has", metrics.Bytes)
- healthChecksCounter = metricsNS.NewCounter("health_checks", "The total number of health checks")
- healthChecksFailedCounter = metricsNS.NewCounter("health_checks_failed", "The total number of failed health checks")
- healthCheckStartDuration = metricsNS.NewTimer("health_check_start_duration", "The number of seconds it takes to prepare to run health checks")
- stateCtr = newStateCounter(metricsNS, metricsNS.NewDesc("container_states", "The count of containers in various states", metrics.Unit("containers"), "state"))
- )
- func init() {
- for _, a := range []string{
- "start",
- "changes",
- "commit",
- "create",
- "delete",
- } {
- containerActions.WithValues(a).Update(0)
- }
- metrics.Register(metricsNS)
- }
- type stateCounter struct {
- mu sync.RWMutex
- states map[string]string
- desc *prometheus.Desc
- }
- func newStateCounter(ns *metrics.Namespace, desc *prometheus.Desc) *stateCounter {
- c := &stateCounter{
- states: make(map[string]string),
- desc: desc,
- }
- ns.Add(c)
- return c
- }
- func (ctr *stateCounter) get() (running int, paused int, stopped int) {
- ctr.mu.RLock()
- defer ctr.mu.RUnlock()
- states := map[string]int{
- "running": 0,
- "paused": 0,
- "stopped": 0,
- }
- for _, state := range ctr.states {
- states[state]++
- }
- return states["running"], states["paused"], states["stopped"]
- }
- func (ctr *stateCounter) set(id, label string) {
- ctr.mu.Lock()
- ctr.states[id] = label
- ctr.mu.Unlock()
- }
- func (ctr *stateCounter) del(id string) {
- ctr.mu.Lock()
- delete(ctr.states, id)
- ctr.mu.Unlock()
- }
- func (ctr *stateCounter) Describe(ch chan<- *prometheus.Desc) {
- ch <- ctr.desc
- }
- 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")
- }
- func (daemon *Daemon) cleanupMetricsPlugins() {
- ls := daemon.PluginStore.GetAllManagedPluginsByCap(metricsPluginType)
- var wg sync.WaitGroup
- wg.Add(len(ls))
- for _, plugin := range ls {
- p := plugin
- go func() {
- defer wg.Done()
- adapter, err := makePluginAdapter(p)
- if err != nil {
- log.G(context.TODO()).WithError(err).WithField("plugin", p.Name()).Error("Error creating metrics plugin adapter")
- return
- }
- if err := adapter.StopMetrics(); err != nil {
- log.G(context.TODO()).WithError(err).WithField("plugin", p.Name()).Error("Error stopping plugin metrics collection")
- }
- }()
- }
- wg.Wait()
- if daemon.metricsPluginListener != nil {
- daemon.metricsPluginListener.Close()
- }
- }
- type metricsPlugin interface {
- StartMetrics() error
- StopMetrics() error
- }
- func makePluginAdapter(p plugingetter.CompatPlugin) (metricsPlugin, error) {
- if pc, ok := p.(plugingetter.PluginWithV1Client); ok {
- return &metricsPluginAdapter{pc.Client(), p.Name()}, nil
- }
- pa, ok := p.(plugingetter.PluginAddr)
- if !ok {
- return nil, errdefs.System(errors.Errorf("got unknown plugin type %T", p))
- }
- if pa.Protocol() != plugins.ProtocolSchemeHTTPV1 {
- return nil, errors.Errorf("plugin protocol not supported: %s", pa.Protocol())
- }
- addr := pa.Addr()
- client, err := plugins.NewClientWithTimeout(addr.Network()+"://"+addr.String(), nil, pa.Timeout())
- if err != nil {
- return nil, errors.Wrap(err, "error creating metrics plugin client")
- }
- return &metricsPluginAdapter{client, p.Name()}, nil
- }
- type metricsPluginAdapter struct {
- c *plugins.Client
- name string
- }
- func (a *metricsPluginAdapter) StartMetrics() error {
- type metricsPluginResponse struct {
- Err string
- }
- var res metricsPluginResponse
- if err := a.c.Call(metricsPluginType+".StartMetrics", nil, &res); err != nil {
- return errors.Wrap(err, "could not start metrics plugin")
- }
- if res.Err != "" {
- return errors.New(res.Err)
- }
- return nil
- }
- func (a *metricsPluginAdapter) StopMetrics() error {
- if err := a.c.Call(metricsPluginType+".StopMetrics", nil, nil); err != nil {
- return errors.Wrap(err, "error stopping metrics collector")
- }
- return nil
- }
|