From 3e4d91c4ba0fbc6aa7ac4636ffed6036c26634ce Mon Sep 17 00:00:00 2001 From: opeco17 Date: Mon, 14 Aug 2023 13:18:38 +0000 Subject: [PATCH] feat: implement kube_pod_status_initialized_time --- docs/pod-metrics.md | 1 + internal/store/pod.go | 28 ++++++++++++++++++++ internal/store/pod_test.go | 53 +++++++++++++++++++++++++++++++++++++- pkg/app/server_test.go | 2 ++ 4 files changed, 83 insertions(+), 1 deletion(-) diff --git a/docs/pod-metrics.md b/docs/pod-metrics.md index 3037372efd..faa191c38a 100644 --- a/docs/pod-metrics.md +++ b/docs/pod-metrics.md @@ -24,6 +24,7 @@ | kube_pod_container_status_last_terminated_reason | Gauge | Describes the last reason the container was in terminated state | |`container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`reason`=<last-terminated-reason>
`uid`=<pod-uid> | EXPERIMENTAL | - | | kube_pod_container_status_last_terminated_exitcode | Gauge | Describes the exit code for the last container in terminated state. | | `container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | EXPERIMENTAL | - | | kube_pod_container_status_ready | Gauge | Describes whether the containers readiness check succeeded | |`container`=<container-name>
`pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | STABLE | - | +| kube_pod_status_initialized_time | Gauge | Time when the pod is initialized. | seconds | `pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | EXPERIMENTAL | | kube_pod_status_ready_time | Gauge | Time when pod passed readiness probes. | seconds | `pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | EXPERIMENTAL | | kube_pod_status_container_ready_time | Gauge | Time when the container of the pod entered Ready state. | seconds | `pod`=<pod-name>
`namespace`=<pod-namespace>
`uid`=<pod-uid> | EXPERIMENTAL | | kube_pod_container_status_restarts_total | Counter | The number of container restarts per container | | `container`=<container-name>
`namespace`=<pod-namespace>
`pod`=<pod-name>
`uid`=<pod-uid> | STABLE | - | diff --git a/internal/store/pod.go b/internal/store/pod.go index 233fb2718b..fe14949136 100644 --- a/internal/store/pod.go +++ b/internal/store/pod.go @@ -85,6 +85,7 @@ func podMetricFamilies(allowAnnotationsList, allowLabelsList []string) []generat createPodStatusQosClassFamilyGenerator(), createPodStatusReadyFamilyGenerator(), createPodStatusReadyTimeFamilyGenerator(), + createPodStatusInitializedTimeFamilyGenerator(), createPodStatusContainerReadyTimeFamilyGenerator(), createPodStatusReasonFamilyGenerator(), createPodStatusScheduledFamilyGenerator(), @@ -1337,6 +1338,33 @@ func createPodStatusPhaseFamilyGenerator() generator.FamilyGenerator { ) } +func createPodStatusInitializedTimeFamilyGenerator() generator.FamilyGenerator { + return *generator.NewFamilyGeneratorWithStability( + "kube_pod_status_initialized_time", + "Initialized time in unix timestamp for a pod.", + metric.Gauge, + basemetrics.ALPHA, + "", + wrapPodFunc(func(p *v1.Pod) *metric.Family { + ms := []*metric.Metric{} + + for _, c := range p.Status.Conditions { + if c.Type == v1.PodInitialized && c.Status == v1.ConditionTrue { + ms = append(ms, &metric.Metric{ + LabelKeys: []string{}, + LabelValues: []string{}, + Value: float64((c.LastTransitionTime).Unix()), + }) + } + } + + return &metric.Family{ + Metrics: ms, + } + }), + ) +} + func createPodStatusContainerReadyTimeFamilyGenerator() generator.FamilyGenerator { return *generator.NewFamilyGeneratorWithStability( "kube_pod_status_container_ready_time", diff --git a/internal/store/pod_test.go b/internal/store/pod_test.go index e1ae2d00bd..791884d3d5 100644 --- a/internal/store/pod_test.go +++ b/internal/store/pod_test.go @@ -1434,6 +1434,57 @@ func TestPodStore(t *testing.T) { `, MetricNames: []string{"kube_pod_status_reason"}, }, + { + Obj: &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pod1", + Namespace: "ns1", + UID: "uid1", + }, + Status: v1.PodStatus{ + Conditions: []v1.PodCondition{ + { + Type: v1.PodInitialized, + Status: v1.ConditionTrue, + LastTransitionTime: metav1.Time{ + Time: time.Unix(1501666018, 0), + }, + }, + }, + }, + }, + Want: ` + # HELP kube_pod_status_initialized_time Initialized time in unix timestamp for a pod. + # TYPE kube_pod_status_initialized_time gauge + kube_pod_status_initialized_time{namespace="ns1",pod="pod1",uid="uid1"} 1.501666018e+09 + `, + MetricNames: []string{"kube_pod_status_initialized_time"}, + }, + { + Obj: &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pod1", + Namespace: "ns1", + UID: "uid1", + }, + Status: v1.PodStatus{ + Conditions: []v1.PodCondition{ + { + Type: v1.PodInitialized, + Status: v1.ConditionFalse, + LastTransitionTime: metav1.Time{ + Time: time.Unix(1501666018, 0), + }, + }, + }, + }, + }, + Want: ` + # HELP kube_pod_status_initialized_time Initialized time in unix timestamp for a pod. + # TYPE kube_pod_status_initialized_time gauge + `, + MetricNames: []string{"kube_pod_status_initialized_time"}, + }, { Obj: &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ @@ -2181,7 +2232,7 @@ func BenchmarkPodStore(b *testing.B) { }, } - expectedFamilies := 51 + expectedFamilies := 52 for n := 0; n < b.N; n++ { families := f(pod) if len(families) != expectedFamilies { diff --git a/pkg/app/server_test.go b/pkg/app/server_test.go index daf693b24d..9adbe50607 100644 --- a/pkg/app/server_test.go +++ b/pkg/app/server_test.go @@ -242,6 +242,7 @@ func TestFullScrapeCycle(t *testing.T) { # HELP kube_pod_spec_volumes_persistentvolumeclaims_readonly [STABLE] Describes whether a persistentvolumeclaim is mounted read only. # HELP kube_pod_start_time [STABLE] Start time in unix timestamp for a pod. # HELP kube_pod_status_container_ready_time Readiness achieved time in unix timestamp for a pod containers. +# HELP kube_pod_status_initialized_time Initialized time in unix timestamp for a pod. # HELP kube_pod_status_qos_class The pods current qosClass. # HELP kube_pod_status_phase [STABLE] The pods current phase. # HELP kube_pod_status_ready_time Readiness achieved time in unix timestamp for a pod. @@ -292,6 +293,7 @@ func TestFullScrapeCycle(t *testing.T) { # TYPE kube_pod_spec_volumes_persistentvolumeclaims_readonly gauge # TYPE kube_pod_start_time gauge # TYPE kube_pod_status_container_ready_time gauge +# TYPE kube_pod_status_initialized_time gauge # TYPE kube_pod_status_phase gauge # TYPE kube_pod_status_qos_class gauge # TYPE kube_pod_status_ready gauge