summaryrefslogtreecommitdiffstats
path: root/src/go/collectors/go.d.plugin/modules/k8s_state/charts.go
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/go/collectors/go.d.plugin/modules/k8s_state/charts.go785
1 files changed, 785 insertions, 0 deletions
diff --git a/src/go/collectors/go.d.plugin/modules/k8s_state/charts.go b/src/go/collectors/go.d.plugin/modules/k8s_state/charts.go
new file mode 100644
index 000000000..0cec12512
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/k8s_state/charts.go
@@ -0,0 +1,785 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package k8s_state
+
+import (
+ "fmt"
+ "regexp"
+ "strings"
+
+ "github.com/netdata/netdata/go/go.d.plugin/agent/module"
+)
+
+// NETDATA_CHART_PRIO_CGROUPS_CONTAINERS 40000
+const prioDiscoveryDiscovererState = 50999
+
+const (
+ prioNodeAllocatableCPURequestsUtil = 50100 + iota
+ prioNodeAllocatableCPURequestsUsed
+ prioNodeAllocatableCPULimitsUtil
+ prioNodeAllocatableCPULimitsUsed
+ prioNodeAllocatableMemRequestsUtil
+ prioNodeAllocatableMemRequestsUsed
+ prioNodeAllocatableMemLimitsUtil
+ prioNodeAllocatableMemLimitsUsed
+ prioNodeAllocatablePodsUtil
+ prioNodeAllocatablePodsUsage
+ prioNodeConditions
+ prioNodeSchedulability
+ prioNodePodsReadiness
+ prioNodePodsReadinessState
+ prioNodePodsCondition
+ prioNodePodsPhase
+ prioNodeContainersCount
+ prioNodeContainersState
+ prioNodeInitContainersState
+ prioNodeAge
+)
+
+const (
+ prioPodCPURequestsUsed = 50300 + iota
+ prioPodCPULimitsUsed
+ prioPodMemRequestsUsed
+ prioPodMemLimitsUsed
+ prioPodCondition
+ prioPodPhase
+ prioPodAge
+ prioPodContainersCount
+ prioPodContainersState
+ prioPodInitContainersState
+ prioPodContainerReadinessState
+ prioPodContainerRestarts
+ prioPodContainerState
+ prioPodContainerWaitingStateReason
+ prioPodContainerTerminatedStateReason
+)
+
+const (
+ labelKeyPrefix = "k8s_"
+ //labelKeyLabelPrefix = labelKeyPrefix + "label_"
+ //labelKeyAnnotationPrefix = labelKeyPrefix + "annotation_"
+ labelKeyClusterID = labelKeyPrefix + "cluster_id"
+ labelKeyClusterName = labelKeyPrefix + "cluster_name"
+ labelKeyNamespace = labelKeyPrefix + "namespace"
+ labelKeyKind = labelKeyPrefix + "kind"
+ labelKeyPodName = labelKeyPrefix + "pod_name"
+ labelKeyNodeName = labelKeyPrefix + "node_name"
+ labelKeyPodUID = labelKeyPrefix + "pod_uid"
+ labelKeyControllerKind = labelKeyPrefix + "controller_kind"
+ labelKeyControllerName = labelKeyPrefix + "controller_name"
+ labelKeyContainerName = labelKeyPrefix + "container_name"
+ labelKeyContainerID = labelKeyPrefix + "container_id"
+ labelKeyQoSClass = labelKeyPrefix + "qos_class"
+)
+
+var baseCharts = module.Charts{
+ discoveryStatusChart.Copy(),
+}
+
+var nodeChartsTmpl = module.Charts{
+ nodeAllocatableCPURequestsUtilChartTmpl.Copy(),
+ nodeAllocatableCPURequestsUsedChartTmpl.Copy(),
+ nodeAllocatableCPULimitsUtilChartTmpl.Copy(),
+ nodeAllocatableCPULimitsUsedChartTmpl.Copy(),
+ nodeAllocatableMemRequestsUtilChartTmpl.Copy(),
+ nodeAllocatableMemRequestsUsedChartTmpl.Copy(),
+ nodeAllocatableMemLimitsUtilChartTmpl.Copy(),
+ nodeAllocatableMemLimitsUsedChartTmpl.Copy(),
+ nodeAllocatablePodsUtilizationChartTmpl.Copy(),
+ nodeAllocatablePodsUsageChartTmpl.Copy(),
+ nodeConditionsChartTmpl.Copy(),
+ nodeSchedulabilityChartTmpl.Copy(),
+ nodePodsReadinessChartTmpl.Copy(),
+ nodePodsReadinessStateChartTmpl.Copy(),
+ nodePodsConditionChartTmpl.Copy(),
+ nodePodsPhaseChartTmpl.Copy(),
+ nodeContainersChartTmpl.Copy(),
+ nodeContainersStateChartTmpl.Copy(),
+ nodeInitContainersStateChartTmpl.Copy(),
+ nodeAgeChartTmpl.Copy(),
+}
+
+var podChartsTmpl = module.Charts{
+ podCPURequestsUsedChartTmpl.Copy(),
+ podCPULimitsUsedChartTmpl.Copy(),
+ podMemRequestsUsedChartTmpl.Copy(),
+ podMemLimitsUsedChartTmpl.Copy(),
+ podConditionChartTmpl.Copy(),
+ podPhaseChartTmpl.Copy(),
+ podAgeChartTmpl.Copy(),
+ podContainersCountChartTmpl.Copy(),
+ podContainersStateChartTmpl.Copy(),
+ podInitContainersStateChartTmpl.Copy(),
+}
+
+var containerChartsTmpl = module.Charts{
+ containerReadinessStateChartTmpl.Copy(),
+ containerRestartsChartTmpl.Copy(),
+ containersStateChartTmpl.Copy(),
+ containersStateWaitingChartTmpl.Copy(),
+ containersStateTerminatedChartTmpl.Copy(),
+}
+
+var (
+ // CPU resource
+ nodeAllocatableCPURequestsUtilChartTmpl = module.Chart{
+ IDSep: true,
+ ID: "node_%s.allocatable_cpu_requests_utilization",
+ Title: "CPU requests utilization",
+ Units: "%",
+ Fam: "node cpu resource",
+ Ctx: "k8s_state.node_allocatable_cpu_requests_utilization",
+ Priority: prioNodeAllocatableCPURequestsUtil,
+ Dims: module.Dims{
+ {ID: "node_%s_alloc_cpu_requests_util", Name: "requests", Div: precision},
+ },
+ }
+ nodeAllocatableCPURequestsUsedChartTmpl = module.Chart{
+ IDSep: true,
+ ID: "node_%s.allocatable_cpu_requests_used",
+ Title: "CPU requests used",
+ Units: "millicpu",
+ Fam: "node cpu resource",
+ Ctx: "k8s_state.node_allocatable_cpu_requests_used",
+ Priority: prioNodeAllocatableCPURequestsUsed,
+ Dims: module.Dims{
+ {ID: "node_%s_alloc_cpu_requests_used", Name: "requests"},
+ },
+ }
+ nodeAllocatableCPULimitsUtilChartTmpl = module.Chart{
+ IDSep: true,
+ ID: "node_%s.allocatable_cpu_limits_utilization",
+ Title: "CPU limits utilization",
+ Units: "%",
+ Fam: "node cpu resource",
+ Ctx: "k8s_state.node_allocatable_cpu_limits_utilization",
+ Priority: prioNodeAllocatableCPULimitsUtil,
+ Dims: module.Dims{
+ {ID: "node_%s_alloc_cpu_limits_util", Name: "limits", Div: precision},
+ },
+ }
+ nodeAllocatableCPULimitsUsedChartTmpl = module.Chart{
+ IDSep: true,
+ ID: "node_%s.allocatable_cpu_limits_used",
+ Title: "CPU limits used",
+ Units: "millicpu",
+ Fam: "node cpu resource",
+ Ctx: "k8s_state.node_allocatable_cpu_limits_used",
+ Priority: prioNodeAllocatableCPULimitsUsed,
+ Dims: module.Dims{
+ {ID: "node_%s_alloc_cpu_limits_used", Name: "limits"},
+ },
+ }
+ // memory resource
+ nodeAllocatableMemRequestsUtilChartTmpl = module.Chart{
+ IDSep: true,
+ ID: "node_%s.allocatable_mem_requests_utilization",
+ Title: "Memory requests utilization",
+ Units: "%",
+ Fam: "node mem resource",
+ Ctx: "k8s_state.node_allocatable_mem_requests_utilization",
+ Priority: prioNodeAllocatableMemRequestsUtil,
+ Dims: module.Dims{
+ {ID: "node_%s_alloc_mem_requests_util", Name: "requests", Div: precision},
+ },
+ }
+ nodeAllocatableMemRequestsUsedChartTmpl = module.Chart{
+ IDSep: true,
+ ID: "node_%s.allocatable_mem_requests_used",
+ Title: "Memory requests used",
+ Units: "bytes",
+ Fam: "node mem resource",
+ Ctx: "k8s_state.node_allocatable_mem_requests_used",
+ Priority: prioNodeAllocatableMemRequestsUsed,
+ Dims: module.Dims{
+ {ID: "node_%s_alloc_mem_requests_used", Name: "requests"},
+ },
+ }
+ nodeAllocatableMemLimitsUtilChartTmpl = module.Chart{
+ IDSep: true,
+ ID: "node_%s.allocatable_mem_limits_utilization",
+ Title: "Memory limits utilization",
+ Units: "%",
+ Fam: "node mem resource",
+ Ctx: "k8s_state.node_allocatable_mem_limits_utilization",
+ Priority: prioNodeAllocatableMemLimitsUtil,
+ Dims: module.Dims{
+ {ID: "node_%s_alloc_mem_limits_util", Name: "limits", Div: precision},
+ },
+ }
+ nodeAllocatableMemLimitsUsedChartTmpl = module.Chart{
+ IDSep: true,
+ ID: "node_%s.allocatable_mem_limits_used",
+ Title: "Memory limits used",
+ Units: "bytes",
+ Fam: "node mem resource",
+ Ctx: "k8s_state.node_allocatable_mem_limits_used",
+ Priority: prioNodeAllocatableMemLimitsUsed,
+ Dims: module.Dims{
+ {ID: "node_%s_alloc_mem_limits_used", Name: "limits"},
+ },
+ }
+ // pods resource
+ nodeAllocatablePodsUtilizationChartTmpl = module.Chart{
+ IDSep: true,
+ ID: "node_%s.allocatable_pods_utilization",
+ Title: "Pods resource utilization",
+ Units: "%",
+ Fam: "node pods resource",
+ Ctx: "k8s_state.node_allocatable_pods_utilization",
+ Priority: prioNodeAllocatablePodsUtil,
+ Dims: module.Dims{
+ {ID: "node_%s_alloc_pods_util", Name: "allocated", Div: precision},
+ },
+ }
+ nodeAllocatablePodsUsageChartTmpl = module.Chart{
+ IDSep: true,
+ ID: "node_%s.allocated_pods_usage",
+ Title: "Pods resource usage",
+ Units: "pods",
+ Fam: "node pods resource",
+ Ctx: "k8s_state.node_allocatable_pods_usage",
+ Type: module.Stacked,
+ Priority: prioNodeAllocatablePodsUsage,
+ Dims: module.Dims{
+ {ID: "node_%s_alloc_pods_available", Name: "available"},
+ {ID: "node_%s_alloc_pods_allocated", Name: "allocated"},
+ },
+ }
+ // condition
+ nodeConditionsChartTmpl = module.Chart{
+ IDSep: true,
+ ID: "node_%s.condition_status",
+ Title: "Condition status",
+ Units: "status",
+ Fam: "node condition",
+ Ctx: "k8s_state.node_condition",
+ Priority: prioNodeConditions,
+ }
+ nodeSchedulabilityChartTmpl = module.Chart{
+ IDSep: true,
+ ID: "node_%s.schedulability",
+ Title: "Schedulability",
+ Units: "state",
+ Fam: "node schedulability",
+ Ctx: "k8s_state.node_schedulability",
+ Priority: prioNodeSchedulability,
+ Dims: module.Dims{
+ {ID: "node_%s_schedulability_schedulable", Name: "schedulable"},
+ {ID: "node_%s_schedulability_unschedulable", Name: "unschedulable"},
+ },
+ }
+ // pods readiness
+ nodePodsReadinessChartTmpl = module.Chart{
+ IDSep: true,
+ ID: "node_%s.pods_readiness",
+ Title: "Pods readiness",
+ Units: "%",
+ Fam: "node pods readiness",
+ Ctx: "k8s_state.node_pods_readiness",
+ Priority: prioNodePodsReadiness,
+ Dims: module.Dims{
+ {ID: "node_%s_pods_readiness", Name: "ready", Div: precision},
+ },
+ }
+ nodePodsReadinessStateChartTmpl = module.Chart{
+ IDSep: true,
+ ID: "node_%s.pods_readiness_state",
+ Title: "Pods readiness state",
+ Units: "pods",
+ Fam: "node pods readiness",
+ Ctx: "k8s_state.node_pods_readiness_state",
+ Type: module.Stacked,
+ Priority: prioNodePodsReadinessState,
+ Dims: module.Dims{
+ {ID: "node_%s_pods_readiness_ready", Name: "ready"},
+ {ID: "node_%s_pods_readiness_unready", Name: "unready"},
+ },
+ }
+ // pods condition
+ nodePodsConditionChartTmpl = module.Chart{
+ IDSep: true,
+ ID: "node_%s.pods_condition",
+ Title: "Pods condition",
+ Units: "pods",
+ Fam: "node pods condition",
+ Ctx: "k8s_state.node_pods_condition",
+ Priority: prioNodePodsCondition,
+ Dims: module.Dims{
+ {ID: "node_%s_pods_cond_podready", Name: "pod_ready"},
+ {ID: "node_%s_pods_cond_podscheduled", Name: "pod_scheduled"},
+ {ID: "node_%s_pods_cond_podinitialized", Name: "pod_initialized"},
+ {ID: "node_%s_pods_cond_containersready", Name: "containers_ready"},
+ },
+ }
+ // pods phase
+ nodePodsPhaseChartTmpl = module.Chart{
+ IDSep: true,
+ ID: "node_%s.pods_phase",
+ Title: "Pods phase",
+ Units: "pods",
+ Fam: "node pods phase",
+ Ctx: "k8s_state.node_pods_phase",
+ Type: module.Stacked,
+ Priority: prioNodePodsPhase,
+ Dims: module.Dims{
+ {ID: "node_%s_pods_phase_running", Name: "running"},
+ {ID: "node_%s_pods_phase_failed", Name: "failed"},
+ {ID: "node_%s_pods_phase_succeeded", Name: "succeeded"},
+ {ID: "node_%s_pods_phase_pending", Name: "pending"},
+ },
+ }
+ // containers
+ nodeContainersChartTmpl = module.Chart{
+ IDSep: true,
+ ID: "node_%s.containers",
+ Title: "Containers",
+ Units: "containers",
+ Fam: "node containers",
+ Ctx: "k8s_state.node_containers",
+ Priority: prioNodeContainersCount,
+ Dims: module.Dims{
+ {ID: "node_%s_containers", Name: "containers"},
+ {ID: "node_%s_init_containers", Name: "init_containers"},
+ },
+ }
+ nodeContainersStateChartTmpl = module.Chart{
+ IDSep: true,
+ ID: "node_%s.containers_state",
+ Title: "Containers state",
+ Units: "containers",
+ Fam: "node containers",
+ Ctx: "k8s_state.node_containers_state",
+ Type: module.Stacked,
+ Priority: prioNodeContainersState,
+ Dims: module.Dims{
+ {ID: "node_%s_containers_state_running", Name: "running"},
+ {ID: "node_%s_containers_state_waiting", Name: "waiting"},
+ {ID: "node_%s_containers_state_terminated", Name: "terminated"},
+ },
+ }
+ nodeInitContainersStateChartTmpl = module.Chart{
+ IDSep: true,
+ ID: "node_%s.init_containers_state",
+ Title: "Init containers state",
+ Units: "containers",
+ Fam: "node containers",
+ Ctx: "k8s_state.node_init_containers_state",
+ Type: module.Stacked,
+ Priority: prioNodeInitContainersState,
+ Dims: module.Dims{
+ {ID: "node_%s_init_containers_state_running", Name: "running"},
+ {ID: "node_%s_init_containers_state_waiting", Name: "waiting"},
+ {ID: "node_%s_init_containers_state_terminated", Name: "terminated"},
+ },
+ }
+ // age
+ nodeAgeChartTmpl = module.Chart{
+ IDSep: true,
+ ID: "node_%s.age",
+ Title: "Age",
+ Units: "seconds",
+ Fam: "node age",
+ Ctx: "k8s_state.node_age",
+ Priority: prioNodeAge,
+ Dims: module.Dims{
+ {ID: "node_%s_age", Name: "age"},
+ },
+ }
+)
+
+func (ks *KubeState) newNodeCharts(ns *nodeState) *module.Charts {
+ cs := nodeChartsTmpl.Copy()
+ for _, c := range *cs {
+ c.ID = fmt.Sprintf(c.ID, replaceDots(ns.id()))
+ c.Labels = ks.newNodeChartLabels(ns)
+ for _, d := range c.Dims {
+ d.ID = fmt.Sprintf(d.ID, ns.id())
+ }
+ }
+ return cs
+}
+
+func (ks *KubeState) newNodeChartLabels(ns *nodeState) []module.Label {
+ labels := []module.Label{
+ {Key: labelKeyNodeName, Value: ns.name, Source: module.LabelSourceK8s},
+ {Key: labelKeyClusterID, Value: ks.kubeClusterID, Source: module.LabelSourceK8s},
+ {Key: labelKeyClusterName, Value: ks.kubeClusterName, Source: module.LabelSourceK8s},
+ }
+ return labels
+}
+
+func (ks *KubeState) addNodeCharts(ns *nodeState) {
+ cs := ks.newNodeCharts(ns)
+ if err := ks.Charts().Add(*cs...); err != nil {
+ ks.Warning(err)
+ }
+}
+
+func (ks *KubeState) removeNodeCharts(ns *nodeState) {
+ prefix := fmt.Sprintf("node_%s", replaceDots(ns.id()))
+ for _, c := range *ks.Charts() {
+ if strings.HasPrefix(c.ID, prefix) {
+ c.MarkRemove()
+ c.MarkNotCreated()
+ }
+ }
+}
+
+func (ks *KubeState) addNodeConditionToCharts(ns *nodeState, cond string) {
+ id := fmt.Sprintf(nodeConditionsChartTmpl.ID, replaceDots(ns.id()))
+ c := ks.Charts().Get(id)
+ if c == nil {
+ ks.Warningf("chart '%s' does not exist", id)
+ return
+ }
+ dim := &module.Dim{
+ ID: fmt.Sprintf("node_%s_cond_%s", ns.id(), strings.ToLower(cond)),
+ Name: cond,
+ }
+ if err := c.AddDim(dim); err != nil {
+ ks.Warning(err)
+ return
+ }
+ c.MarkNotCreated()
+}
+
+var (
+ podCPURequestsUsedChartTmpl = module.Chart{
+ IDSep: true,
+ ID: "pod_%s.cpu_requests_used",
+ Title: "CPU requests used",
+ Units: "millicpu",
+ Fam: "pod allocated cpu",
+ Ctx: "k8s_state.pod_cpu_requests_used",
+ Priority: prioPodCPURequestsUsed,
+ Dims: module.Dims{
+ {ID: "pod_%s_cpu_requests_used", Name: "requests"},
+ },
+ }
+ podCPULimitsUsedChartTmpl = module.Chart{
+ IDSep: true,
+ ID: "pod_%s.cpu_limits_used",
+ Title: "CPU limits used",
+ Units: "millicpu",
+ Fam: "pod allocated cpu",
+ Ctx: "k8s_state.pod_cpu_limits_used",
+ Priority: prioPodCPULimitsUsed,
+ Dims: module.Dims{
+ {ID: "pod_%s_cpu_limits_used", Name: "limits"},
+ },
+ }
+ podMemRequestsUsedChartTmpl = module.Chart{
+ IDSep: true,
+ ID: "pod_%s.mem_requests_used",
+ Title: "Memory requests used",
+ Units: "bytes",
+ Fam: "pod allocated mem",
+ Ctx: "k8s_state.pod_mem_requests_used",
+ Priority: prioPodMemRequestsUsed,
+ Dims: module.Dims{
+ {ID: "pod_%s_mem_requests_used", Name: "requests"},
+ },
+ }
+ podMemLimitsUsedChartTmpl = module.Chart{
+ IDSep: true,
+ ID: "pod_%s.mem_limits_used",
+ Title: "Memory limits used",
+ Units: "bytes",
+ Fam: "pod allocated mem",
+ Ctx: "k8s_state.pod_mem_limits_used",
+ Priority: prioPodMemLimitsUsed,
+ Dims: module.Dims{
+ {ID: "pod_%s_mem_limits_used", Name: "limits"},
+ },
+ }
+ podConditionChartTmpl = module.Chart{
+ IDSep: true,
+ ID: "pod_%s.condition",
+ Title: "Condition",
+ Units: "state",
+ Fam: "pod condition",
+ Ctx: "k8s_state.pod_condition",
+ Priority: prioPodCondition,
+ Dims: module.Dims{
+ {ID: "pod_%s_cond_podready", Name: "pod_ready"},
+ {ID: "pod_%s_cond_podscheduled", Name: "pod_scheduled"},
+ {ID: "pod_%s_cond_podinitialized", Name: "pod_initialized"},
+ {ID: "pod_%s_cond_containersready", Name: "containers_ready"},
+ },
+ }
+ podPhaseChartTmpl = module.Chart{
+ IDSep: true,
+ ID: "pod_%s.phase",
+ Title: "Phase",
+ Units: "state",
+ Fam: "pod phase",
+ Ctx: "k8s_state.pod_phase",
+ Priority: prioPodPhase,
+ Dims: module.Dims{
+ {ID: "pod_%s_phase_running", Name: "running"},
+ {ID: "pod_%s_phase_failed", Name: "failed"},
+ {ID: "pod_%s_phase_succeeded", Name: "succeeded"},
+ {ID: "pod_%s_phase_pending", Name: "pending"},
+ },
+ }
+ podAgeChartTmpl = module.Chart{
+ IDSep: true,
+ ID: "pod_%s.age",
+ Title: "Age",
+ Units: "seconds",
+ Fam: "pod age",
+ Ctx: "k8s_state.pod_age",
+ Priority: prioPodAge,
+ Dims: module.Dims{
+ {ID: "pod_%s_age", Name: "age"},
+ },
+ }
+ podContainersCountChartTmpl = module.Chart{
+ IDSep: true,
+ ID: "pod_%s.containers_count",
+ Title: "Containers",
+ Units: "containers",
+ Fam: "pod containers",
+ Ctx: "k8s_state.pod_containers",
+ Priority: prioPodContainersCount,
+ Dims: module.Dims{
+ {ID: "pod_%s_containers", Name: "containers"},
+ {ID: "pod_%s_init_containers", Name: "init_containers"},
+ },
+ }
+ podContainersStateChartTmpl = module.Chart{
+ IDSep: true,
+ ID: "pod_%s.containers_state",
+ Title: "Containers state",
+ Units: "containers",
+ Fam: "pod containers",
+ Ctx: "k8s_state.pod_containers_state",
+ Type: module.Stacked,
+ Priority: prioPodContainersState,
+ Dims: module.Dims{
+ {ID: "pod_%s_containers_state_running", Name: "running"},
+ {ID: "pod_%s_containers_state_waiting", Name: "waiting"},
+ {ID: "pod_%s_containers_state_terminated", Name: "terminated"},
+ },
+ }
+ podInitContainersStateChartTmpl = module.Chart{
+ IDSep: true,
+ ID: "pod_%s.init_containers_state",
+ Title: "Init containers state",
+ Units: "containers",
+ Fam: "pod containers",
+ Ctx: "k8s_state.pod_init_containers_state",
+ Type: module.Stacked,
+ Priority: prioPodInitContainersState,
+ Dims: module.Dims{
+ {ID: "pod_%s_init_containers_state_running", Name: "running"},
+ {ID: "pod_%s_init_containers_state_waiting", Name: "waiting"},
+ {ID: "pod_%s_init_containers_state_terminated", Name: "terminated"},
+ },
+ }
+)
+
+func (ks *KubeState) newPodCharts(ps *podState) *module.Charts {
+ charts := podChartsTmpl.Copy()
+ for _, c := range *charts {
+ c.ID = fmt.Sprintf(c.ID, replaceDots(ps.id()))
+ c.Labels = ks.newPodChartLabels(ps)
+ for _, d := range c.Dims {
+ d.ID = fmt.Sprintf(d.ID, ps.id())
+ }
+ }
+ return charts
+}
+
+func (ks *KubeState) newPodChartLabels(ps *podState) []module.Label {
+ labels := []module.Label{
+ {Key: labelKeyNamespace, Value: ps.namespace, Source: module.LabelSourceK8s},
+ {Key: labelKeyPodName, Value: ps.name, Source: module.LabelSourceK8s},
+ {Key: labelKeyNodeName, Value: ps.nodeName, Source: module.LabelSourceK8s},
+ {Key: labelKeyQoSClass, Value: ps.qosClass, Source: module.LabelSourceK8s},
+ {Key: labelKeyControllerKind, Value: ps.controllerKind, Source: module.LabelSourceK8s},
+ {Key: labelKeyControllerName, Value: ps.controllerName, Source: module.LabelSourceK8s},
+ {Key: labelKeyClusterID, Value: ks.kubeClusterID, Source: module.LabelSourceK8s},
+ {Key: labelKeyClusterName, Value: ks.kubeClusterName, Source: module.LabelSourceK8s},
+ }
+ return labels
+}
+
+func (ks *KubeState) addPodCharts(ps *podState) {
+ charts := ks.newPodCharts(ps)
+ if err := ks.Charts().Add(*charts...); err != nil {
+ ks.Warning(err)
+ }
+}
+
+func (ks *KubeState) updatePodChartsNodeLabel(ps *podState) {
+ prefix := fmt.Sprintf("pod_%s", replaceDots(ps.id()))
+ for _, c := range *ks.Charts() {
+ if strings.HasPrefix(c.ID, prefix) {
+ updateNodeLabel(c, ps.nodeName)
+ c.MarkNotCreated()
+ }
+ }
+}
+
+func updateNodeLabel(c *module.Chart, nodeName string) {
+ for i, l := range c.Labels {
+ if l.Key == labelKeyNodeName {
+ c.Labels[i].Value = nodeName
+ break
+ }
+ }
+}
+
+func (ks *KubeState) removePodCharts(ps *podState) {
+ prefix := fmt.Sprintf("pod_%s", replaceDots(ps.id()))
+ for _, c := range *ks.Charts() {
+ if strings.HasPrefix(c.ID, prefix) {
+ c.MarkRemove()
+ c.MarkNotCreated()
+ }
+ }
+}
+
+var (
+ containerReadinessStateChartTmpl = module.Chart{
+ IDSep: true,
+ ID: "pod_%s_container_%s.readiness_state",
+ Title: "Readiness state",
+ Units: "state",
+ Fam: "container readiness",
+ Ctx: "k8s_state.pod_container_readiness_state",
+ Priority: prioPodContainerReadinessState,
+ Dims: module.Dims{
+ {ID: "pod_%s_container_%s_readiness", Name: "ready"},
+ },
+ }
+ containerRestartsChartTmpl = module.Chart{
+ IDSep: true,
+ ID: "pod_%s_container_%s.restarts",
+ Title: "Restarts",
+ Units: "restarts",
+ Fam: "container restarts",
+ Ctx: "k8s_state.pod_container_restarts",
+ Priority: prioPodContainerRestarts,
+ Dims: module.Dims{
+ {ID: "pod_%s_container_%s_restarts", Name: "restarts"},
+ },
+ }
+ containersStateChartTmpl = module.Chart{
+ IDSep: true,
+ ID: "pod_%s_container_%s.state",
+ Title: "Container state",
+ Units: "state",
+ Fam: "container state",
+ Ctx: "k8s_state.pod_container_state",
+ Priority: prioPodContainerState,
+ Dims: module.Dims{
+ {ID: "pod_%s_container_%s_state_running", Name: "running"},
+ {ID: "pod_%s_container_%s_state_waiting", Name: "waiting"},
+ {ID: "pod_%s_container_%s_state_terminated", Name: "terminated"},
+ },
+ }
+ containersStateWaitingChartTmpl = module.Chart{
+ IDSep: true,
+ ID: "pod_%s_container_%s.state_waiting_reason",
+ Title: "Container waiting state reason",
+ Units: "state",
+ Fam: "container waiting reason",
+ Ctx: "k8s_state.pod_container_waiting_state_reason",
+ Priority: prioPodContainerWaitingStateReason,
+ }
+ containersStateTerminatedChartTmpl = module.Chart{
+ IDSep: true,
+ ID: "pod_%s_container_%s.state_terminated_reason",
+ Title: "Container terminated state reason",
+ Units: "state",
+ Fam: "container terminated reason",
+ Ctx: "k8s_state.pod_container_terminated_state_reason",
+ Priority: prioPodContainerTerminatedStateReason,
+ }
+)
+
+func (ks *KubeState) newContainerCharts(ps *podState, cs *containerState) *module.Charts {
+ charts := containerChartsTmpl.Copy()
+ for _, c := range *charts {
+ c.ID = fmt.Sprintf(c.ID, replaceDots(ps.id()), cs.name)
+ c.Labels = ks.newContainerChartLabels(ps, cs)
+ for _, d := range c.Dims {
+ d.ID = fmt.Sprintf(d.ID, ps.id(), cs.name)
+ }
+ }
+ return charts
+}
+
+func (ks *KubeState) newContainerChartLabels(ps *podState, cs *containerState) []module.Label {
+ labels := ks.newPodChartLabels(ps)
+ labels = append(
+ labels, module.Label{Key: labelKeyContainerName, Value: cs.name, Source: module.LabelSourceK8s},
+ )
+ return labels
+}
+
+func (ks *KubeState) addContainerCharts(ps *podState, cs *containerState) {
+ charts := ks.newContainerCharts(ps, cs)
+ if err := ks.Charts().Add(*charts...); err != nil {
+ ks.Warning(err)
+ }
+}
+
+func (ks *KubeState) addContainerWaitingStateReasonToChart(ps *podState, cs *containerState, reason string) {
+ id := fmt.Sprintf(containersStateWaitingChartTmpl.ID, replaceDots(ps.id()), cs.name)
+ c := ks.Charts().Get(id)
+ if c == nil {
+ ks.Warningf("chart '%s' does not exist", id)
+ return
+ }
+ dim := &module.Dim{
+ ID: fmt.Sprintf("pod_%s_container_%s_state_waiting_reason_%s", ps.id(), cs.name, reason),
+ Name: reason,
+ }
+ if err := c.AddDim(dim); err != nil {
+ ks.Warning(err)
+ return
+ }
+ c.MarkNotCreated()
+}
+
+func (ks *KubeState) addContainerTerminatedStateReasonToChart(ps *podState, cs *containerState, reason string) {
+ id := fmt.Sprintf(containersStateTerminatedChartTmpl.ID, replaceDots(ps.id()), cs.name)
+ c := ks.Charts().Get(id)
+ if c == nil {
+ ks.Warningf("chart '%s' does not exist", id)
+ return
+ }
+ dim := &module.Dim{
+ ID: fmt.Sprintf("pod_%s_container_%s_state_terminated_reason_%s", ps.id(), cs.name, reason),
+ Name: reason,
+ }
+ if err := c.AddDim(dim); err != nil {
+ ks.Warning(err)
+ return
+ }
+ c.MarkNotCreated()
+}
+
+var discoveryStatusChart = module.Chart{
+ ID: "discovery_discoverers_state",
+ Title: "Running discoverers state",
+ Units: "state",
+ Fam: "discovery",
+ Ctx: "k8s_state.discovery_discoverers_state",
+ Priority: prioDiscoveryDiscovererState,
+ Opts: module.Opts{Hidden: true},
+ Dims: module.Dims{
+ {ID: "discovery_node_discoverer_state", Name: "node"},
+ {ID: "discovery_pod_discoverer_state", Name: "pod"},
+ },
+}
+
+var reDots = regexp.MustCompile(`\.`)
+
+func replaceDots(v string) string {
+ return reDots.ReplaceAllString(v, "-")
+}