firehol/netdata

View on GitHub
src/go/plugin/go.d/modules/docker_engine/collect.go

Summary

Maintainability
A
1 hr
Test Coverage
// SPDX-License-Identifier: GPL-3.0-or-later

package docker_engine

import (
    "fmt"

    "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/prometheus"
    "github.com/netdata/netdata/go/plugins/plugin/go.d/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
    }
}