// SPDX-License-Identifier: GPL-3.0-or-later package docker_engine import ( "fmt" "github.com/netdata/netdata/go/go.d.plugin/pkg/prometheus" "github.com/netdata/netdata/go/go.d.plugin/pkg/stm" ) func isDockerEngineMetrics(pms prometheus.Series) bool { return pms.FindByName("engine_daemon_engine_info").Len() > 0 } func (de *DockerEngine) collect() (map[string]int64, error) { pms, err := de.prom.ScrapeSeries() if err != nil { return nil, err } if !isDockerEngineMetrics(pms) { return nil, fmt.Errorf("'%s' returned non docker engine metrics", de.URL) } mx := de.collectMetrics(pms) return stm.ToMap(mx), nil } func (de *DockerEngine) collectMetrics(pms prometheus.Series) metrics { var mx metrics collectHealthChecks(&mx, pms) collectContainerActions(&mx, pms) collectBuilderBuildsFails(&mx, pms) if hasContainerStates(pms) { de.hasContainerStates = true mx.Container.States = &containerStates{} collectContainerStates(&mx, pms) } if isSwarmManager(pms) { de.isSwarmManager = true mx.SwarmManager = &swarmManager{} collectSwarmManager(&mx, pms) } return mx } func isSwarmManager(pms prometheus.Series) bool { return pms.FindByName("swarm_node_manager").Max() == 1 } func hasContainerStates(pms prometheus.Series) bool { return pms.FindByName("engine_daemon_container_states_containers").Len() > 0 } func collectHealthChecks(mx *metrics, raw prometheus.Series) { v := raw.FindByName("engine_daemon_health_checks_failed_total").Max() mx.HealthChecks.Failed = v } func collectContainerActions(mx *metrics, raw prometheus.Series) { for _, metric := range raw.FindByName("engine_daemon_container_actions_seconds_count") { action := metric.Labels.Get("action") if action == "" { continue } v := metric.Value switch action { default: case "changes": mx.Container.Actions.Changes = v case "commit": mx.Container.Actions.Commit = v case "create": mx.Container.Actions.Create = v case "delete": mx.Container.Actions.Delete = v case "start": mx.Container.Actions.Start = v } } } func collectContainerStates(mx *metrics, raw prometheus.Series) { for _, metric := range raw.FindByName("engine_daemon_container_states_containers") { state := metric.Labels.Get("state") if state == "" { continue } v := metric.Value switch state { default: case "paused": mx.Container.States.Paused = v case "running": mx.Container.States.Running = v case "stopped": mx.Container.States.Stopped = v } } } func collectBuilderBuildsFails(mx *metrics, raw prometheus.Series) { for _, metric := range raw.FindByName("builder_builds_failed_total") { reason := metric.Labels.Get("reason") if reason == "" { continue } v := metric.Value switch reason { default: case "build_canceled": mx.Builder.FailsByReason.BuildCanceled = v case "build_target_not_reachable_error": mx.Builder.FailsByReason.BuildTargetNotReachableError = v case "command_not_supported_error": mx.Builder.FailsByReason.CommandNotSupportedError = v case "dockerfile_empty_error": mx.Builder.FailsByReason.DockerfileEmptyError = v case "dockerfile_syntax_error": mx.Builder.FailsByReason.DockerfileSyntaxError = v case "error_processing_commands_error": mx.Builder.FailsByReason.ErrorProcessingCommandsError = v case "missing_onbuild_arguments_error": mx.Builder.FailsByReason.MissingOnbuildArgumentsError = v case "unknown_instruction_error": mx.Builder.FailsByReason.UnknownInstructionError = v } } } func collectSwarmManager(mx *metrics, raw prometheus.Series) { v := raw.FindByName("swarm_manager_configs_total").Max() mx.SwarmManager.Configs = v v = raw.FindByName("swarm_manager_networks_total").Max() mx.SwarmManager.Networks = v v = raw.FindByName("swarm_manager_secrets_total").Max() mx.SwarmManager.Secrets = v v = raw.FindByName("swarm_manager_services_total").Max() mx.SwarmManager.Services = v v = raw.FindByName("swarm_manager_leader").Max() mx.SwarmManager.IsLeader = v for _, metric := range raw.FindByName("swarm_manager_nodes") { state := metric.Labels.Get("state") if state == "" { continue } v := metric.Value switch state { default: case "disconnected": mx.SwarmManager.Nodes.PerState.Disconnected = v case "down": mx.SwarmManager.Nodes.PerState.Down = v case "ready": mx.SwarmManager.Nodes.PerState.Ready = v case "unknown": mx.SwarmManager.Nodes.PerState.Unknown = v } mx.SwarmManager.Nodes.Total += v } for _, metric := range raw.FindByName("swarm_manager_tasks_total") { state := metric.Labels.Get("state") if state == "" { continue } v := metric.Value switch state { default: case "accepted": mx.SwarmManager.Tasks.PerState.Accepted = v case "assigned": mx.SwarmManager.Tasks.PerState.Assigned = v case "complete": mx.SwarmManager.Tasks.PerState.Complete = v case "failed": mx.SwarmManager.Tasks.PerState.Failed = v case "new": mx.SwarmManager.Tasks.PerState.New = v case "orphaned": mx.SwarmManager.Tasks.PerState.Orphaned = v case "pending": mx.SwarmManager.Tasks.PerState.Pending = v case "preparing": mx.SwarmManager.Tasks.PerState.Preparing = v case "ready": mx.SwarmManager.Tasks.PerState.Ready = v case "rejected": mx.SwarmManager.Tasks.PerState.Rejected = v case "remove": mx.SwarmManager.Tasks.PerState.Remove = v case "running": mx.SwarmManager.Tasks.PerState.Running = v case "shutdown": mx.SwarmManager.Tasks.PerState.Shutdown = v case "starting": mx.SwarmManager.Tasks.PerState.Starting = v } mx.SwarmManager.Tasks.Total += v } }