3343d234 |
package daemon
|
e4c03623 |
import ( |
0e8e8f0f |
"path/filepath" |
e4c03623 |
"sync"
|
0e8e8f0f |
"github.com/docker/docker/pkg/mount"
"github.com/docker/docker/pkg/plugingetter" |
62c1f0ef |
metrics "github.com/docker/go-metrics" |
0e8e8f0f |
"github.com/pkg/errors" |
e4c03623 |
"github.com/prometheus/client_golang/prometheus" |
1009e6a4 |
"github.com/sirupsen/logrus" |
e4c03623 |
) |
3343d234 |
|
0e8e8f0f |
const metricsPluginType = "MetricsCollector"
|
3343d234 |
var (
containerActions metrics.LabeledTimer
imageActions metrics.LabeledTimer
networkActions metrics.LabeledTimer |
a28b173a |
engineInfo metrics.LabeledGauge |
3343d234 |
engineCpus metrics.Gauge
engineMemory metrics.Gauge
healthChecksCounter metrics.Counter
healthChecksFailedCounter metrics.Counter |
e4c03623 |
stateCtr *stateCounter |
3343d234 |
)
func init() {
ns := metrics.NewNamespace("engine", "daemon", nil)
containerActions = ns.NewLabeledTimer("container_actions", "The number of seconds it takes to process each container action", "action")
for _, a := range []string{
"start",
"changes",
"commit",
"create",
"delete",
} {
containerActions.WithValues(a).Update(0)
} |
e4c03623 |
|
3343d234 |
networkActions = ns.NewLabeledTimer("network_actions", "The number of seconds it takes to process each network action", "action") |
a28b173a |
engineInfo = ns.NewLabeledGauge("engine", "The information related to the engine and the OS it is running on", metrics.Unit("info"), |
3343d234 |
"version",
"commit",
"architecture", |
a28b173a |
"graphdriver",
"kernel", "os",
"os_type",
"daemon_id", // ID is a randomly generated unique identifier (e.g. UUID4) |
3343d234 |
)
engineCpus = ns.NewGauge("engine_cpus", "The number of cpus that the host system of the engine has", metrics.Unit("cpus"))
engineMemory = ns.NewGauge("engine_memory", "The number of bytes of memory that the host system of the engine has", metrics.Bytes)
healthChecksCounter = ns.NewCounter("health_checks", "The total number of health checks")
healthChecksFailedCounter = ns.NewCounter("health_checks_failed", "The total number of failed health checks")
imageActions = ns.NewLabeledTimer("image_actions", "The number of seconds it takes to process each image action", "action") |
e4c03623 |
stateCtr = newStateCounter(ns.NewDesc("container_states", "The count of containers in various states", metrics.Unit("containers"), "state"))
ns.Add(stateCtr)
|
3343d234 |
metrics.Register(ns)
} |
e4c03623 |
type stateCounter struct {
mu sync.Mutex
states map[string]string
desc *prometheus.Desc
}
func newStateCounter(desc *prometheus.Desc) *stateCounter {
return &stateCounter{
states: make(map[string]string),
desc: desc,
}
}
func (ctr *stateCounter) get() (running int, paused int, stopped int) {
ctr.mu.Lock()
defer ctr.mu.Unlock()
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")
} |
0e8e8f0f |
func (d *Daemon) cleanupMetricsPlugins() {
ls := d.PluginStore.GetAllManagedPluginsByCap(metricsPluginType)
var wg sync.WaitGroup
wg.Add(len(ls))
|
9db2c624 |
for _, plugin := range ls {
p := plugin |
0e8e8f0f |
go func() {
defer wg.Done()
pluginStopMetricsCollection(p)
}()
}
wg.Wait()
if d.metricsPluginListener != nil {
d.metricsPluginListener.Close()
}
}
type metricsPlugin struct {
plugingetter.CompatPlugin
}
func (p metricsPlugin) sock() string {
return "metrics.sock"
}
func (p metricsPlugin) sockBase() string {
return filepath.Join(p.BasePath(), "run", "docker")
}
func pluginStartMetricsCollection(p plugingetter.CompatPlugin) error {
type metricsPluginResponse struct {
Err string
}
var res metricsPluginResponse
if err := p.Client().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 pluginStopMetricsCollection(p plugingetter.CompatPlugin) {
if err := p.Client().Call(metricsPluginType+".StopMetrics", nil, nil); err != nil {
logrus.WithError(err).WithField("name", p.Name()).Error("error stopping metrics collector")
}
mp := metricsPlugin{p}
sockPath := filepath.Join(mp.sockBase(), mp.sock())
if err := mount.Unmount(sockPath); err != nil {
if mounted, _ := mount.Mounted(sockPath); mounted {
logrus.WithError(err).WithField("name", p.Name()).WithField("socket", sockPath).Error("error unmounting metrics socket for plugin")
}
}
} |