Compare commits

...

32 Commits

Author SHA1 Message Date
Nikhil Mantri
dc9c127925 Merge branch 'infraM/pod_status_restart_counts' into infraM/goroutines_for_concurrent_queries 2026-07-06 18:01:41 +05:30
Nikhil Mantri
612ffd8cf7 Merge branch 'main' into infraM/pod_status_restart_counts 2026-07-06 16:51:47 +05:30
nikhilmantri0902
babb2e2cd1 chore: added goroutines for ListStatefulsets, ListJobs and ListDaemonsets 2026-07-06 12:51:07 +05:30
nikhilmantri0902
0bd0f7ada9 chore: goroutines for ListStatefulsets 2026-07-06 12:45:31 +05:30
nikhilmantri0902
66b40b5509 chore: goroutines for ListDeployments 2026-07-06 12:43:48 +05:30
nikhilmantri0902
77e56eea8c chore: goroutines for ListClusters 2026-07-06 12:34:59 +05:30
nikhilmantri0902
c4448c9940 chore: goroutines for ListNamespaces 2026-07-06 12:33:52 +05:30
nikhilmantri0902
60c33003b8 chore: goroutines for ListNodes 2026-07-06 12:30:31 +05:30
nikhilmantri0902
a126cee885 chore: goroutines for ListPods 2026-07-06 12:26:59 +05:30
nikhilmantri0902
916466d7d1 chore: goroutines for ListHosts 2026-07-06 12:19:15 +05:30
nikhilmantri0902
11fa6bbb10 chore: removed dead constants 2026-07-03 20:02:14 +05:30
Nikhil Mantri
b1136348c4 Merge branch 'main' into infraM/pod_status_restart_counts 2026-07-02 20:07:56 +05:30
nikhilmantri0902
3bdff5a083 chore: corrected metrics list for metadata lookup 2026-07-02 17:58:54 +05:30
nikhilmantri0902
76eccec91c chore: query beautified 2026-07-02 16:48:53 +05:30
Nikhil Mantri
4d94a4090d Merge branch 'main' into infraM/pod_status_restart_counts 2026-07-01 16:54:00 +05:30
nikhilmantri0902
406f676e7c chore: removed succeeded status and mark it as completed 2026-07-01 16:53:04 +05:30
Nikhil Mantri
73c267e3f7 Merge branch 'main' into infraM/pod_status_restart_counts 2026-06-30 16:39:48 +05:30
nikhilmantri0902
e7fbf89d4a chore: rearrangement 2026-06-30 10:48:00 +05:30
Nikhil Mantri
f08cea5491 Merge branch 'main' into infraM/pod_status_restart_counts 2026-06-29 21:30:14 +05:30
nikhilmantri0902
79160910d1 chore: added checks api changes for other entities 2026-06-29 21:25:14 +05:30
nikhilmantri0902
fdcdd935a7 chore: added integration tests for other entities 2026-06-29 21:02:19 +05:30
nikhilmantri0902
2c4a661edb chore: added pod status counts for other entities 2026-06-29 20:38:05 +05:30
nikhilmantri0902
20ddd8df8c chore: added podcountsbyphase in other entities 2026-06-29 20:18:04 +05:30
nikhilmantri0902
744c5cf587 chore: integration tests added 2026-06-29 18:56:50 +05:30
nikhilmantri0902
d4ddfceba5 chore: onboarding API changes 2026-06-29 17:46:44 +05:30
nikhilmantri0902
c752131fe0 chore: bug in query fix 2026-06-29 17:30:02 +05:30
nikhilmantri0902
223c2a6c31 chore: added restart counts for the group 2026-06-29 16:08:35 +05:30
nikhilmantri0902
6bf20c5e93 chore: pod restarts type added 2026-06-29 16:01:14 +05:30
nikhilmantri0902
09fce10c1d chore: wired up pod status counts 2026-06-29 15:28:54 +05:30
nikhilmantri0902
8e6891cf58 chore: per group pod status counts with req metric checks method added 2026-06-29 15:14:41 +05:30
nikhilmantri0902
49019f44b6 chore: added method to calculate reason 2026-06-29 15:00:33 +05:30
nikhilmantri0902
075611fc6c chore: added types and open api spec changes 2026-06-29 14:00:52 +05:30
43 changed files with 2062 additions and 125 deletions

View File

@@ -4251,6 +4251,8 @@ components:
$ref: '#/components/schemas/InframonitoringtypesNodeCountsByReadiness'
podCountsByPhase:
$ref: '#/components/schemas/InframonitoringtypesPodCountsByPhase'
podCountsByStatus:
$ref: '#/components/schemas/InframonitoringtypesPodCountsByStatus'
required:
- clusterName
- clusterCPU
@@ -4259,6 +4261,7 @@ components:
- clusterMemoryAllocatable
- nodeCountsByReadiness
- podCountsByPhase
- podCountsByStatus
- meta
type: object
InframonitoringtypesClusters:
@@ -4314,6 +4317,8 @@ components:
type: object
podCountsByPhase:
$ref: '#/components/schemas/InframonitoringtypesPodCountsByPhase'
podCountsByStatus:
$ref: '#/components/schemas/InframonitoringtypesPodCountsByStatus'
required:
- daemonSetName
- daemonSetCPU
@@ -4325,6 +4330,7 @@ components:
- desiredNodes
- currentNodes
- podCountsByPhase
- podCountsByStatus
- meta
type: object
InframonitoringtypesDaemonSets:
@@ -4380,6 +4386,8 @@ components:
type: object
podCountsByPhase:
$ref: '#/components/schemas/InframonitoringtypesPodCountsByPhase'
podCountsByStatus:
$ref: '#/components/schemas/InframonitoringtypesPodCountsByStatus'
required:
- deploymentName
- deploymentCPU
@@ -4391,6 +4399,7 @@ components:
- desiredPods
- availablePods
- podCountsByPhase
- podCountsByStatus
- meta
type: object
InframonitoringtypesDeployments:
@@ -4523,6 +4532,8 @@ components:
type: object
podCountsByPhase:
$ref: '#/components/schemas/InframonitoringtypesPodCountsByPhase'
podCountsByStatus:
$ref: '#/components/schemas/InframonitoringtypesPodCountsByStatus'
successfulPods:
type: integer
required:
@@ -4538,6 +4549,7 @@ components:
- failedPods
- successfulPods
- podCountsByPhase
- podCountsByStatus
- meta
type: object
InframonitoringtypesJobs:
@@ -4628,11 +4640,14 @@ components:
type: string
podCountsByPhase:
$ref: '#/components/schemas/InframonitoringtypesPodCountsByPhase'
podCountsByStatus:
$ref: '#/components/schemas/InframonitoringtypesPodCountsByStatus'
required:
- namespaceName
- namespaceCPU
- namespaceMemory
- podCountsByPhase
- podCountsByStatus
- meta
type: object
InframonitoringtypesNamespaces:
@@ -4698,11 +4713,14 @@ components:
type: string
podCountsByPhase:
$ref: '#/components/schemas/InframonitoringtypesPodCountsByPhase'
podCountsByStatus:
$ref: '#/components/schemas/InframonitoringtypesPodCountsByStatus'
required:
- nodeName
- condition
- nodeCountsByReadiness
- podCountsByPhase
- podCountsByStatus
- nodeCPU
- nodeCPUAllocatable
- nodeMemory
@@ -4748,6 +4766,64 @@ components:
- failed
- unknown
type: object
InframonitoringtypesPodCountsByStatus:
properties:
completed:
type: integer
containerCannotRun:
type: integer
containerCreating:
type: integer
crashLoopBackOff:
type: integer
createContainerConfigError:
type: integer
errImagePull:
type: integer
error:
type: integer
evicted:
type: integer
failed:
type: integer
imagePullBackOff:
type: integer
nodeAffinity:
type: integer
nodeLost:
type: integer
oomKilled:
type: integer
pending:
type: integer
running:
type: integer
shutdown:
type: integer
unexpectedAdmissionError:
type: integer
unknown:
type: integer
required:
- pending
- running
- failed
- unknown
- crashLoopBackOff
- imagePullBackOff
- errImagePull
- createContainerConfigError
- containerCreating
- oomKilled
- completed
- error
- containerCannotRun
- evicted
- nodeAffinity
- nodeLost
- shutdown
- unexpectedAdmissionError
type: object
InframonitoringtypesPodPhase:
enum:
- pending
@@ -4778,6 +4854,8 @@ components:
type: number
podCountsByPhase:
$ref: '#/components/schemas/InframonitoringtypesPodCountsByPhase'
podCountsByStatus:
$ref: '#/components/schemas/InframonitoringtypesPodCountsByStatus'
podMemory:
format: double
type: number
@@ -4789,6 +4867,11 @@ components:
type: number
podPhase:
$ref: '#/components/schemas/InframonitoringtypesPodPhase'
podRestarts:
format: int64
type: integer
podStatus:
$ref: '#/components/schemas/InframonitoringtypesPodStatus'
podUID:
type: string
required:
@@ -4801,9 +4884,34 @@ components:
- podMemoryLimit
- podPhase
- podCountsByPhase
- podStatus
- podCountsByStatus
- podRestarts
- podAge
- meta
type: object
InframonitoringtypesPodStatus:
enum:
- pending
- running
- failed
- unknown
- crashloopbackoff
- imagepullbackoff
- errimagepull
- createcontainerconfigerror
- containercreating
- oomkilled
- completed
- error
- containercannotrun
- evicted
- nodeaffinity
- nodelost
- shutdown
- unexpectedadmissionerror
- no_data
type: string
InframonitoringtypesPods:
properties:
endTimeBeforeRetention:
@@ -5102,6 +5210,8 @@ components:
type: object
podCountsByPhase:
$ref: '#/components/schemas/InframonitoringtypesPodCountsByPhase'
podCountsByStatus:
$ref: '#/components/schemas/InframonitoringtypesPodCountsByStatus'
statefulSetCPU:
format: double
type: number
@@ -5133,6 +5243,7 @@ components:
- desiredPods
- currentPods
- podCountsByPhase
- podCountsByStatus
- meta
type: object
InframonitoringtypesStatefulSets:

View File

@@ -5693,6 +5693,81 @@ export interface InframonitoringtypesPodCountsByPhaseDTO {
unknown: number;
}
export interface InframonitoringtypesPodCountsByStatusDTO {
/**
* @type integer
*/
completed: number;
/**
* @type integer
*/
containerCannotRun: number;
/**
* @type integer
*/
containerCreating: number;
/**
* @type integer
*/
crashLoopBackOff: number;
/**
* @type integer
*/
createContainerConfigError: number;
/**
* @type integer
*/
errImagePull: number;
/**
* @type integer
*/
error: number;
/**
* @type integer
*/
evicted: number;
/**
* @type integer
*/
failed: number;
/**
* @type integer
*/
imagePullBackOff: number;
/**
* @type integer
*/
nodeAffinity: number;
/**
* @type integer
*/
nodeLost: number;
/**
* @type integer
*/
oomKilled: number;
/**
* @type integer
*/
pending: number;
/**
* @type integer
*/
running: number;
/**
* @type integer
*/
shutdown: number;
/**
* @type integer
*/
unexpectedAdmissionError: number;
/**
* @type integer
*/
unknown: number;
}
export interface InframonitoringtypesClusterRecordDTO {
/**
* @type number
@@ -5724,6 +5799,7 @@ export interface InframonitoringtypesClusterRecordDTO {
meta: InframonitoringtypesClusterRecordDTOMeta;
nodeCountsByReadiness: InframonitoringtypesNodeCountsByReadinessDTO;
podCountsByPhase: InframonitoringtypesPodCountsByPhaseDTO;
podCountsByStatus: InframonitoringtypesPodCountsByStatusDTO;
}
export enum InframonitoringtypesResponseTypeDTO {
@@ -5827,6 +5903,7 @@ export interface InframonitoringtypesDaemonSetRecordDTO {
*/
meta: InframonitoringtypesDaemonSetRecordDTOMeta;
podCountsByPhase: InframonitoringtypesPodCountsByPhaseDTO;
podCountsByStatus: InframonitoringtypesPodCountsByStatusDTO;
}
export interface InframonitoringtypesDaemonSetsDTO {
@@ -5904,6 +5981,7 @@ export interface InframonitoringtypesDeploymentRecordDTO {
*/
meta: InframonitoringtypesDeploymentRecordDTOMeta;
podCountsByPhase: InframonitoringtypesPodCountsByPhaseDTO;
podCountsByStatus: InframonitoringtypesPodCountsByStatusDTO;
}
export interface InframonitoringtypesDeploymentsDTO {
@@ -6070,6 +6148,7 @@ export interface InframonitoringtypesJobRecordDTO {
*/
meta: InframonitoringtypesJobRecordDTOMeta;
podCountsByPhase: InframonitoringtypesPodCountsByPhaseDTO;
podCountsByStatus: InframonitoringtypesPodCountsByStatusDTO;
/**
* @type integer
*/
@@ -6123,6 +6202,7 @@ export interface InframonitoringtypesNamespaceRecordDTO {
*/
namespaceName: string;
podCountsByPhase: InframonitoringtypesPodCountsByPhaseDTO;
podCountsByStatus: InframonitoringtypesPodCountsByStatusDTO;
}
export interface InframonitoringtypesNamespacesDTO {
@@ -6189,6 +6269,7 @@ export interface InframonitoringtypesNodeRecordDTO {
*/
nodeName: string;
podCountsByPhase: InframonitoringtypesPodCountsByPhaseDTO;
podCountsByStatus: InframonitoringtypesPodCountsByStatusDTO;
}
export interface InframonitoringtypesNodesDTO {
@@ -6226,6 +6307,27 @@ export type InframonitoringtypesPodRecordDTOMetaAnyOf = {
export type InframonitoringtypesPodRecordDTOMeta =
InframonitoringtypesPodRecordDTOMetaAnyOf | null;
export enum InframonitoringtypesPodStatusDTO {
pending = 'pending',
running = 'running',
failed = 'failed',
unknown = 'unknown',
crashloopbackoff = 'crashloopbackoff',
imagepullbackoff = 'imagepullbackoff',
errimagepull = 'errimagepull',
createcontainerconfigerror = 'createcontainerconfigerror',
containercreating = 'containercreating',
oomkilled = 'oomkilled',
completed = 'completed',
error = 'error',
containercannotrun = 'containercannotrun',
evicted = 'evicted',
nodeaffinity = 'nodeaffinity',
nodelost = 'nodelost',
shutdown = 'shutdown',
unexpectedadmissionerror = 'unexpectedadmissionerror',
no_data = 'no_data',
}
export interface InframonitoringtypesPodRecordDTO {
/**
* @type object,null
@@ -6252,6 +6354,7 @@ export interface InframonitoringtypesPodRecordDTO {
*/
podCPURequest: number;
podCountsByPhase: InframonitoringtypesPodCountsByPhaseDTO;
podCountsByStatus: InframonitoringtypesPodCountsByStatusDTO;
/**
* @type number
* @format double
@@ -6268,6 +6371,12 @@ export interface InframonitoringtypesPodRecordDTO {
*/
podMemoryRequest: number;
podPhase: InframonitoringtypesPodPhaseDTO;
/**
* @type integer
* @format int64
*/
podRestarts: number;
podStatus: InframonitoringtypesPodStatusDTO;
/**
* @type string
*/
@@ -6585,6 +6694,7 @@ export interface InframonitoringtypesStatefulSetRecordDTO {
*/
meta: InframonitoringtypesStatefulSetRecordDTOMeta;
podCountsByPhase: InframonitoringtypesPodCountsByPhaseDTO;
podCountsByStatus: InframonitoringtypesPodCountsByStatusDTO;
/**
* @type number
* @format double

View File

@@ -117,8 +117,16 @@ var podsSpec = checkSpec{
DocumentationLink: docLinkKubeletStatsReceiver,
},
{
Component: componentK8sClusterReceiver,
DefaultMetrics: []string{"k8s.pod.phase"},
Component: componentK8sClusterReceiver,
DefaultMetrics: []string{
"k8s.pod.phase",
"k8s.container.restarts", // pod restart count (default-on)
},
OptionalMetrics: []string{
// kubectl-style pod display status (default-off in the receiver).
"k8s.pod.status_reason",
"k8s.container.status.reason",
},
DocumentationLink: docLinkK8sClusterReceiver,
},
{
@@ -149,6 +157,10 @@ var nodesSpec = checkSpec{
// By default, only k8s.node.condition_ready is enabled. (Check https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/4f9a578b210a6dcb9f9bf47942f27208b5765298/receiver/k8sclusterreceiver/metadata.yaml#L802)
"k8s.pod.phase", // pod counts per node by phase
},
OptionalMetrics: []string{
"k8s.pod.status_reason",
"k8s.container.status.reason",
},
DocumentationLink: docLinkK8sClusterReceiver,
},
{
@@ -182,6 +194,10 @@ var deploymentsSpec = checkSpec{
"k8s.deployment.desired",
"k8s.deployment.available",
},
OptionalMetrics: []string{
"k8s.pod.status_reason",
"k8s.container.status.reason",
},
DocumentationLink: docLinkK8sClusterReceiver,
},
{
@@ -220,6 +236,10 @@ var daemonsetsSpec = checkSpec{
"k8s.daemonset.desired_scheduled_nodes",
"k8s.daemonset.current_scheduled_nodes",
},
OptionalMetrics: []string{
"k8s.pod.status_reason",
"k8s.container.status.reason",
},
DocumentationLink: docLinkK8sClusterReceiver,
},
{
@@ -258,6 +278,10 @@ var statefulsetsSpec = checkSpec{
"k8s.statefulset.desired_pods",
"k8s.statefulset.current_pods",
},
OptionalMetrics: []string{
"k8s.pod.status_reason",
"k8s.container.status.reason",
},
DocumentationLink: docLinkK8sClusterReceiver,
},
{
@@ -298,6 +322,10 @@ var jobsSpec = checkSpec{
"k8s.job.failed_pods",
"k8s.job.successful_pods",
},
OptionalMetrics: []string{
"k8s.pod.status_reason",
"k8s.container.status.reason",
},
DocumentationLink: docLinkK8sClusterReceiver,
},
{
@@ -324,8 +352,12 @@ var namespacesSpec = checkSpec{
DocumentationLink: docLinkKubeletStatsReceiver,
},
{
Component: componentK8sClusterReceiver,
DefaultMetrics: []string{"k8s.pod.phase"},
Component: componentK8sClusterReceiver,
DefaultMetrics: []string{"k8s.pod.phase"},
OptionalMetrics: []string{
"k8s.pod.status_reason",
"k8s.container.status.reason",
},
DocumentationLink: docLinkK8sClusterReceiver,
},
{
@@ -360,6 +392,10 @@ var clustersSpec = checkSpec{
"k8s.node.condition_ready", // node counts by readiness
"k8s.pod.phase", // pod counts per cluster by phase
},
OptionalMetrics: []string{
"k8s.pod.status_reason",
"k8s.container.status.reason",
},
DocumentationLink: docLinkK8sClusterReceiver,
},
{

View File

@@ -20,6 +20,7 @@ func buildClusterRecords(
metadataMap map[string]map[string]string,
nodeConditionCountsMap map[string]nodeConditionCounts,
podPhaseCountsMap map[string]podPhaseCounts,
podStatusCounts map[string]podStatusCounts,
) []inframonitoringtypes.ClusterRecord {
metricsMap := parseFullQueryResponse(resp, groupBy)
@@ -69,6 +70,10 @@ func buildClusterRecords(
}
}
if podStatusCountsForGroup, ok := podStatusCounts[compositeKey]; ok {
record.PodCountsByStatus = podStatusCountsToResponse(podStatusCountsForGroup)
}
if attrs, ok := metadataMap[compositeKey]; ok {
for k, v := range attrs {
record.Meta[k] = v

View File

@@ -27,6 +27,8 @@ var clustersTableMetricNamesList = []string{
"k8s.node.allocatable_memory",
"k8s.node.condition_ready", //TODO(nikhilmantri0902): should these metrics be used to count groups k8s.node.condition_ready and k8s.pod.phase
"k8s.pod.phase",
"k8s.pod.status_reason",
"k8s.container.status.reason",
}
var clusterAttrKeysForMetadata = []string{

View File

@@ -19,6 +19,7 @@ func buildDaemonSetRecords(
groupBy []qbtypes.GroupByKey,
metadataMap map[string]map[string]string,
phaseCounts map[string]podPhaseCounts,
podStatusCounts map[string]podStatusCounts,
) []inframonitoringtypes.DaemonSetRecord {
metricsMap := parseFullQueryResponse(resp, groupBy)
@@ -77,6 +78,10 @@ func buildDaemonSetRecords(
}
}
if podStatusCountsForGroup, ok := podStatusCounts[compositeKey]; ok {
record.PodCountsByStatus = podStatusCountsToResponse(podStatusCountsForGroup)
}
if attrs, ok := metadataMap[compositeKey]; ok {
for k, v := range attrs {
record.Meta[k] = v

View File

@@ -23,6 +23,8 @@ var daemonSetNameGroupByKey = qbtypes.GroupByKey{
// response to short-circuit cleanly when the phase metric is absent.
var daemonSetsTableMetricNamesList = []string{
"k8s.pod.phase",
"k8s.pod.status_reason",
"k8s.container.status.reason",
"k8s.pod.cpu.usage",
"k8s.pod.cpu_request_utilization",
"k8s.pod.cpu_limit_utilization",

View File

@@ -19,6 +19,7 @@ func buildDeploymentRecords(
groupBy []qbtypes.GroupByKey,
metadataMap map[string]map[string]string,
phaseCounts map[string]podPhaseCounts,
podStatusCounts map[string]podStatusCounts,
) []inframonitoringtypes.DeploymentRecord {
metricsMap := parseFullQueryResponse(resp, groupBy)
@@ -77,6 +78,10 @@ func buildDeploymentRecords(
}
}
if podStatusCountsForGroup, ok := podStatusCounts[compositeKey]; ok {
record.PodCountsByStatus = podStatusCountsToResponse(podStatusCountsForGroup)
}
if attrs, ok := metadataMap[compositeKey]; ok {
for k, v := range attrs {
record.Meta[k] = v

View File

@@ -23,6 +23,8 @@ var deploymentNameGroupByKey = qbtypes.GroupByKey{
// response to short-circuit cleanly when the phase metric is absent.
var deploymentsTableMetricNamesList = []string{
"k8s.pod.phase",
"k8s.pod.status_reason",
"k8s.container.status.reason",
"k8s.pod.cpu.usage",
"k8s.pod.cpu_request_utilization",
"k8s.pod.cpu_limit_utilization",

View File

@@ -440,6 +440,30 @@ func (m *module) buildFilterClause(ctx context.Context, filter *qbtypes.Filter,
return whereClause.WhereClause, nil
}
// mergeQueryWarnings combines any number of query warnings. It is nil-safe and
// skips nil entries. The first non-nil warning becomes the primary; each
// subsequent one contributes its message (as an additional warning) and its
// own additional warnings. Returns nil when all inputs are nil.
func mergeQueryWarnings(warnings ...*qbtypes.QueryWarnData) *qbtypes.QueryWarnData {
var merged *qbtypes.QueryWarnData
for _, w := range warnings {
if w == nil {
continue
}
if merged == nil {
// Copy so we don't mutate the caller's warning.
primary := *w
merged = &primary
continue
}
if w.Message != "" {
merged.Warnings = append(merged.Warnings, qbtypes.QueryWarnDataAdditional{Message: w.Message})
}
merged.Warnings = append(merged.Warnings, w.Warnings...)
}
return merged
}
// NOTE: this method is not specific to infra monitoring — it queries attributes_metadata generically.
// Consider moving to telemetryMetaStore when a second use case emerges.
//

View File

@@ -26,6 +26,60 @@ type podPhaseCounts struct {
Unknown int
}
// podStatusCounts holds per-group pod counts bucketed by latest kubectl-style
// display status in window. Mirrors inframonitoringtypes.PodCountsByStatus.
type podStatusCounts struct {
// Phase fallback.
Pending int
Running int
Failed int
Unknown int
// Container-level reasons.
CrashLoopBackOff int
ImagePullBackOff int
ErrImagePull int
CreateContainerConfigError int
ContainerCreating int
OOMKilled int
Completed int
Error int
ContainerCannotRun int
// Pod-level reasons.
Evicted int
NodeAffinity int
NodeLost int
Shutdown int
UnexpectedAdmissionError int
}
// podStatusCountsToResponse copies the internal per-group status counts into the
// public response struct. Shared by every entity that surfaces pod status
// counts (pods, nodes, namespaces, clusters, workloads).
func podStatusCountsToResponse(podStatuses podStatusCounts) inframonitoringtypes.PodCountsByStatus {
return inframonitoringtypes.PodCountsByStatus{
Pending: podStatuses.Pending,
Running: podStatuses.Running,
Failed: podStatuses.Failed,
Unknown: podStatuses.Unknown,
CrashLoopBackOff: podStatuses.CrashLoopBackOff,
ImagePullBackOff: podStatuses.ImagePullBackOff,
ErrImagePull: podStatuses.ErrImagePull,
CreateContainerConfigError: podStatuses.CreateContainerConfigError,
ContainerCreating: podStatuses.ContainerCreating,
OOMKilled: podStatuses.OOMKilled,
Completed: podStatuses.Completed,
Error: podStatuses.Error,
ContainerCannotRun: podStatuses.ContainerCannotRun,
Evicted: podStatuses.Evicted,
NodeAffinity: podStatuses.NodeAffinity,
NodeLost: podStatuses.NodeLost,
Shutdown: podStatuses.Shutdown,
UnexpectedAdmissionError: podStatuses.UnexpectedAdmissionError,
}
}
// nodeConditionCounts holds per-group node counts bucketed by latest condition_ready in window.
type nodeConditionCounts struct {
Ready int

View File

@@ -19,6 +19,7 @@ func buildJobRecords(
groupBy []qbtypes.GroupByKey,
metadataMap map[string]map[string]string,
phaseCounts map[string]podPhaseCounts,
podStatusCounts map[string]podStatusCounts,
) []inframonitoringtypes.JobRecord {
metricsMap := parseFullQueryResponse(resp, groupBy)
@@ -85,6 +86,10 @@ func buildJobRecords(
}
}
if podStatusCountsForGroup, ok := podStatusCounts[compositeKey]; ok {
record.PodCountsByStatus = podStatusCountsToResponse(podStatusCountsForGroup)
}
if attrs, ok := metadataMap[compositeKey]; ok {
for k, v := range attrs {
record.Meta[k] = v

View File

@@ -23,6 +23,8 @@ var jobNameGroupByKey = qbtypes.GroupByKey{
// response to short-circuit cleanly when the phase metric is absent.
var jobsTableMetricNamesList = []string{
"k8s.pod.phase",
"k8s.pod.status_reason",
"k8s.container.status.reason",
"k8s.pod.cpu.usage",
"k8s.pod.cpu_request_utilization",
"k8s.pod.cpu_limit_utilization",

View File

@@ -17,6 +17,7 @@ import (
qbtypes "github.com/SigNoz/signoz/pkg/types/querybuildertypes/querybuildertypesv5"
"github.com/SigNoz/signoz/pkg/types/telemetrytypes"
"github.com/SigNoz/signoz/pkg/valuer"
"golang.org/x/sync/errgroup"
)
type module struct {
@@ -213,23 +214,37 @@ func (m *module) ListHosts(ctx context.Context, orgID valuer.UUID, req *inframon
}
fullQueryReq := buildFullQueryRequest(req.Start, req.End, hostsFilterExpr, req.GroupBy, pageGroups, m.newListHostsQuery())
queryResp, err := m.querier.QueryRange(ctx, orgID, fullQueryReq)
if err != nil {
return nil, err
}
// Compute per-group active/inactive host counts.
// When host.name is in groupBy, each row = one host, so counts are derived
// directly from activeHostsMap in buildHostRecords (no extra query needed).
// When host.name is not in groupBy, we need to run an additional query to get the counts per group for the current page,
// using the same filter expression as the main query (including user filters + page groups IN clause).
hostCounts := make(map[string]groupHostStatusCounts)
isHostNameInGroupBy := isKeyInGroupByAttrs(req.GroupBy, inframonitoringtypes.HostNameAttrKey)
var (
queryResp *qbtypes.QueryRangeResponse
hostCounts = make(map[string]groupHostStatusCounts)
)
g, gCtx := errgroup.WithContext(ctx)
g.Go(func() error {
var err error
queryResp, err = m.querier.QueryRange(gCtx, orgID, fullQueryReq)
return err
})
if !isHostNameInGroupBy {
hostCounts, err = m.getPerGroupHostStatusCounts(ctx, orgID, req, hostsTableMetricNamesList, pageGroups, sinceUnixMilli)
if err != nil {
return nil, err
}
g.Go(func() error {
var err error
hostCounts, err = m.getPerGroupHostStatusCounts(gCtx, orgID, req, hostsTableMetricNamesList, pageGroups, sinceUnixMilli)
return err
})
}
if err := g.Wait(); err != nil {
return nil, err
}
resp.Records = buildHostRecords(isHostNameInGroupBy, queryResp, pageGroups, req.GroupBy, metadataMap, activeHostsMap, hostCounts)
@@ -299,19 +314,45 @@ func (m *module) ListPods(ctx context.Context, orgID valuer.UUID, req *inframoni
}
fullQueryReq := buildFullQueryRequest(req.Start, req.End, filterExpr, req.GroupBy, pageGroups, m.newPodsTableListQuery())
queryResp, err := m.querier.QueryRange(ctx, orgID, fullQueryReq)
if err != nil {
return nil, err
}
phaseCounts, err := m.getPerGroupPodPhaseCounts(ctx, req.Start, req.End, req.Filter, req.GroupBy, pageGroups)
if err != nil {
var (
queryResp *qbtypes.QueryRangeResponse
phaseCounts map[string]podPhaseCounts
statusCounts map[string]podStatusCounts
statusWarning *qbtypes.QueryWarnData
restartCounts map[string]int64
)
g, gCtx := errgroup.WithContext(ctx)
g.Go(func() error {
var err error
queryResp, err = m.querier.QueryRange(gCtx, orgID, fullQueryReq)
return err
})
g.Go(func() error {
var err error
phaseCounts, err = m.getPerGroupPodPhaseCounts(gCtx, req.Start, req.End, req.Filter, req.GroupBy, pageGroups)
return err
})
g.Go(func() error {
var err error
statusCounts, statusWarning, err = m.getPerGroupPodStatusCountsWithReqMetricChecks(gCtx, req.Start, req.End, req.Filter, req.GroupBy, pageGroups)
return err
})
g.Go(func() error {
var err error
restartCounts, err = m.getPerGroupPodRestartCounts(gCtx, req.Start, req.End, req.Filter, req.GroupBy, pageGroups)
return err
})
if err := g.Wait(); err != nil {
return nil, err
}
isPodUIDInGroupBy := isKeyInGroupByAttrs(req.GroupBy, podUIDAttrKey)
resp.Records = buildPodRecords(isPodUIDInGroupBy, queryResp, pageGroups, req.GroupBy, metadataMap, phaseCounts, req.End)
resp.Warning = queryResp.Warning
resp.Records = buildPodRecords(isPodUIDInGroupBy, queryResp, pageGroups, req.GroupBy, metadataMap, phaseCounts, statusCounts, restartCounts, req.End)
resp.Warning = mergeQueryWarnings(queryResp.Warning, statusWarning)
return resp, nil
}
@@ -377,24 +418,45 @@ func (m *module) ListNodes(ctx context.Context, orgID valuer.UUID, req *inframon
}
fullQueryReq := buildFullQueryRequest(req.Start, req.End, filterExpr, req.GroupBy, pageGroups, m.newNodesTableListQuery())
queryResp, err := m.querier.QueryRange(ctx, orgID, fullQueryReq)
if err != nil {
return nil, err
}
nodeConditionCounts, err := m.getPerGroupNodeConditionCounts(ctx, req.Start, req.End, req.Filter, req.GroupBy, pageGroups)
if err != nil {
return nil, err
}
var (
queryResp *qbtypes.QueryRangeResponse
nodeConditionCounts map[string]nodeConditionCounts
podPhaseCounts map[string]podPhaseCounts
podStatusCounts map[string]podStatusCounts
podStatusWarning *qbtypes.QueryWarnData
)
podPhaseCounts, err := m.getPerGroupPodPhaseCounts(ctx, req.Start, req.End, req.Filter, req.GroupBy, pageGroups)
if err != nil {
g, gCtx := errgroup.WithContext(ctx)
g.Go(func() error {
var err error
queryResp, err = m.querier.QueryRange(gCtx, orgID, fullQueryReq)
return err
})
g.Go(func() error {
var err error
nodeConditionCounts, err = m.getPerGroupNodeConditionCounts(gCtx, req.Start, req.End, req.Filter, req.GroupBy, pageGroups)
return err
})
g.Go(func() error {
var err error
podPhaseCounts, err = m.getPerGroupPodPhaseCounts(gCtx, req.Start, req.End, req.Filter, req.GroupBy, pageGroups)
return err
})
g.Go(func() error {
var err error
podStatusCounts, podStatusWarning, err = m.getPerGroupPodStatusCountsWithReqMetricChecks(gCtx, req.Start, req.End, req.Filter, req.GroupBy, pageGroups)
return err
})
if err := g.Wait(); err != nil {
return nil, err
}
isNodeNameInGroupBy := isKeyInGroupByAttrs(req.GroupBy, inframonitoringtypes.NodeNameAttrKey)
resp.Records = buildNodeRecords(isNodeNameInGroupBy, queryResp, pageGroups, req.GroupBy, metadataMap, nodeConditionCounts, podPhaseCounts)
resp.Warning = queryResp.Warning
resp.Records = buildNodeRecords(isNodeNameInGroupBy, queryResp, pageGroups, req.GroupBy, metadataMap, nodeConditionCounts, podPhaseCounts, podStatusCounts)
resp.Warning = mergeQueryWarnings(queryResp.Warning, podStatusWarning)
return resp, nil
}
@@ -460,18 +522,38 @@ func (m *module) ListNamespaces(ctx context.Context, orgID valuer.UUID, req *inf
}
fullQueryReq := buildFullQueryRequest(req.Start, req.End, filterExpr, req.GroupBy, pageGroups, m.newNamespacesTableListQuery())
queryResp, err := m.querier.QueryRange(ctx, orgID, fullQueryReq)
if err != nil {
var (
queryResp *qbtypes.QueryRangeResponse
phaseCounts map[string]podPhaseCounts
podStatusCounts map[string]podStatusCounts
podStatusWarning *qbtypes.QueryWarnData
)
g, gCtx := errgroup.WithContext(ctx)
g.Go(func() error {
var err error
queryResp, err = m.querier.QueryRange(gCtx, orgID, fullQueryReq)
return err
})
g.Go(func() error {
var err error
phaseCounts, err = m.getPerGroupPodPhaseCounts(gCtx, req.Start, req.End, req.Filter, req.GroupBy, pageGroups)
return err
})
g.Go(func() error {
var err error
podStatusCounts, podStatusWarning, err = m.getPerGroupPodStatusCountsWithReqMetricChecks(gCtx, req.Start, req.End, req.Filter, req.GroupBy, pageGroups)
return err
})
if err := g.Wait(); err != nil {
return nil, err
}
phaseCounts, err := m.getPerGroupPodPhaseCounts(ctx, req.Start, req.End, req.Filter, req.GroupBy, pageGroups)
if err != nil {
return nil, err
}
resp.Records = buildNamespaceRecords(queryResp, pageGroups, req.GroupBy, metadataMap, phaseCounts)
resp.Warning = queryResp.Warning
resp.Records = buildNamespaceRecords(queryResp, pageGroups, req.GroupBy, metadataMap, phaseCounts, podStatusCounts)
resp.Warning = mergeQueryWarnings(queryResp.Warning, podStatusWarning)
return resp, nil
}
@@ -537,25 +619,46 @@ func (m *module) ListClusters(ctx context.Context, orgID valuer.UUID, req *infra
}
fullQueryReq := buildFullQueryRequest(req.Start, req.End, filterExpr, req.GroupBy, pageGroups, m.newClustersTableListQuery())
queryResp, err := m.querier.QueryRange(ctx, orgID, fullQueryReq)
if err != nil {
return nil, err
}
// With default groupBy [k8s.cluster.name], counts are bucketed per cluster;
// with a custom groupBy, they aggregate across clusters in that group.
nodeConditionCountsMap, err := m.getPerGroupNodeConditionCounts(ctx, req.Start, req.End, req.Filter, req.GroupBy, pageGroups)
if err != nil {
var (
queryResp *qbtypes.QueryRangeResponse
nodeConditionCountsMap map[string]nodeConditionCounts
podPhaseCountsMap map[string]podPhaseCounts
podStatusCounts map[string]podStatusCounts
podStatusWarning *qbtypes.QueryWarnData
)
g, gCtx := errgroup.WithContext(ctx)
g.Go(func() error {
var err error
queryResp, err = m.querier.QueryRange(gCtx, orgID, fullQueryReq)
return err
})
g.Go(func() error {
var err error
nodeConditionCountsMap, err = m.getPerGroupNodeConditionCounts(gCtx, req.Start, req.End, req.Filter, req.GroupBy, pageGroups)
return err
})
g.Go(func() error {
var err error
podPhaseCountsMap, err = m.getPerGroupPodPhaseCounts(gCtx, req.Start, req.End, req.Filter, req.GroupBy, pageGroups)
return err
})
g.Go(func() error {
var err error
podStatusCounts, podStatusWarning, err = m.getPerGroupPodStatusCountsWithReqMetricChecks(gCtx, req.Start, req.End, req.Filter, req.GroupBy, pageGroups)
return err
})
if err := g.Wait(); err != nil {
return nil, err
}
podPhaseCountsMap, err := m.getPerGroupPodPhaseCounts(ctx, req.Start, req.End, req.Filter, req.GroupBy, pageGroups)
if err != nil {
return nil, err
}
resp.Records = buildClusterRecords(queryResp, pageGroups, req.GroupBy, metadataMap, nodeConditionCountsMap, podPhaseCountsMap)
resp.Warning = queryResp.Warning
resp.Records = buildClusterRecords(queryResp, pageGroups, req.GroupBy, metadataMap, nodeConditionCountsMap, podPhaseCountsMap, podStatusCounts)
resp.Warning = mergeQueryWarnings(queryResp.Warning, podStatusWarning)
return resp, nil
}
@@ -705,18 +808,38 @@ func (m *module) ListDeployments(ctx context.Context, orgID valuer.UUID, req *in
}
fullQueryReq := buildFullQueryRequest(req.Start, req.End, filterExpr, req.GroupBy, pageGroups, m.newDeploymentsTableListQuery())
queryResp, err := m.querier.QueryRange(ctx, orgID, fullQueryReq)
if err != nil {
var (
queryResp *qbtypes.QueryRangeResponse
phaseCounts map[string]podPhaseCounts
podStatusCounts map[string]podStatusCounts
podStatusWarning *qbtypes.QueryWarnData
)
g, gCtx := errgroup.WithContext(ctx)
g.Go(func() error {
var err error
queryResp, err = m.querier.QueryRange(gCtx, orgID, fullQueryReq)
return err
})
g.Go(func() error {
var err error
phaseCounts, err = m.getPerGroupPodPhaseCounts(gCtx, req.Start, req.End, req.Filter, req.GroupBy, pageGroups)
return err
})
g.Go(func() error {
var err error
podStatusCounts, podStatusWarning, err = m.getPerGroupPodStatusCountsWithReqMetricChecks(gCtx, req.Start, req.End, req.Filter, req.GroupBy, pageGroups)
return err
})
if err := g.Wait(); err != nil {
return nil, err
}
phaseCounts, err := m.getPerGroupPodPhaseCounts(ctx, req.Start, req.End, req.Filter, req.GroupBy, pageGroups)
if err != nil {
return nil, err
}
resp.Records = buildDeploymentRecords(queryResp, pageGroups, req.GroupBy, metadataMap, phaseCounts)
resp.Warning = queryResp.Warning
resp.Records = buildDeploymentRecords(queryResp, pageGroups, req.GroupBy, metadataMap, phaseCounts, podStatusCounts)
resp.Warning = mergeQueryWarnings(queryResp.Warning, podStatusWarning)
return resp, nil
}
@@ -788,20 +911,40 @@ func (m *module) ListStatefulSets(ctx context.Context, orgID valuer.UUID, req *i
}
fullQueryReq := buildFullQueryRequest(req.Start, req.End, filterExpr, req.GroupBy, pageGroups, m.newStatefulSetsTableListQuery())
queryResp, err := m.querier.QueryRange(ctx, orgID, fullQueryReq)
if err != nil {
return nil, err
}
// Pods owned by a StatefulSet carry k8s.statefulset.name as a resource attribute,
// so default-groupBy gives per-statefulset phase counts automatically.
phaseCounts, err := m.getPerGroupPodPhaseCounts(ctx, req.Start, req.End, req.Filter, req.GroupBy, pageGroups)
if err != nil {
var (
queryResp *qbtypes.QueryRangeResponse
phaseCounts map[string]podPhaseCounts
podStatusCounts map[string]podStatusCounts
podStatusWarning *qbtypes.QueryWarnData
)
g, gCtx := errgroup.WithContext(ctx)
g.Go(func() error {
var err error
queryResp, err = m.querier.QueryRange(gCtx, orgID, fullQueryReq)
return err
})
g.Go(func() error {
var err error
phaseCounts, err = m.getPerGroupPodPhaseCounts(gCtx, req.Start, req.End, req.Filter, req.GroupBy, pageGroups)
return err
})
g.Go(func() error {
var err error
podStatusCounts, podStatusWarning, err = m.getPerGroupPodStatusCountsWithReqMetricChecks(gCtx, req.Start, req.End, req.Filter, req.GroupBy, pageGroups)
return err
})
if err := g.Wait(); err != nil {
return nil, err
}
resp.Records = buildStatefulSetRecords(queryResp, pageGroups, req.GroupBy, metadataMap, phaseCounts)
resp.Warning = queryResp.Warning
resp.Records = buildStatefulSetRecords(queryResp, pageGroups, req.GroupBy, metadataMap, phaseCounts, podStatusCounts)
resp.Warning = mergeQueryWarnings(queryResp.Warning, podStatusWarning)
return resp, nil
}
@@ -873,20 +1016,40 @@ func (m *module) ListJobs(ctx context.Context, orgID valuer.UUID, req *inframoni
}
fullQueryReq := buildFullQueryRequest(req.Start, req.End, filterExpr, req.GroupBy, pageGroups, m.newJobsTableListQuery())
queryResp, err := m.querier.QueryRange(ctx, orgID, fullQueryReq)
if err != nil {
return nil, err
}
// Pods owned by a Job carry k8s.job.name as a resource attribute, so default-groupBy
// gives per-job phase counts automatically.
phaseCounts, err := m.getPerGroupPodPhaseCounts(ctx, req.Start, req.End, req.Filter, req.GroupBy, pageGroups)
if err != nil {
var (
queryResp *qbtypes.QueryRangeResponse
phaseCounts map[string]podPhaseCounts
podStatusCounts map[string]podStatusCounts
podStatusWarning *qbtypes.QueryWarnData
)
g, gCtx := errgroup.WithContext(ctx)
g.Go(func() error {
var err error
queryResp, err = m.querier.QueryRange(gCtx, orgID, fullQueryReq)
return err
})
g.Go(func() error {
var err error
phaseCounts, err = m.getPerGroupPodPhaseCounts(gCtx, req.Start, req.End, req.Filter, req.GroupBy, pageGroups)
return err
})
g.Go(func() error {
var err error
podStatusCounts, podStatusWarning, err = m.getPerGroupPodStatusCountsWithReqMetricChecks(gCtx, req.Start, req.End, req.Filter, req.GroupBy, pageGroups)
return err
})
if err := g.Wait(); err != nil {
return nil, err
}
resp.Records = buildJobRecords(queryResp, pageGroups, req.GroupBy, metadataMap, phaseCounts)
resp.Warning = queryResp.Warning
resp.Records = buildJobRecords(queryResp, pageGroups, req.GroupBy, metadataMap, phaseCounts, podStatusCounts)
resp.Warning = mergeQueryWarnings(queryResp.Warning, podStatusWarning)
return resp, nil
}
@@ -958,20 +1121,40 @@ func (m *module) ListDaemonSets(ctx context.Context, orgID valuer.UUID, req *inf
}
fullQueryReq := buildFullQueryRequest(req.Start, req.End, filterExpr, req.GroupBy, pageGroups, m.newDaemonSetsTableListQuery())
queryResp, err := m.querier.QueryRange(ctx, orgID, fullQueryReq)
if err != nil {
return nil, err
}
// Pods owned by a DaemonSet carry k8s.daemonset.name as a resource attribute,
// so default-groupBy gives per-daemonset phase counts automatically.
phaseCounts, err := m.getPerGroupPodPhaseCounts(ctx, req.Start, req.End, req.Filter, req.GroupBy, pageGroups)
if err != nil {
var (
queryResp *qbtypes.QueryRangeResponse
phaseCounts map[string]podPhaseCounts
podStatusCounts map[string]podStatusCounts
podStatusWarning *qbtypes.QueryWarnData
)
g, gCtx := errgroup.WithContext(ctx)
g.Go(func() error {
var err error
queryResp, err = m.querier.QueryRange(gCtx, orgID, fullQueryReq)
return err
})
g.Go(func() error {
var err error
phaseCounts, err = m.getPerGroupPodPhaseCounts(gCtx, req.Start, req.End, req.Filter, req.GroupBy, pageGroups)
return err
})
g.Go(func() error {
var err error
podStatusCounts, podStatusWarning, err = m.getPerGroupPodStatusCountsWithReqMetricChecks(gCtx, req.Start, req.End, req.Filter, req.GroupBy, pageGroups)
return err
})
if err := g.Wait(); err != nil {
return nil, err
}
resp.Records = buildDaemonSetRecords(queryResp, pageGroups, req.GroupBy, metadataMap, phaseCounts)
resp.Warning = queryResp.Warning
resp.Records = buildDaemonSetRecords(queryResp, pageGroups, req.GroupBy, metadataMap, phaseCounts, podStatusCounts)
resp.Warning = mergeQueryWarnings(queryResp.Warning, podStatusWarning)
return resp, nil
}

View File

@@ -18,6 +18,7 @@ func buildNamespaceRecords(
groupBy []qbtypes.GroupByKey,
metadataMap map[string]map[string]string,
phaseCounts map[string]podPhaseCounts,
podStatusCounts map[string]podStatusCounts,
) []inframonitoringtypes.NamespaceRecord {
metricsMap := parseFullQueryResponse(resp, groupBy)
@@ -52,6 +53,10 @@ func buildNamespaceRecords(
}
}
if podStatusCountsForGroup, ok := podStatusCounts[compositeKey]; ok {
record.PodCountsByStatus = podStatusCountsToResponse(podStatusCountsForGroup)
}
if attrs, ok := metadataMap[compositeKey]; ok {
for k, v := range attrs {
record.Meta[k] = v

View File

@@ -23,6 +23,8 @@ var namespacesTableMetricNamesList = []string{
"k8s.pod.cpu.usage",
"k8s.pod.memory.working_set",
"k8s.pod.phase",
"k8s.pod.status_reason",
"k8s.container.status.reason",
}
var namespaceAttrKeysForMetadata = []string{

View File

@@ -26,6 +26,7 @@ func buildNodeRecords(
metadataMap map[string]map[string]string,
nodeConditionCounts map[string]nodeConditionCounts,
podPhaseCounts map[string]podPhaseCounts,
podStatusCounts map[string]podStatusCounts,
) []inframonitoringtypes.NodeRecord {
metricsMap := parseFullQueryResponse(resp, groupBy)
@@ -86,6 +87,10 @@ func buildNodeRecords(
}
}
if podStatusCountsForGroup, ok := podStatusCounts[compositeKey]; ok {
record.PodCountsByStatus = podStatusCountsToResponse(podStatusCountsForGroup)
}
if attrs, ok := metadataMap[compositeKey]; ok {
for k, v := range attrs {
record.Meta[k] = v

View File

@@ -26,6 +26,8 @@ var nodesTableMetricNamesList = []string{
"k8s.node.allocatable_memory",
"k8s.node.condition_ready",
"k8s.pod.phase",
"k8s.pod.status_reason",
"k8s.container.status.reason",
}
var nodeAttrKeysForMetadata = []string{

View File

@@ -26,6 +26,8 @@ func buildPodRecords(
groupBy []qbtypes.GroupByKey,
metadataMap map[string]map[string]string,
phaseCounts map[string]podPhaseCounts,
statusCounts map[string]podStatusCounts,
restartCounts map[string]int64,
reqEnd int64,
) []inframonitoringtypes.PodRecord {
metricsMap := parseFullQueryResponse(resp, groupBy)
@@ -38,6 +40,8 @@ func buildPodRecords(
record := inframonitoringtypes.PodRecord{ // initialize with default values
PodUID: podUID,
PodPhase: inframonitoringtypes.PodPhaseNoData,
PodStatus: inframonitoringtypes.PodStatusNoData,
PodRestarts: -1,
PodCPU: -1,
PodCPURequest: -1,
PodCPULimit: -1,
@@ -95,6 +99,57 @@ func buildPodRecords(
}
}
if statusCountsForGroup, ok := statusCounts[compositeKey]; ok {
record.PodCountsByStatus = podStatusCountsToResponse(statusCountsForGroup)
// In list mode each group is one pod; the count==1 bucket identifies the status.
if isPodUIDInGroupBy {
switch {
case statusCountsForGroup.Pending == 1:
record.PodStatus = inframonitoringtypes.PodStatusPending
case statusCountsForGroup.Running == 1:
record.PodStatus = inframonitoringtypes.PodStatusRunning
case statusCountsForGroup.Failed == 1:
record.PodStatus = inframonitoringtypes.PodStatusFailed
case statusCountsForGroup.Unknown == 1:
record.PodStatus = inframonitoringtypes.PodStatusUnknown
case statusCountsForGroup.CrashLoopBackOff == 1:
record.PodStatus = inframonitoringtypes.PodStatusCrashLoopBackOff
case statusCountsForGroup.ImagePullBackOff == 1:
record.PodStatus = inframonitoringtypes.PodStatusImagePullBackOff
case statusCountsForGroup.ErrImagePull == 1:
record.PodStatus = inframonitoringtypes.PodStatusErrImagePull
case statusCountsForGroup.CreateContainerConfigError == 1:
record.PodStatus = inframonitoringtypes.PodStatusCreateContainerConfigError
case statusCountsForGroup.ContainerCreating == 1:
record.PodStatus = inframonitoringtypes.PodStatusContainerCreating
case statusCountsForGroup.OOMKilled == 1:
record.PodStatus = inframonitoringtypes.PodStatusOOMKilled
case statusCountsForGroup.Completed == 1:
record.PodStatus = inframonitoringtypes.PodStatusCompleted
case statusCountsForGroup.Error == 1:
record.PodStatus = inframonitoringtypes.PodStatusError
case statusCountsForGroup.ContainerCannotRun == 1:
record.PodStatus = inframonitoringtypes.PodStatusContainerCannotRun
case statusCountsForGroup.Evicted == 1:
record.PodStatus = inframonitoringtypes.PodStatusEvicted
case statusCountsForGroup.NodeAffinity == 1:
record.PodStatus = inframonitoringtypes.PodStatusNodeAffinity
case statusCountsForGroup.NodeLost == 1:
record.PodStatus = inframonitoringtypes.PodStatusNodeLost
case statusCountsForGroup.Shutdown == 1:
record.PodStatus = inframonitoringtypes.PodStatusShutdown
case statusCountsForGroup.UnexpectedAdmissionError == 1:
record.PodStatus = inframonitoringtypes.PodStatusUnexpectedAdmissionError
}
}
}
// Restart count: pod's own sum (list mode) or group total (grouped mode).
if restartCountForGroup, ok := restartCounts[compositeKey]; ok {
record.PodRestarts = restartCountForGroup
}
if attrs, ok := metadataMap[compositeKey]; ok {
// podAge only makes sense when pod uid is in groupBy. Otherwise the
// group can contain multiple pods with different start times.
@@ -334,3 +389,519 @@ func (m *module) getPerGroupPodPhaseCounts(
}
return result, nil
}
// getPerGroupPodStatusCountsWithReqMetricChecks gates getPerGroupPodStatusCounts
// on the required metrics being present. If any of podStatusMetricNamesList has
// never been reported, it skips the query and returns a warning instead (the
// status query would otherwise silently degrade to bare phase). Otherwise it
// runs the query. The returned counts map is empty (never nil) when gated off.
func (m *module) getPerGroupPodStatusCountsWithReqMetricChecks(
ctx context.Context,
start, end int64,
filter *qbtypes.Filter,
groupBy []qbtypes.GroupByKey,
pageGroups []map[string]string,
) (map[string]podStatusCounts, *qbtypes.QueryWarnData, error) {
present, err := m.getMetricsExistence(ctx, podStatusMetricNamesList)
if err != nil {
return nil, nil, err
}
var missing []string
for _, name := range podStatusMetricNamesList {
if !present[name] {
missing = append(missing, name)
}
}
if len(missing) > 0 {
warning := &qbtypes.QueryWarnData{
Message: fmt.Sprintf(
"Pod status could not be computed: required metric(s) not found: %s. "+
"Enable the optional k8s.pod.status_reason and k8s.container.status.reason "+
"metrics in the k8s_cluster receiver to see pod statuses.",
strings.Join(missing, ", "),
),
Url: docLinkK8sClusterReceiver,
}
return map[string]podStatusCounts{}, warning, nil
}
counts, err := m.getPerGroupPodStatusCounts(ctx, start, end, filter, groupBy, pageGroups)
if err != nil {
return nil, nil, err
}
return counts, nil, nil
}
// getPerGroupPodStatusCounts computes per-group pod counts bucketed by each
// pod's latest kubectl-style display status in the requested window. Caller
// must ensure the required metrics exist (getPerGroupPodStatusCountsWithReqMetricChecks).
// Pipeline (mirrors getPerGroupPodPhaseCounts, more CTEs):
//
// phase_fps / phase_per_pod: latest k8s.pod.phase per pod (+ groupBy cols).
// pod_reason_fps / pod_reason_per_pod: latest k8s.pod.status_reason per pod.
// container_reason_fps / container_reason_per_pod:
// highest-priority active k8s.container.status.reason per pod.
// pod_status: display status per pod (container > pod reason > phase).
// countPodsPerStatus: per-group uniqExactIf into the fixed status buckets.
//
// Groups absent from the result map have implicit zero counts (caller default).
func (m *module) getPerGroupPodStatusCounts(
ctx context.Context,
start, end int64,
filter *qbtypes.Filter,
groupBy []qbtypes.GroupByKey,
pageGroups []map[string]string,
) (map[string]podStatusCounts, error) {
if len(pageGroups) == 0 || len(groupBy) == 0 {
return map[string]podStatusCounts{}, nil
}
// Merge user filter with page-groups IN clauses.
userFilterExpr := ""
if filter != nil {
userFilterExpr = filter.Expression
}
mergedFilterExpr := mergeFilterExpressions(userFilterExpr, buildPageGroupsFilterExpr(pageGroups))
samplesStartMs, flooredEndMs, tsAdjustedStart, _, localTimeSeriesTable, distributedSamplesTable, _ := alignedMetricWindow(start, end)
valueCol := telemetrymetrics.ValueColumnForSamplesTable(distributedSamplesTable)
// Build the merged filter clause once; it's identical across the three fps
// CTEs, and buildFilterClause hits the metadata store + parses the
// expression, so we don't want to repeat it per CTE. AddWhereClause only
// reads the clause, so the same instance is safe to attach to each builder.
var (
filterClause *sqlbuilder.WhereClause
err error
)
if mergedFilterExpr != "" {
filterClause, err = m.buildFilterClause(ctx, &qbtypes.Filter{Expression: mergedFilterExpr}, start, end)
if err != nil {
return nil, err
}
}
// ----- phase_fps (carries groupBy cols) -----
phaseFps := sqlbuilder.NewSelectBuilder()
phaseFpsCols := []string{
"fingerprint",
fmt.Sprintf("JSONExtractString(labels, %s) AS pod_uid", phaseFps.Var(podUIDAttrKey)),
}
for _, key := range groupBy {
phaseFpsCols = append(phaseFpsCols,
fmt.Sprintf("JSONExtractString(labels, %s) AS %s", phaseFps.Var(key.Name), quoteIdentifier(key.Name)),
)
}
phaseFps.Select(phaseFpsCols...)
phaseFps.From(fmt.Sprintf("%s.%s", telemetrymetrics.DBName, localTimeSeriesTable))
phaseFps.Where(
phaseFps.E("metric_name", podPhaseMetricName),
phaseFps.GE("unix_milli", tsAdjustedStart),
phaseFps.LE("unix_milli", flooredEndMs),
)
if filterClause != nil {
phaseFps.AddWhereClause(filterClause)
}
phaseFpsGroupBy := []string{"fingerprint", "pod_uid"}
for _, key := range groupBy {
phaseFpsGroupBy = append(phaseFpsGroupBy, quoteIdentifier(key.Name))
}
phaseFps.GroupBy(phaseFpsGroupBy...)
phaseFpsSQL, phaseFpsArgs := phaseFps.BuildWithFlavor(sqlbuilder.ClickHouse)
// ----- phase_per_pod -----
phasePerPod := sqlbuilder.NewSelectBuilder()
phasePerPodCols := []string{"fps.pod_uid AS pod_uid"}
for _, key := range groupBy {
col := quoteIdentifier(key.Name)
phasePerPodCols = append(phasePerPodCols, fmt.Sprintf("argMax(fps.%s, samples.unix_milli) AS %s", col, col))
}
phasePerPodCols = append(phasePerPodCols, fmt.Sprintf("argMax(samples.%s, samples.unix_milli) AS phase_value", valueCol))
phasePerPod.Select(phasePerPodCols...)
phasePerPod.From(fmt.Sprintf(
"%s.%s AS samples INNER JOIN phase_fps AS fps ON samples.fingerprint = fps.fingerprint",
telemetrymetrics.DBName, distributedSamplesTable,
))
phasePerPod.Where(
phasePerPod.E("samples.metric_name", podPhaseMetricName),
phasePerPod.GE("samples.unix_milli", samplesStartMs),
phasePerPod.L("samples.unix_milli", flooredEndMs),
"fps.pod_uid != ''",
)
phasePerPod.GroupBy("pod_uid")
phasePerPodSQL, phasePerPodArgs := phasePerPod.BuildWithFlavor(sqlbuilder.ClickHouse)
// ----- pod_reason_fps -----
podReasonFps := sqlbuilder.NewSelectBuilder()
podReasonFps.Select(
"fingerprint",
fmt.Sprintf("JSONExtractString(labels, %s) AS pod_uid", podReasonFps.Var(podUIDAttrKey)),
)
podReasonFps.From(fmt.Sprintf("%s.%s", telemetrymetrics.DBName, localTimeSeriesTable))
podReasonFps.Where(
podReasonFps.E("metric_name", podStatusReasonMetricName),
podReasonFps.GE("unix_milli", tsAdjustedStart),
podReasonFps.LE("unix_milli", flooredEndMs),
)
if filterClause != nil {
podReasonFps.AddWhereClause(filterClause)
}
podReasonFps.GroupBy("fingerprint", "pod_uid")
podReasonFpsSQL, podReasonFpsArgs := podReasonFps.BuildWithFlavor(sqlbuilder.ClickHouse)
// ----- pod_reason_per_pod -----
podReasonPerPod := sqlbuilder.NewSelectBuilder()
podReasonPerPod.Select(
"fps.pod_uid AS pod_uid",
fmt.Sprintf("argMax(samples.%s, samples.unix_milli) AS reason_value", valueCol),
)
podReasonPerPod.From(fmt.Sprintf(
"%s.%s AS samples INNER JOIN pod_reason_fps AS fps ON samples.fingerprint = fps.fingerprint",
telemetrymetrics.DBName, distributedSamplesTable,
))
podReasonPerPod.Where(
podReasonPerPod.E("samples.metric_name", podStatusReasonMetricName),
podReasonPerPod.GE("samples.unix_milli", samplesStartMs),
podReasonPerPod.L("samples.unix_milli", flooredEndMs),
"fps.pod_uid != ''",
)
podReasonPerPod.GroupBy("pod_uid")
podReasonPerPodSQL, podReasonPerPodArgs := podReasonPerPod.BuildWithFlavor(sqlbuilder.ClickHouse)
// ----- container_reason_fps -----
containerReasonFps := sqlbuilder.NewSelectBuilder()
containerReasonFps.Select(
"fingerprint",
fmt.Sprintf("JSONExtractString(labels, %s) AS pod_uid", containerReasonFps.Var(podUIDAttrKey)),
fmt.Sprintf("JSONExtractString(labels, %s) AS container_name", containerReasonFps.Var(containerNameAttrKey)),
fmt.Sprintf("JSONExtractString(labels, %s) AS reason", containerReasonFps.Var(containerStatusReasonAttrKey)),
)
containerReasonFps.From(fmt.Sprintf("%s.%s", telemetrymetrics.DBName, localTimeSeriesTable))
containerReasonFps.Where(
containerReasonFps.E("metric_name", containerStatusReasonMetricName),
containerReasonFps.GE("unix_milli", tsAdjustedStart),
containerReasonFps.LE("unix_milli", flooredEndMs),
)
if filterClause != nil {
containerReasonFps.AddWhereClause(filterClause)
}
containerReasonFps.GroupBy("fingerprint", "pod_uid", "container_name", "reason")
containerReasonFpsSQL, containerReasonFpsArgs := containerReasonFps.BuildWithFlavor(sqlbuilder.ClickHouse)
// ----- container_reason_per_pod -----
// Inner: latest value per (pod, container, reason) -> kills stale
// fingerprints from old container incarnations; keep only active (=1).
// Outer: highest-priority active reason per pod (waiting > terminated).
priorityCase := "CASE fps.reason " +
"WHEN 'CrashLoopBackOff' THEN 8 " +
"WHEN 'ImagePullBackOff' THEN 7 " +
"WHEN 'ErrImagePull' THEN 6 " +
"WHEN 'CreateContainerConfigError' THEN 5 " +
"WHEN 'ContainerCreating' THEN 4 " +
"WHEN 'OOMKilled' THEN 3 " +
"WHEN 'Error' THEN 2 " +
"WHEN 'ContainerCannotRun' THEN 1 " +
"ELSE 0 END"
containerInner := sqlbuilder.NewSelectBuilder()
containerInner.Select(
"fps.pod_uid AS pod_uid",
"fps.container_name AS container_name",
"fps.reason AS reason",
fmt.Sprintf("argMax(samples.%s, samples.unix_milli) AS is_active", valueCol),
priorityCase+" AS priority",
)
containerInner.From(fmt.Sprintf(
"%s.%s AS samples INNER JOIN container_reason_fps AS fps ON samples.fingerprint = fps.fingerprint",
telemetrymetrics.DBName, distributedSamplesTable,
))
containerInner.Where(
containerInner.E("samples.metric_name", containerStatusReasonMetricName),
containerInner.GE("samples.unix_milli", samplesStartMs),
containerInner.L("samples.unix_milli", flooredEndMs),
"fps.pod_uid != ''",
)
containerInner.GroupBy("fps.pod_uid", "fps.container_name", "fps.reason")
containerInner.Having("is_active = 1")
containerInnerSQL, containerInnerArgs := containerInner.BuildWithFlavor(sqlbuilder.ClickHouse)
containerPerPodSQL := fmt.Sprintf(
"SELECT pod_uid, argMax(reason, priority) AS active_reason FROM (%s) GROUP BY pod_uid",
containerInnerSQL,
)
// ----- pod_status (display status per pod) -----
// container reason > pod-level reason > phase fallback. Numeric literals
// match the k8s.pod.status_reason and k8s.pod.phase metric encodings.
displayStatusExpr := "multiIf(" +
"cr.active_reason != '', cr.active_reason, " +
"pr.reason_value = 1, 'Evicted', " +
"pr.reason_value = 2, 'NodeAffinity', " +
"pr.reason_value = 3, 'NodeLost', " +
"pr.reason_value = 4, 'Shutdown', " +
"pr.reason_value = 5, 'UnexpectedAdmissionError', " +
"pp.phase_value = 1, 'Pending', " +
"pp.phase_value = 2, 'Running', " +
"pp.phase_value = 3, 'Completed', " +
"pp.phase_value = 4, 'Failed', " +
"pp.phase_value = 5, 'Unknown', " +
"'Unknown')"
podStatusSelectCols := []string{"pp.pod_uid AS pod_uid"}
for _, key := range groupBy {
col := quoteIdentifier(key.Name)
podStatusSelectCols = append(podStatusSelectCols, fmt.Sprintf("pp.%s AS %s", col, col))
}
podStatusSelectCols = append(podStatusSelectCols, displayStatusExpr+" AS display_status")
podStatusSQL := fmt.Sprintf(
"SELECT %s FROM phase_per_pod AS pp "+
"LEFT JOIN pod_reason_per_pod AS pr ON pp.pod_uid = pr.pod_uid "+
"LEFT JOIN container_reason_per_pod AS cr ON pp.pod_uid = cr.pod_uid",
strings.Join(podStatusSelectCols, ", "),
)
// ----- countPodsPerStatus (outer SELECT) -----
// Fixed status order; MUST match the podStatusCounts assignment in the
// scan loop below.
statusCountCols := []string{
"uniqExactIf(pod_uid, display_status = 'Pending') AS pending_count",
"uniqExactIf(pod_uid, display_status = 'Running') AS running_count",
"uniqExactIf(pod_uid, display_status = 'Failed') AS failed_count",
"uniqExactIf(pod_uid, display_status = 'Unknown') AS unknown_count",
"uniqExactIf(pod_uid, display_status = 'CrashLoopBackOff') AS crash_loop_back_off_count",
"uniqExactIf(pod_uid, display_status = 'ImagePullBackOff') AS image_pull_back_off_count",
"uniqExactIf(pod_uid, display_status = 'ErrImagePull') AS err_image_pull_count",
"uniqExactIf(pod_uid, display_status = 'CreateContainerConfigError') AS create_container_config_error_count",
"uniqExactIf(pod_uid, display_status = 'ContainerCreating') AS container_creating_count",
"uniqExactIf(pod_uid, display_status = 'OOMKilled') AS oom_killed_count",
"uniqExactIf(pod_uid, display_status = 'Completed') AS completed_count",
"uniqExactIf(pod_uid, display_status = 'Error') AS error_count",
"uniqExactIf(pod_uid, display_status = 'ContainerCannotRun') AS container_cannot_run_count",
"uniqExactIf(pod_uid, display_status = 'Evicted') AS evicted_count",
"uniqExactIf(pod_uid, display_status = 'NodeAffinity') AS node_affinity_count",
"uniqExactIf(pod_uid, display_status = 'NodeLost') AS node_lost_count",
"uniqExactIf(pod_uid, display_status = 'Shutdown') AS shutdown_count",
"uniqExactIf(pod_uid, display_status = 'UnexpectedAdmissionError') AS unexpected_admission_error_count",
}
countSelectCols := make([]string, 0, len(groupBy)+len(statusCountCols))
countGroupBy := make([]string, 0, len(groupBy))
for _, key := range groupBy {
col := quoteIdentifier(key.Name)
countSelectCols = append(countSelectCols, col)
countGroupBy = append(countGroupBy, col)
}
countSelectCols = append(countSelectCols, statusCountCols...)
countSQL := fmt.Sprintf(
"SELECT %s FROM pod_status GROUP BY %s",
strings.Join(countSelectCols, ", "),
strings.Join(countGroupBy, ", "),
)
// Combine CTEs + outer. Arg order mirrors CTE declaration order.
cteFragments := []string{
fmt.Sprintf("phase_fps AS (%s)", phaseFpsSQL),
fmt.Sprintf("phase_per_pod AS (%s)", phasePerPodSQL),
fmt.Sprintf("pod_reason_fps AS (%s)", podReasonFpsSQL),
fmt.Sprintf("pod_reason_per_pod AS (%s)", podReasonPerPodSQL),
fmt.Sprintf("container_reason_fps AS (%s)", containerReasonFpsSQL),
fmt.Sprintf("container_reason_per_pod AS (%s)", containerPerPodSQL),
fmt.Sprintf("pod_status AS (%s)", podStatusSQL),
}
finalSQL := querybuilder.CombineCTEs(cteFragments) + countSQL
finalArgs := querybuilder.PrependArgs([][]any{
phaseFpsArgs, phasePerPodArgs,
podReasonFpsArgs, podReasonPerPodArgs,
containerReasonFpsArgs, containerInnerArgs,
}, nil)
rows, err := m.telemetryStore.ClickhouseDB().Query(ctx, finalSQL, finalArgs...)
if err != nil {
return nil, err
}
defer rows.Close()
result := make(map[string]podStatusCounts)
for rows.Next() {
groupVals := make([]string, len(groupBy))
counts := make([]uint64, len(statusCountCols))
scanPtrs := make([]any, 0, len(groupBy)+len(statusCountCols))
for i := range groupVals {
scanPtrs = append(scanPtrs, &groupVals[i])
}
for i := range counts {
scanPtrs = append(scanPtrs, &counts[i])
}
if err := rows.Scan(scanPtrs...); err != nil {
return nil, err
}
result[compositeKeyFromList(groupVals)] = podStatusCounts{
Pending: int(counts[0]),
Running: int(counts[1]),
Failed: int(counts[2]),
Unknown: int(counts[3]),
CrashLoopBackOff: int(counts[4]),
ImagePullBackOff: int(counts[5]),
ErrImagePull: int(counts[6]),
CreateContainerConfigError: int(counts[7]),
ContainerCreating: int(counts[8]),
OOMKilled: int(counts[9]),
Completed: int(counts[10]),
Error: int(counts[11]),
ContainerCannotRun: int(counts[12]),
Evicted: int(counts[13]),
NodeAffinity: int(counts[14]),
NodeLost: int(counts[15]),
Shutdown: int(counts[16]),
UnexpectedAdmissionError: int(counts[17]),
}
}
if err := rows.Err(); err != nil {
return nil, err
}
return result, nil
}
// getPerGroupPodRestartCounts computes the absolute pod restart count per group
// from k8s.container.restarts (default-enabled, so no existence gate). In list
// mode (groupBy=pod_uid) each group is one pod -> its restart count; in grouped
// mode it's the summed restarts across all pods in the group. Mirrors DD:
// argMax(value, unix_milli) per (pod, container) takes the current cumulative
// count from the latest incarnation (handling fingerprint staleness/pruning),
// then sum.
//
// restart_fps: fp ↔ (pod_uid, container_name, groupBy cols) from time_series.
// container_restarts: INNER JOIN samples, latest restartCount per (pod, container).
// (outer): per-group sum(restart_count).
//
// Groups absent from the result map have no data (caller default).
func (m *module) getPerGroupPodRestartCounts(
ctx context.Context,
start, end int64,
filter *qbtypes.Filter,
groupBy []qbtypes.GroupByKey,
pageGroups []map[string]string,
) (map[string]int64, error) {
if len(pageGroups) == 0 || len(groupBy) == 0 {
return map[string]int64{}, nil
}
// Merge user filter with page-groups IN clauses.
userFilterExpr := ""
if filter != nil {
userFilterExpr = filter.Expression
}
mergedFilterExpr := mergeFilterExpressions(userFilterExpr, buildPageGroupsFilterExpr(pageGroups))
samplesStartMs, flooredEndMs, tsAdjustedStart, _, localTimeSeriesTable, distributedSamplesTable, _ := alignedMetricWindow(start, end)
valueCol := telemetrymetrics.ValueColumnForSamplesTable(distributedSamplesTable)
var (
filterClause *sqlbuilder.WhereClause
err error
)
if mergedFilterExpr != "" {
filterClause, err = m.buildFilterClause(ctx, &qbtypes.Filter{Expression: mergedFilterExpr}, start, end)
if err != nil {
return nil, err
}
}
// ----- restart_fps (carries groupBy cols) -----
restartFps := sqlbuilder.NewSelectBuilder()
restartFpsCols := []string{
"fingerprint",
fmt.Sprintf("JSONExtractString(labels, %s) AS pod_uid", restartFps.Var(podUIDAttrKey)),
fmt.Sprintf("JSONExtractString(labels, %s) AS container_name", restartFps.Var(containerNameAttrKey)),
}
for _, key := range groupBy {
restartFpsCols = append(restartFpsCols,
fmt.Sprintf("JSONExtractString(labels, %s) AS %s", restartFps.Var(key.Name), quoteIdentifier(key.Name)),
)
}
restartFps.Select(restartFpsCols...)
restartFps.From(fmt.Sprintf("%s.%s", telemetrymetrics.DBName, localTimeSeriesTable))
restartFps.Where(
restartFps.E("metric_name", containerRestartsMetricName),
restartFps.GE("unix_milli", tsAdjustedStart),
restartFps.LE("unix_milli", flooredEndMs),
)
if filterClause != nil {
restartFps.AddWhereClause(filterClause)
}
restartFpsGroupBy := []string{"fingerprint", "pod_uid", "container_name"}
for _, key := range groupBy {
restartFpsGroupBy = append(restartFpsGroupBy, quoteIdentifier(key.Name))
}
restartFps.GroupBy(restartFpsGroupBy...)
restartFpsSQL, restartFpsArgs := restartFps.BuildWithFlavor(sqlbuilder.ClickHouse)
// ----- container_restarts (latest cumulative count per container) -----
containerRestarts := sqlbuilder.NewSelectBuilder()
containerRestartsCols := []string{
"fps.pod_uid AS pod_uid",
"fps.container_name AS container_name",
}
for _, key := range groupBy {
col := quoteIdentifier(key.Name)
containerRestartsCols = append(containerRestartsCols, fmt.Sprintf("argMax(fps.%s, samples.unix_milli) AS %s", col, col))
}
containerRestartsCols = append(containerRestartsCols, fmt.Sprintf("argMax(samples.%s, samples.unix_milli) AS restart_count", valueCol))
containerRestarts.Select(containerRestartsCols...)
containerRestarts.From(fmt.Sprintf(
"%s.%s AS samples INNER JOIN restart_fps AS fps ON samples.fingerprint = fps.fingerprint",
telemetrymetrics.DBName, distributedSamplesTable,
))
containerRestarts.Where(
containerRestarts.E("samples.metric_name", containerRestartsMetricName),
containerRestarts.GE("samples.unix_milli", samplesStartMs),
containerRestarts.L("samples.unix_milli", flooredEndMs),
"fps.pod_uid != ''",
)
containerRestarts.GroupBy("fps.pod_uid", "fps.container_name")
containerRestartsSQL, containerRestartsArgs := containerRestarts.BuildWithFlavor(sqlbuilder.ClickHouse)
// ----- outer: per-group sum across containers (hence across pods) -----
sumSelectCols := make([]string, 0, len(groupBy)+1)
sumGroupBy := make([]string, 0, len(groupBy))
for _, key := range groupBy {
col := quoteIdentifier(key.Name)
sumSelectCols = append(sumSelectCols, col)
sumGroupBy = append(sumGroupBy, col)
}
sumSelectCols = append(sumSelectCols, "sum(restart_count) AS total_restarts")
sumSQL := fmt.Sprintf(
"SELECT %s FROM container_restarts GROUP BY %s",
strings.Join(sumSelectCols, ", "),
strings.Join(sumGroupBy, ", "),
)
cteFragments := []string{
fmt.Sprintf("restart_fps AS (%s)", restartFpsSQL),
fmt.Sprintf("container_restarts AS (%s)", containerRestartsSQL),
}
finalSQL := querybuilder.CombineCTEs(cteFragments) + sumSQL
finalArgs := querybuilder.PrependArgs([][]any{restartFpsArgs, containerRestartsArgs}, nil)
rows, err := m.telemetryStore.ClickhouseDB().Query(ctx, finalSQL, finalArgs...)
if err != nil {
return nil, err
}
defer rows.Close()
result := make(map[string]int64)
for rows.Next() {
groupVals := make([]string, len(groupBy))
var totalRestarts float64
scanPtrs := make([]any, 0, len(groupBy)+1)
for i := range groupVals {
scanPtrs = append(scanPtrs, &groupVals[i])
}
scanPtrs = append(scanPtrs, &totalRestarts)
if err := rows.Scan(scanPtrs...); err != nil {
return nil, err
}
result[compositeKeyFromList(groupVals)] = int64(totalRestarts)
}
if err := rows.Err(); err != nil {
return nil, err
}
return result, nil
}

View File

@@ -8,11 +8,26 @@ import (
)
const (
podUIDAttrKey = "k8s.pod.uid"
podStartTimeAttrKey = "k8s.pod.start_time"
podPhaseMetricName = "k8s.pod.phase"
podUIDAttrKey = "k8s.pod.uid"
podStartTimeAttrKey = "k8s.pod.start_time"
containerNameAttrKey = "k8s.container.name"
containerStatusReasonAttrKey = "k8s.container.status.reason"
podPhaseMetricName = "k8s.pod.phase"
podStatusReasonMetricName = "k8s.pod.status_reason"
containerStatusReasonMetricName = "k8s.container.status.reason"
containerRestartsMetricName = "k8s.container.restarts"
)
// podStatusMetricNamesList are the metrics required to derive the kubectl-style
// pod display status. All three must be present (getMetricsExistence gate)
// before getPerGroupPodStatusCounts runs.
var podStatusMetricNamesList = []string{
podPhaseMetricName,
podStatusReasonMetricName,
containerStatusReasonMetricName,
}
var podUIDGroupByKey = qbtypes.GroupByKey{
TelemetryFieldKey: telemetrytypes.TelemetryFieldKey{
Name: podUIDAttrKey,
@@ -29,6 +44,9 @@ var podsTableMetricNamesList = []string{
"k8s.pod.memory_request_utilization",
"k8s.pod.memory_limit_utilization",
"k8s.pod.phase",
"k8s.pod.status_reason",
"k8s.container.status.reason",
"k8s.container.restarts",
}
var podAttrKeysForMetadata = []string{

View File

@@ -19,6 +19,7 @@ func buildStatefulSetRecords(
groupBy []qbtypes.GroupByKey,
metadataMap map[string]map[string]string,
phaseCounts map[string]podPhaseCounts,
podStatusCounts map[string]podStatusCounts,
) []inframonitoringtypes.StatefulSetRecord {
metricsMap := parseFullQueryResponse(resp, groupBy)
@@ -77,6 +78,10 @@ func buildStatefulSetRecords(
}
}
if podStatusCountsForGroup, ok := podStatusCounts[compositeKey]; ok {
record.PodCountsByStatus = podStatusCountsToResponse(podStatusCountsForGroup)
}
if attrs, ok := metadataMap[compositeKey]; ok {
for k, v := range attrs {
record.Meta[k] = v

View File

@@ -23,6 +23,8 @@ var statefulSetNameGroupByKey = qbtypes.GroupByKey{
// response to short-circuit cleanly when the phase metric is absent.
var statefulSetsTableMetricNamesList = []string{
"k8s.pod.phase",
"k8s.pod.status_reason",
"k8s.container.status.reason",
"k8s.pod.cpu.usage",
"k8s.pod.cpu_request_utilization",
"k8s.pod.cpu_limit_utilization",

View File

@@ -27,6 +27,7 @@ type ClusterRecord struct {
ClusterMemoryAllocatable float64 `json:"clusterMemoryAllocatable" required:"true"`
NodeCountsByReadiness NodeCountsByReadiness `json:"nodeCountsByReadiness" required:"true"`
PodCountsByPhase PodCountsByPhase `json:"podCountsByPhase" required:"true"`
PodCountsByStatus PodCountsByStatus `json:"podCountsByStatus" required:"true"`
Meta map[string]string `json:"meta" required:"true"`
}

View File

@@ -17,16 +17,17 @@ type DaemonSets struct {
}
type DaemonSetRecord struct {
DaemonSetName string `json:"daemonSetName" required:"true"`
DaemonSetCPU float64 `json:"daemonSetCPU" required:"true"`
DaemonSetCPURequest float64 `json:"daemonSetCPURequest" required:"true"`
DaemonSetCPULimit float64 `json:"daemonSetCPULimit" required:"true"`
DaemonSetMemory float64 `json:"daemonSetMemory" required:"true"`
DaemonSetMemoryRequest float64 `json:"daemonSetMemoryRequest" required:"true"`
DaemonSetMemoryLimit float64 `json:"daemonSetMemoryLimit" required:"true"`
DaemonSetName string `json:"daemonSetName" required:"true"`
DaemonSetCPU float64 `json:"daemonSetCPU" required:"true"`
DaemonSetCPURequest float64 `json:"daemonSetCPURequest" required:"true"`
DaemonSetCPULimit float64 `json:"daemonSetCPULimit" required:"true"`
DaemonSetMemory float64 `json:"daemonSetMemory" required:"true"`
DaemonSetMemoryRequest float64 `json:"daemonSetMemoryRequest" required:"true"`
DaemonSetMemoryLimit float64 `json:"daemonSetMemoryLimit" required:"true"`
DesiredNodes int `json:"desiredNodes" required:"true"`
CurrentNodes int `json:"currentNodes" required:"true"`
PodCountsByPhase PodCountsByPhase `json:"podCountsByPhase" required:"true"`
PodCountsByStatus PodCountsByStatus `json:"podCountsByStatus" required:"true"`
Meta map[string]string `json:"meta" required:"true"`
}

View File

@@ -27,6 +27,7 @@ type DeploymentRecord struct {
DesiredPods int `json:"desiredPods" required:"true"`
AvailablePods int `json:"availablePods" required:"true"`
PodCountsByPhase PodCountsByPhase `json:"podCountsByPhase" required:"true"`
PodCountsByStatus PodCountsByStatus `json:"podCountsByStatus" required:"true"`
Meta map[string]string `json:"meta" required:"true"`
}

View File

@@ -29,6 +29,7 @@ type JobRecord struct {
FailedPods int `json:"failedPods" required:"true"`
SuccessfulPods int `json:"successfulPods" required:"true"`
PodCountsByPhase PodCountsByPhase `json:"podCountsByPhase" required:"true"`
PodCountsByStatus PodCountsByStatus `json:"podCountsByStatus" required:"true"`
Meta map[string]string `json:"meta" required:"true"`
}

View File

@@ -17,11 +17,12 @@ type Namespaces struct {
}
type NamespaceRecord struct {
NamespaceName string `json:"namespaceName" required:"true"`
NamespaceCPU float64 `json:"namespaceCPU" required:"true"`
NamespaceMemory float64 `json:"namespaceMemory" required:"true"`
PodCountsByPhase PodCountsByPhase `json:"podCountsByPhase" required:"true"`
Meta map[string]string `json:"meta" required:"true"`
NamespaceName string `json:"namespaceName" required:"true"`
NamespaceCPU float64 `json:"namespaceCPU" required:"true"`
NamespaceMemory float64 `json:"namespaceMemory" required:"true"`
PodCountsByPhase PodCountsByPhase `json:"podCountsByPhase" required:"true"`
PodCountsByStatus PodCountsByStatus `json:"podCountsByStatus" required:"true"`
Meta map[string]string `json:"meta" required:"true"`
}
// PostableNamespaces is the request body for the v2 namespaces list API.

View File

@@ -28,6 +28,7 @@ type NodeRecord struct {
Condition NodeCondition `json:"condition" required:"true"`
NodeCountsByReadiness NodeCountsByReadiness `json:"nodeCountsByReadiness" required:"true"`
PodCountsByPhase PodCountsByPhase `json:"podCountsByPhase" required:"true"`
PodCountsByStatus PodCountsByStatus `json:"podCountsByStatus" required:"true"`
NodeCPU float64 `json:"nodeCPU" required:"true"`
NodeCPUAllocatable float64 `json:"nodeCPUAllocatable" required:"true"`
NodeMemory float64 `json:"nodeMemory" required:"true"`

View File

@@ -26,18 +26,49 @@ type PodCountsByPhase struct {
Unknown int `json:"unknown" required:"true"`
}
// PodCountsByStatus buckets pod counts by their latest kubectl-style display
// status in the time window (see PodStatus). One field per derivable status.
type PodCountsByStatus struct {
// Phase fallback.
Pending int `json:"pending" required:"true"`
Running int `json:"running" required:"true"`
Failed int `json:"failed" required:"true"`
Unknown int `json:"unknown" required:"true"`
// Container-level reasons.
CrashLoopBackOff int `json:"crashLoopBackOff" required:"true"`
ImagePullBackOff int `json:"imagePullBackOff" required:"true"`
ErrImagePull int `json:"errImagePull" required:"true"`
CreateContainerConfigError int `json:"createContainerConfigError" required:"true"`
ContainerCreating int `json:"containerCreating" required:"true"`
OOMKilled int `json:"oomKilled" required:"true"`
Completed int `json:"completed" required:"true"`
Error int `json:"error" required:"true"`
ContainerCannotRun int `json:"containerCannotRun" required:"true"`
// Pod-level reasons.
Evicted int `json:"evicted" required:"true"`
NodeAffinity int `json:"nodeAffinity" required:"true"`
NodeLost int `json:"nodeLost" required:"true"`
Shutdown int `json:"shutdown" required:"true"`
UnexpectedAdmissionError int `json:"unexpectedAdmissionError" required:"true"`
}
type PodRecord struct {
PodUID string `json:"podUID" required:"true"`
PodCPU float64 `json:"podCPU" required:"true"`
PodCPURequest float64 `json:"podCPURequest" required:"true"`
PodCPULimit float64 `json:"podCPULimit" required:"true"`
PodMemory float64 `json:"podMemory" required:"true"`
PodMemoryRequest float64 `json:"podMemoryRequest" required:"true"`
PodMemoryLimit float64 `json:"podMemoryLimit" required:"true"`
PodPhase PodPhase `json:"podPhase" required:"true"`
PodCountsByPhase PodCountsByPhase `json:"podCountsByPhase" required:"true"`
PodAge int64 `json:"podAge" required:"true"`
Meta map[string]string `json:"meta" required:"true"`
PodUID string `json:"podUID" required:"true"`
PodCPU float64 `json:"podCPU" required:"true"`
PodCPURequest float64 `json:"podCPURequest" required:"true"`
PodCPULimit float64 `json:"podCPULimit" required:"true"`
PodMemory float64 `json:"podMemory" required:"true"`
PodMemoryRequest float64 `json:"podMemoryRequest" required:"true"`
PodMemoryLimit float64 `json:"podMemoryLimit" required:"true"`
PodPhase PodPhase `json:"podPhase" required:"true"`
PodCountsByPhase PodCountsByPhase `json:"podCountsByPhase" required:"true"`
PodStatus PodStatus `json:"podStatus" required:"true"`
PodCountsByStatus PodCountsByStatus `json:"podCountsByStatus" required:"true"`
PodRestarts int64 `json:"podRestarts" required:"true"`
PodAge int64 `json:"podAge" required:"true"`
Meta map[string]string `json:"meta" required:"true"`
}
// PostablePods is the request body for the v2 pods list API.

View File

@@ -26,6 +26,70 @@ func (PodPhase) Enum() []any {
}
}
// PodStatus is the kubectl-style pod display status, derived from
// k8s.pod.phase + k8s.pod.status_reason + k8s.container.status.reason
// (priority cascade: container reason > pod-level reason > phase).
// Wire values are lowercased by valuer.NewString (e.g. "crashloopbackoff");
// the comment strings below are the kubectl spelling for readability. The
// query emits kubectl-style strings, so SQL output maps to these constants
// explicitly (not by raw string-wrapping).
type PodStatus struct {
valuer.String
}
var (
// Phase fallback.
PodStatusPending = PodStatus{valuer.NewString("Pending")}
PodStatusRunning = PodStatus{valuer.NewString("Running")}
PodStatusFailed = PodStatus{valuer.NewString("Failed")}
PodStatusUnknown = PodStatus{valuer.NewString("Unknown")}
// Container-level reasons (k8s.container.status.reason allowlist).
PodStatusCrashLoopBackOff = PodStatus{valuer.NewString("CrashLoopBackOff")}
PodStatusImagePullBackOff = PodStatus{valuer.NewString("ImagePullBackOff")}
PodStatusErrImagePull = PodStatus{valuer.NewString("ErrImagePull")}
PodStatusCreateContainerConfigError = PodStatus{valuer.NewString("CreateContainerConfigError")}
PodStatusContainerCreating = PodStatus{valuer.NewString("ContainerCreating")}
PodStatusOOMKilled = PodStatus{valuer.NewString("OOMKilled")}
PodStatusCompleted = PodStatus{valuer.NewString("Completed")}
PodStatusError = PodStatus{valuer.NewString("Error")}
PodStatusContainerCannotRun = PodStatus{valuer.NewString("ContainerCannotRun")}
// Pod-level reasons (k8s.pod.status_reason).
PodStatusEvicted = PodStatus{valuer.NewString("Evicted")}
PodStatusNodeAffinity = PodStatus{valuer.NewString("NodeAffinity")}
PodStatusNodeLost = PodStatus{valuer.NewString("NodeLost")}
PodStatusShutdown = PodStatus{valuer.NewString("Shutdown")}
PodStatusUnexpectedAdmissionError = PodStatus{valuer.NewString("UnexpectedAdmissionError")}
// Sentinel when status cannot be derived (metrics absent / not in list view).
PodStatusNoData = PodStatus{valuer.NewString("no_data")}
)
func (PodStatus) Enum() []any {
return []any{
PodStatusPending,
PodStatusRunning,
PodStatusFailed,
PodStatusUnknown,
PodStatusCrashLoopBackOff,
PodStatusImagePullBackOff,
PodStatusErrImagePull,
PodStatusCreateContainerConfigError,
PodStatusContainerCreating,
PodStatusOOMKilled,
PodStatusCompleted,
PodStatusError,
PodStatusContainerCannotRun,
PodStatusEvicted,
PodStatusNodeAffinity,
PodStatusNodeLost,
PodStatusShutdown,
PodStatusUnexpectedAdmissionError,
PodStatusNoData,
}
}
// Numeric pod phase values emitted by the k8s.pod.phase metric
// (source: OTel kubeletstats receiver).
const (

View File

@@ -27,6 +27,7 @@ type StatefulSetRecord struct {
DesiredPods int `json:"desiredPods" required:"true"`
CurrentPods int `json:"currentPods" required:"true"`
PodCountsByPhase PodCountsByPhase `json:"podCountsByPhase" required:"true"`
PodCountsByStatus PodCountsByStatus `json:"podCountsByStatus" required:"true"`
Meta map[string]string `json:"meta" required:"true"`
}

52
tests/fixtures/inframonitoring.py vendored Normal file
View File

@@ -0,0 +1,52 @@
"""Shared constants/helpers for v2 infra-monitoring pod-status tests."""
# All 18 PodCountsByStatus buckets (camelCase, matches inframonitoringtypes.PodCountsByStatus / the API response).
STATUS_BUCKETS = (
"pending",
"running",
"failed",
"unknown",
"crashLoopBackOff",
"imagePullBackOff",
"errImagePull",
"createContainerConfigError",
"containerCreating",
"oomKilled",
"completed",
"error",
"containerCannotRun",
"evicted",
"nodeAffinity",
"nodeLost",
"shutdown",
"unexpectedAdmissionError",
)
# Maps a PodStatus wire value (lowercase) to its PodCountsByStatus bucket key (camelCase).
STATUS_TO_BUCKET = {
"pending": "pending",
"running": "running",
"failed": "failed",
"unknown": "unknown",
"crashloopbackoff": "crashLoopBackOff",
"imagepullbackoff": "imagePullBackOff",
"errimagepull": "errImagePull",
"createcontainerconfigerror": "createContainerConfigError",
"containercreating": "containerCreating",
"oomkilled": "oomKilled",
"completed": "completed",
"error": "error",
"containercannotrun": "containerCannotRun",
"evicted": "evicted",
"nodeaffinity": "nodeAffinity",
"nodelost": "nodeLost",
"shutdown": "shutdown",
"unexpectedadmissionerror": "unexpectedAdmissionError",
}
def expected_status_counts(**nonzero: int) -> dict:
"""Full 19-bucket PodCountsByStatus with the given buckets set, rest 0."""
counts = {bucket: 0 for bucket in STATUS_BUCKETS}
counts.update(nonzero)
return counts

View File

@@ -34,3 +34,30 @@
{"metric_name":"k8s.pod.phase","labels":{"k8s.pod.uid":"pp-fail-2-uid","k8s.pod.name":"pp-fail-2","k8s.namespace.name":"ns-x","k8s.node.name":"pp-node","k8s.cluster.name":"pp-cluster"},"timestamp":"2025-01-10T10:00:00+00:00","value":4,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.pod.phase","labels":{"k8s.pod.uid":"pp-fail-2-uid","k8s.pod.name":"pp-fail-2","k8s.namespace.name":"ns-x","k8s.node.name":"pp-node","k8s.cluster.name":"pp-cluster"},"timestamp":"2025-01-10T10:02:00+00:00","value":4,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.pod.phase","labels":{"k8s.pod.uid":"pp-fail-2-uid","k8s.pod.name":"pp-fail-2","k8s.namespace.name":"ns-x","k8s.node.name":"pp-node","k8s.cluster.name":"pp-cluster"},"timestamp":"2025-01-10T10:04:00+00:00","value":4,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "pp-run-1-uid", "k8s.pod.name": "pp-run-1", "k8s.namespace.name": "ns-x", "k8s.node.name": "pp-node", "k8s.cluster.name": "pp-cluster"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "pp-run-1-uid", "k8s.pod.name": "pp-run-1", "k8s.namespace.name": "ns-x", "k8s.node.name": "pp-node", "k8s.cluster.name": "pp-cluster"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "pp-run-1-uid", "k8s.pod.name": "pp-run-1", "k8s.namespace.name": "ns-x", "k8s.node.name": "pp-node", "k8s.cluster.name": "pp-cluster"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "pp-run-2-uid", "k8s.pod.name": "pp-run-2", "k8s.namespace.name": "ns-x", "k8s.node.name": "pp-node", "k8s.cluster.name": "pp-cluster"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.status.reason", "labels": {"k8s.pod.uid": "pp-run-2-uid", "k8s.pod.name": "pp-run-2", "k8s.namespace.name": "ns-x", "k8s.node.name": "pp-node", "k8s.cluster.name": "pp-cluster", "k8s.container.name": "app", "k8s.container.status.reason": "CrashLoopBackOff"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "pp-run-2-uid", "k8s.pod.name": "pp-run-2", "k8s.namespace.name": "ns-x", "k8s.node.name": "pp-node", "k8s.cluster.name": "pp-cluster"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.status.reason", "labels": {"k8s.pod.uid": "pp-run-2-uid", "k8s.pod.name": "pp-run-2", "k8s.namespace.name": "ns-x", "k8s.node.name": "pp-node", "k8s.cluster.name": "pp-cluster", "k8s.container.name": "app", "k8s.container.status.reason": "CrashLoopBackOff"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "pp-run-2-uid", "k8s.pod.name": "pp-run-2", "k8s.namespace.name": "ns-x", "k8s.node.name": "pp-node", "k8s.cluster.name": "pp-cluster"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.status.reason", "labels": {"k8s.pod.uid": "pp-run-2-uid", "k8s.pod.name": "pp-run-2", "k8s.namespace.name": "ns-x", "k8s.node.name": "pp-node", "k8s.cluster.name": "pp-cluster", "k8s.container.name": "app", "k8s.container.status.reason": "CrashLoopBackOff"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "pp-run-3-uid", "k8s.pod.name": "pp-run-3", "k8s.namespace.name": "ns-x", "k8s.node.name": "pp-node", "k8s.cluster.name": "pp-cluster"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "pp-run-3-uid", "k8s.pod.name": "pp-run-3", "k8s.namespace.name": "ns-x", "k8s.node.name": "pp-node", "k8s.cluster.name": "pp-cluster"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "pp-run-3-uid", "k8s.pod.name": "pp-run-3", "k8s.namespace.name": "ns-x", "k8s.node.name": "pp-node", "k8s.cluster.name": "pp-cluster"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "pp-run-4-uid", "k8s.pod.name": "pp-run-4", "k8s.namespace.name": "ns-x", "k8s.node.name": "pp-node", "k8s.cluster.name": "pp-cluster"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "pp-run-4-uid", "k8s.pod.name": "pp-run-4", "k8s.namespace.name": "ns-x", "k8s.node.name": "pp-node", "k8s.cluster.name": "pp-cluster"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "pp-run-4-uid", "k8s.pod.name": "pp-run-4", "k8s.namespace.name": "ns-x", "k8s.node.name": "pp-node", "k8s.cluster.name": "pp-cluster"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "pp-pend-1-uid", "k8s.pod.name": "pp-pend-1", "k8s.namespace.name": "ns-x", "k8s.node.name": "pp-node", "k8s.cluster.name": "pp-cluster"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "pp-pend-1-uid", "k8s.pod.name": "pp-pend-1", "k8s.namespace.name": "ns-x", "k8s.node.name": "pp-node", "k8s.cluster.name": "pp-cluster"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "pp-pend-1-uid", "k8s.pod.name": "pp-pend-1", "k8s.namespace.name": "ns-x", "k8s.node.name": "pp-node", "k8s.cluster.name": "pp-cluster"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "pp-fail-1-uid", "k8s.pod.name": "pp-fail-1", "k8s.namespace.name": "ns-x", "k8s.node.name": "pp-node", "k8s.cluster.name": "pp-cluster"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.status.reason", "labels": {"k8s.pod.uid": "pp-fail-1-uid", "k8s.pod.name": "pp-fail-1", "k8s.namespace.name": "ns-x", "k8s.node.name": "pp-node", "k8s.cluster.name": "pp-cluster", "k8s.container.name": "app", "k8s.container.status.reason": "Error"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "pp-fail-1-uid", "k8s.pod.name": "pp-fail-1", "k8s.namespace.name": "ns-x", "k8s.node.name": "pp-node", "k8s.cluster.name": "pp-cluster"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.status.reason", "labels": {"k8s.pod.uid": "pp-fail-1-uid", "k8s.pod.name": "pp-fail-1", "k8s.namespace.name": "ns-x", "k8s.node.name": "pp-node", "k8s.cluster.name": "pp-cluster", "k8s.container.name": "app", "k8s.container.status.reason": "Error"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "pp-fail-1-uid", "k8s.pod.name": "pp-fail-1", "k8s.namespace.name": "ns-x", "k8s.node.name": "pp-node", "k8s.cluster.name": "pp-cluster"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.status.reason", "labels": {"k8s.pod.uid": "pp-fail-1-uid", "k8s.pod.name": "pp-fail-1", "k8s.namespace.name": "ns-x", "k8s.node.name": "pp-node", "k8s.cluster.name": "pp-cluster", "k8s.container.name": "app", "k8s.container.status.reason": "Error"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "pp-fail-2-uid", "k8s.pod.name": "pp-fail-2", "k8s.namespace.name": "ns-x", "k8s.node.name": "pp-node", "k8s.cluster.name": "pp-cluster"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "pp-fail-2-uid", "k8s.pod.name": "pp-fail-2", "k8s.namespace.name": "ns-x", "k8s.node.name": "pp-node", "k8s.cluster.name": "pp-cluster"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "pp-fail-2-uid", "k8s.pod.name": "pp-fail-2", "k8s.namespace.name": "ns-x", "k8s.node.name": "pp-node", "k8s.cluster.name": "pp-cluster"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}

View File

@@ -151,3 +151,30 @@
{"metric_name":"k8s.deployment.available","labels":{"k8s.deployment.name":"pp-dep","k8s.namespace.name":"ns-pp","k8s.cluster.name":"cluster-x"},"timestamp":"2025-01-10T10:02:00+00:00","value":4,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.deployment.desired","labels":{"k8s.deployment.name":"pp-dep","k8s.namespace.name":"ns-pp","k8s.cluster.name":"cluster-x"},"timestamp":"2025-01-10T10:04:00+00:00","value":7,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.deployment.available","labels":{"k8s.deployment.name":"pp-dep","k8s.namespace.name":"ns-pp","k8s.cluster.name":"cluster-x"},"timestamp":"2025-01-10T10:04:00+00:00","value":4,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "pp-run-1-uid", "k8s.pod.name": "pp-run-1", "k8s.deployment.name": "pp-dep", "k8s.namespace.name": "ns-pp", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "pp-run-1-uid", "k8s.pod.name": "pp-run-1", "k8s.deployment.name": "pp-dep", "k8s.namespace.name": "ns-pp", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "pp-run-1-uid", "k8s.pod.name": "pp-run-1", "k8s.deployment.name": "pp-dep", "k8s.namespace.name": "ns-pp", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "pp-run-2-uid", "k8s.pod.name": "pp-run-2", "k8s.deployment.name": "pp-dep", "k8s.namespace.name": "ns-pp", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.status.reason", "labels": {"k8s.pod.uid": "pp-run-2-uid", "k8s.pod.name": "pp-run-2", "k8s.deployment.name": "pp-dep", "k8s.namespace.name": "ns-pp", "k8s.cluster.name": "cluster-x", "k8s.container.name": "app", "k8s.container.status.reason": "CrashLoopBackOff"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "pp-run-2-uid", "k8s.pod.name": "pp-run-2", "k8s.deployment.name": "pp-dep", "k8s.namespace.name": "ns-pp", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.status.reason", "labels": {"k8s.pod.uid": "pp-run-2-uid", "k8s.pod.name": "pp-run-2", "k8s.deployment.name": "pp-dep", "k8s.namespace.name": "ns-pp", "k8s.cluster.name": "cluster-x", "k8s.container.name": "app", "k8s.container.status.reason": "CrashLoopBackOff"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "pp-run-2-uid", "k8s.pod.name": "pp-run-2", "k8s.deployment.name": "pp-dep", "k8s.namespace.name": "ns-pp", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.status.reason", "labels": {"k8s.pod.uid": "pp-run-2-uid", "k8s.pod.name": "pp-run-2", "k8s.deployment.name": "pp-dep", "k8s.namespace.name": "ns-pp", "k8s.cluster.name": "cluster-x", "k8s.container.name": "app", "k8s.container.status.reason": "CrashLoopBackOff"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "pp-run-3-uid", "k8s.pod.name": "pp-run-3", "k8s.deployment.name": "pp-dep", "k8s.namespace.name": "ns-pp", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "pp-run-3-uid", "k8s.pod.name": "pp-run-3", "k8s.deployment.name": "pp-dep", "k8s.namespace.name": "ns-pp", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "pp-run-3-uid", "k8s.pod.name": "pp-run-3", "k8s.deployment.name": "pp-dep", "k8s.namespace.name": "ns-pp", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "pp-run-4-uid", "k8s.pod.name": "pp-run-4", "k8s.deployment.name": "pp-dep", "k8s.namespace.name": "ns-pp", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "pp-run-4-uid", "k8s.pod.name": "pp-run-4", "k8s.deployment.name": "pp-dep", "k8s.namespace.name": "ns-pp", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "pp-run-4-uid", "k8s.pod.name": "pp-run-4", "k8s.deployment.name": "pp-dep", "k8s.namespace.name": "ns-pp", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "pp-pen-1-uid", "k8s.pod.name": "pp-pen-1", "k8s.deployment.name": "pp-dep", "k8s.namespace.name": "ns-pp", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "pp-pen-1-uid", "k8s.pod.name": "pp-pen-1", "k8s.deployment.name": "pp-dep", "k8s.namespace.name": "ns-pp", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "pp-pen-1-uid", "k8s.pod.name": "pp-pen-1", "k8s.deployment.name": "pp-dep", "k8s.namespace.name": "ns-pp", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "pp-fail-1-uid", "k8s.pod.name": "pp-fail-1", "k8s.deployment.name": "pp-dep", "k8s.namespace.name": "ns-pp", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.status.reason", "labels": {"k8s.pod.uid": "pp-fail-1-uid", "k8s.pod.name": "pp-fail-1", "k8s.deployment.name": "pp-dep", "k8s.namespace.name": "ns-pp", "k8s.cluster.name": "cluster-x", "k8s.container.name": "app", "k8s.container.status.reason": "Error"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "pp-fail-1-uid", "k8s.pod.name": "pp-fail-1", "k8s.deployment.name": "pp-dep", "k8s.namespace.name": "ns-pp", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.status.reason", "labels": {"k8s.pod.uid": "pp-fail-1-uid", "k8s.pod.name": "pp-fail-1", "k8s.deployment.name": "pp-dep", "k8s.namespace.name": "ns-pp", "k8s.cluster.name": "cluster-x", "k8s.container.name": "app", "k8s.container.status.reason": "Error"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "pp-fail-1-uid", "k8s.pod.name": "pp-fail-1", "k8s.deployment.name": "pp-dep", "k8s.namespace.name": "ns-pp", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.status.reason", "labels": {"k8s.pod.uid": "pp-fail-1-uid", "k8s.pod.name": "pp-fail-1", "k8s.deployment.name": "pp-dep", "k8s.namespace.name": "ns-pp", "k8s.cluster.name": "cluster-x", "k8s.container.name": "app", "k8s.container.status.reason": "Error"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "pp-fail-2-uid", "k8s.pod.name": "pp-fail-2", "k8s.deployment.name": "pp-dep", "k8s.namespace.name": "ns-pp", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "pp-fail-2-uid", "k8s.pod.name": "pp-fail-2", "k8s.deployment.name": "pp-dep", "k8s.namespace.name": "ns-pp", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "pp-fail-2-uid", "k8s.pod.name": "pp-fail-2", "k8s.deployment.name": "pp-dep", "k8s.namespace.name": "ns-pp", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}

View File

@@ -103,3 +103,45 @@
{"metric_name":"k8s.pod.phase","labels":{"k8s.pod.uid":"unk-p-uid","k8s.pod.name":"unk-p","k8s.namespace.name":"ns-x","k8s.node.name":"node-a","k8s.deployment.name":"phase-test","k8s.cluster.name":"cluster-x","k8s.statefulset.name":"","k8s.daemonset.name":"","k8s.job.name":"","k8s.cronjob.name":"","k8s.pod.start_time":"__START_TIME__"},"timestamp":"2025-01-10T10:00:00+00:00","value":5,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.pod.phase","labels":{"k8s.pod.uid":"unk-p-uid","k8s.pod.name":"unk-p","k8s.namespace.name":"ns-x","k8s.node.name":"node-a","k8s.deployment.name":"phase-test","k8s.cluster.name":"cluster-x","k8s.statefulset.name":"","k8s.daemonset.name":"","k8s.job.name":"","k8s.cronjob.name":"","k8s.pod.start_time":"__START_TIME__"},"timestamp":"2025-01-10T10:02:00+00:00","value":5,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.pod.phase","labels":{"k8s.pod.uid":"unk-p-uid","k8s.pod.name":"unk-p","k8s.namespace.name":"ns-x","k8s.node.name":"node-a","k8s.deployment.name":"phase-test","k8s.cluster.name":"cluster-x","k8s.statefulset.name":"","k8s.daemonset.name":"","k8s.job.name":"","k8s.cronjob.name":"","k8s.pod.start_time":"__START_TIME__"},"timestamp":"2025-01-10T10:04:00+00:00","value":5,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "pend-p-uid", "k8s.pod.name": "pend-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "node-a", "k8s.deployment.name": "phase-test", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "pend-p-uid", "k8s.pod.name": "pend-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "node-a", "k8s.deployment.name": "phase-test", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "pend-p-uid", "k8s.pod.name": "pend-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "node-a", "k8s.deployment.name": "phase-test", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "run-p-uid", "k8s.pod.name": "run-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "node-a", "k8s.deployment.name": "phase-test", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "run-p-uid", "k8s.pod.name": "run-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "node-a", "k8s.deployment.name": "phase-test", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "run-p-uid", "k8s.pod.name": "run-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "node-a", "k8s.deployment.name": "phase-test", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.status.reason", "labels": {"k8s.pod.uid": "run-p-uid", "k8s.pod.name": "run-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "node-a", "k8s.deployment.name": "phase-test", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "app", "k8s.container.status.reason": "CrashLoopBackOff"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.status.reason", "labels": {"k8s.pod.uid": "run-p-uid", "k8s.pod.name": "run-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "node-a", "k8s.deployment.name": "phase-test", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "app", "k8s.container.status.reason": "CrashLoopBackOff"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.status.reason", "labels": {"k8s.pod.uid": "run-p-uid", "k8s.pod.name": "run-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "node-a", "k8s.deployment.name": "phase-test", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "app", "k8s.container.status.reason": "CrashLoopBackOff"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.restarts", "labels": {"k8s.pod.uid": "run-p-uid", "k8s.pod.name": "run-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "node-a", "k8s.deployment.name": "phase-test", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "app"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.restarts", "labels": {"k8s.pod.uid": "run-p-uid", "k8s.pod.name": "run-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "node-a", "k8s.deployment.name": "phase-test", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "app"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.restarts", "labels": {"k8s.pod.uid": "run-p-uid", "k8s.pod.name": "run-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "node-a", "k8s.deployment.name": "phase-test", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "app"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "succ-p-uid", "k8s.pod.name": "succ-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "node-a", "k8s.deployment.name": "phase-test", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "succ-p-uid", "k8s.pod.name": "succ-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "node-a", "k8s.deployment.name": "phase-test", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "succ-p-uid", "k8s.pod.name": "succ-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "node-a", "k8s.deployment.name": "phase-test", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.status.reason", "labels": {"k8s.pod.uid": "succ-p-uid", "k8s.pod.name": "succ-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "node-a", "k8s.deployment.name": "phase-test", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "app", "k8s.container.status.reason": "Completed"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.status.reason", "labels": {"k8s.pod.uid": "succ-p-uid", "k8s.pod.name": "succ-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "node-a", "k8s.deployment.name": "phase-test", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "app", "k8s.container.status.reason": "Completed"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.status.reason", "labels": {"k8s.pod.uid": "succ-p-uid", "k8s.pod.name": "succ-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "node-a", "k8s.deployment.name": "phase-test", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "app", "k8s.container.status.reason": "Completed"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.restarts", "labels": {"k8s.pod.uid": "succ-p-uid", "k8s.pod.name": "succ-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "node-a", "k8s.deployment.name": "phase-test", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "app"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.restarts", "labels": {"k8s.pod.uid": "succ-p-uid", "k8s.pod.name": "succ-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "node-a", "k8s.deployment.name": "phase-test", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "app"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.restarts", "labels": {"k8s.pod.uid": "succ-p-uid", "k8s.pod.name": "succ-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "node-a", "k8s.deployment.name": "phase-test", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "app"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "fail-p-uid", "k8s.pod.name": "fail-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "node-a", "k8s.deployment.name": "phase-test", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "fail-p-uid", "k8s.pod.name": "fail-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "node-a", "k8s.deployment.name": "phase-test", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "fail-p-uid", "k8s.pod.name": "fail-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "node-a", "k8s.deployment.name": "phase-test", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.restarts", "labels": {"k8s.pod.uid": "fail-p-uid", "k8s.pod.name": "fail-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "node-a", "k8s.deployment.name": "phase-test", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "app"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.restarts", "labels": {"k8s.pod.uid": "fail-p-uid", "k8s.pod.name": "fail-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "node-a", "k8s.deployment.name": "phase-test", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "app"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.restarts", "labels": {"k8s.pod.uid": "fail-p-uid", "k8s.pod.name": "fail-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "node-a", "k8s.deployment.name": "phase-test", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "app"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "unk-p-uid", "k8s.pod.name": "unk-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "node-a", "k8s.deployment.name": "phase-test", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "unk-p-uid", "k8s.pod.name": "unk-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "node-a", "k8s.deployment.name": "phase-test", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "unk-p-uid", "k8s.pod.name": "unk-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "node-a", "k8s.deployment.name": "phase-test", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.status.reason", "labels": {"k8s.pod.uid": "unk-p-uid", "k8s.pod.name": "unk-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "node-a", "k8s.deployment.name": "phase-test", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "c-oom", "k8s.container.status.reason": "OOMKilled"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.status.reason", "labels": {"k8s.pod.uid": "unk-p-uid", "k8s.pod.name": "unk-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "node-a", "k8s.deployment.name": "phase-test", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "c-oom", "k8s.container.status.reason": "OOMKilled"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.status.reason", "labels": {"k8s.pod.uid": "unk-p-uid", "k8s.pod.name": "unk-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "node-a", "k8s.deployment.name": "phase-test", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "c-oom", "k8s.container.status.reason": "OOMKilled"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.status.reason", "labels": {"k8s.pod.uid": "unk-p-uid", "k8s.pod.name": "unk-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "node-a", "k8s.deployment.name": "phase-test", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "c-clbo", "k8s.container.status.reason": "CrashLoopBackOff"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.status.reason", "labels": {"k8s.pod.uid": "unk-p-uid", "k8s.pod.name": "unk-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "node-a", "k8s.deployment.name": "phase-test", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "c-clbo", "k8s.container.status.reason": "CrashLoopBackOff"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.status.reason", "labels": {"k8s.pod.uid": "unk-p-uid", "k8s.pod.name": "unk-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "node-a", "k8s.deployment.name": "phase-test", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "c-clbo", "k8s.container.status.reason": "CrashLoopBackOff"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.restarts", "labels": {"k8s.pod.uid": "unk-p-uid", "k8s.pod.name": "unk-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "node-a", "k8s.deployment.name": "phase-test", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "c-oom"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.restarts", "labels": {"k8s.pod.uid": "unk-p-uid", "k8s.pod.name": "unk-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "node-a", "k8s.deployment.name": "phase-test", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "c-oom"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.restarts", "labels": {"k8s.pod.uid": "unk-p-uid", "k8s.pod.name": "unk-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "node-a", "k8s.deployment.name": "phase-test", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "c-oom"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.restarts", "labels": {"k8s.pod.uid": "unk-p-uid", "k8s.pod.name": "unk-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "node-a", "k8s.deployment.name": "phase-test", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "c-clbo"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 8, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.restarts", "labels": {"k8s.pod.uid": "unk-p-uid", "k8s.pod.name": "unk-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "node-a", "k8s.deployment.name": "phase-test", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "c-clbo"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 8, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.restarts", "labels": {"k8s.pod.uid": "unk-p-uid", "k8s.pod.name": "unk-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "node-a", "k8s.deployment.name": "phase-test", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "c-clbo"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 8, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}

View File

@@ -124,3 +124,42 @@
{"metric_name":"k8s.pod.phase","labels":{"k8s.pod.uid":"g-pend-1-uid","k8s.pod.name":"g-pend-1","k8s.namespace.name":"ns-mixed","k8s.node.name":"node-b","k8s.deployment.name":"dep-y","k8s.cluster.name":"cluster-x","k8s.statefulset.name":"","k8s.daemonset.name":"","k8s.job.name":"","k8s.cronjob.name":"","k8s.pod.start_time":"__START_TIME__"},"timestamp":"2025-01-10T10:00:00+00:00","value":1,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.pod.phase","labels":{"k8s.pod.uid":"g-pend-1-uid","k8s.pod.name":"g-pend-1","k8s.namespace.name":"ns-mixed","k8s.node.name":"node-b","k8s.deployment.name":"dep-y","k8s.cluster.name":"cluster-x","k8s.statefulset.name":"","k8s.daemonset.name":"","k8s.job.name":"","k8s.cronjob.name":"","k8s.pod.start_time":"__START_TIME__"},"timestamp":"2025-01-10T10:02:00+00:00","value":1,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.pod.phase","labels":{"k8s.pod.uid":"g-pend-1-uid","k8s.pod.name":"g-pend-1","k8s.namespace.name":"ns-mixed","k8s.node.name":"node-b","k8s.deployment.name":"dep-y","k8s.cluster.name":"cluster-x","k8s.statefulset.name":"","k8s.daemonset.name":"","k8s.job.name":"","k8s.cronjob.name":"","k8s.pod.start_time":"__START_TIME__"},"timestamp":"2025-01-10T10:04:00+00:00","value":1,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "g-run-1-uid", "k8s.pod.name": "g-run-1", "k8s.namespace.name": "ns-mixed", "k8s.node.name": "node-a", "k8s.deployment.name": "dep-x", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "g-run-1-uid", "k8s.pod.name": "g-run-1", "k8s.namespace.name": "ns-mixed", "k8s.node.name": "node-a", "k8s.deployment.name": "dep-x", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "g-run-1-uid", "k8s.pod.name": "g-run-1", "k8s.namespace.name": "ns-mixed", "k8s.node.name": "node-a", "k8s.deployment.name": "dep-x", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.restarts", "labels": {"k8s.pod.uid": "g-run-1-uid", "k8s.pod.name": "g-run-1", "k8s.namespace.name": "ns-mixed", "k8s.node.name": "node-a", "k8s.deployment.name": "dep-x", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "app"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.restarts", "labels": {"k8s.pod.uid": "g-run-1-uid", "k8s.pod.name": "g-run-1", "k8s.namespace.name": "ns-mixed", "k8s.node.name": "node-a", "k8s.deployment.name": "dep-x", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "app"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.restarts", "labels": {"k8s.pod.uid": "g-run-1-uid", "k8s.pod.name": "g-run-1", "k8s.namespace.name": "ns-mixed", "k8s.node.name": "node-a", "k8s.deployment.name": "dep-x", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "app"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "g-run-3-uid", "k8s.pod.name": "g-run-3", "k8s.namespace.name": "ns-mixed", "k8s.node.name": "node-a", "k8s.deployment.name": "dep-x", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "g-run-3-uid", "k8s.pod.name": "g-run-3", "k8s.namespace.name": "ns-mixed", "k8s.node.name": "node-a", "k8s.deployment.name": "dep-x", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "g-run-3-uid", "k8s.pod.name": "g-run-3", "k8s.namespace.name": "ns-mixed", "k8s.node.name": "node-a", "k8s.deployment.name": "dep-x", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.restarts", "labels": {"k8s.pod.uid": "g-run-3-uid", "k8s.pod.name": "g-run-3", "k8s.namespace.name": "ns-mixed", "k8s.node.name": "node-a", "k8s.deployment.name": "dep-x", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "app"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.restarts", "labels": {"k8s.pod.uid": "g-run-3-uid", "k8s.pod.name": "g-run-3", "k8s.namespace.name": "ns-mixed", "k8s.node.name": "node-a", "k8s.deployment.name": "dep-x", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "app"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.restarts", "labels": {"k8s.pod.uid": "g-run-3-uid", "k8s.pod.name": "g-run-3", "k8s.namespace.name": "ns-mixed", "k8s.node.name": "node-a", "k8s.deployment.name": "dep-x", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "app"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "g-run-2-uid", "k8s.pod.name": "g-run-2", "k8s.namespace.name": "ns-mixed", "k8s.node.name": "node-a", "k8s.deployment.name": "dep-x", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "g-run-2-uid", "k8s.pod.name": "g-run-2", "k8s.namespace.name": "ns-mixed", "k8s.node.name": "node-a", "k8s.deployment.name": "dep-x", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "g-run-2-uid", "k8s.pod.name": "g-run-2", "k8s.namespace.name": "ns-mixed", "k8s.node.name": "node-a", "k8s.deployment.name": "dep-x", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.status.reason", "labels": {"k8s.pod.uid": "g-run-2-uid", "k8s.pod.name": "g-run-2", "k8s.namespace.name": "ns-mixed", "k8s.node.name": "node-a", "k8s.deployment.name": "dep-x", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "app", "k8s.container.status.reason": "CrashLoopBackOff"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.status.reason", "labels": {"k8s.pod.uid": "g-run-2-uid", "k8s.pod.name": "g-run-2", "k8s.namespace.name": "ns-mixed", "k8s.node.name": "node-a", "k8s.deployment.name": "dep-x", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "app", "k8s.container.status.reason": "CrashLoopBackOff"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.status.reason", "labels": {"k8s.pod.uid": "g-run-2-uid", "k8s.pod.name": "g-run-2", "k8s.namespace.name": "ns-mixed", "k8s.node.name": "node-a", "k8s.deployment.name": "dep-x", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "app", "k8s.container.status.reason": "CrashLoopBackOff"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.restarts", "labels": {"k8s.pod.uid": "g-run-2-uid", "k8s.pod.name": "g-run-2", "k8s.namespace.name": "ns-mixed", "k8s.node.name": "node-a", "k8s.deployment.name": "dep-x", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "app"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 3, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.restarts", "labels": {"k8s.pod.uid": "g-run-2-uid", "k8s.pod.name": "g-run-2", "k8s.namespace.name": "ns-mixed", "k8s.node.name": "node-a", "k8s.deployment.name": "dep-x", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "app"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 3, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.restarts", "labels": {"k8s.pod.uid": "g-run-2-uid", "k8s.pod.name": "g-run-2", "k8s.namespace.name": "ns-mixed", "k8s.node.name": "node-a", "k8s.deployment.name": "dep-x", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "app"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 3, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "g-fail-1-uid", "k8s.pod.name": "g-fail-1", "k8s.namespace.name": "ns-mixed", "k8s.node.name": "node-b", "k8s.deployment.name": "dep-y", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "g-fail-1-uid", "k8s.pod.name": "g-fail-1", "k8s.namespace.name": "ns-mixed", "k8s.node.name": "node-b", "k8s.deployment.name": "dep-y", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "g-fail-1-uid", "k8s.pod.name": "g-fail-1", "k8s.namespace.name": "ns-mixed", "k8s.node.name": "node-b", "k8s.deployment.name": "dep-y", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.status.reason", "labels": {"k8s.pod.uid": "g-fail-1-uid", "k8s.pod.name": "g-fail-1", "k8s.namespace.name": "ns-mixed", "k8s.node.name": "node-b", "k8s.deployment.name": "dep-y", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "app", "k8s.container.status.reason": "Error"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.status.reason", "labels": {"k8s.pod.uid": "g-fail-1-uid", "k8s.pod.name": "g-fail-1", "k8s.namespace.name": "ns-mixed", "k8s.node.name": "node-b", "k8s.deployment.name": "dep-y", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "app", "k8s.container.status.reason": "Error"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.status.reason", "labels": {"k8s.pod.uid": "g-fail-1-uid", "k8s.pod.name": "g-fail-1", "k8s.namespace.name": "ns-mixed", "k8s.node.name": "node-b", "k8s.deployment.name": "dep-y", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "app", "k8s.container.status.reason": "Error"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.restarts", "labels": {"k8s.pod.uid": "g-fail-1-uid", "k8s.pod.name": "g-fail-1", "k8s.namespace.name": "ns-mixed", "k8s.node.name": "node-b", "k8s.deployment.name": "dep-y", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "app"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.restarts", "labels": {"k8s.pod.uid": "g-fail-1-uid", "k8s.pod.name": "g-fail-1", "k8s.namespace.name": "ns-mixed", "k8s.node.name": "node-b", "k8s.deployment.name": "dep-y", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "app"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.restarts", "labels": {"k8s.pod.uid": "g-fail-1-uid", "k8s.pod.name": "g-fail-1", "k8s.namespace.name": "ns-mixed", "k8s.node.name": "node-b", "k8s.deployment.name": "dep-y", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "app"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "g-fail-2-uid", "k8s.pod.name": "g-fail-2", "k8s.namespace.name": "ns-mixed", "k8s.node.name": "node-b", "k8s.deployment.name": "dep-y", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "g-fail-2-uid", "k8s.pod.name": "g-fail-2", "k8s.namespace.name": "ns-mixed", "k8s.node.name": "node-b", "k8s.deployment.name": "dep-y", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "g-fail-2-uid", "k8s.pod.name": "g-fail-2", "k8s.namespace.name": "ns-mixed", "k8s.node.name": "node-b", "k8s.deployment.name": "dep-y", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.restarts", "labels": {"k8s.pod.uid": "g-fail-2-uid", "k8s.pod.name": "g-fail-2", "k8s.namespace.name": "ns-mixed", "k8s.node.name": "node-b", "k8s.deployment.name": "dep-y", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "app"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.restarts", "labels": {"k8s.pod.uid": "g-fail-2-uid", "k8s.pod.name": "g-fail-2", "k8s.namespace.name": "ns-mixed", "k8s.node.name": "node-b", "k8s.deployment.name": "dep-y", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "app"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.restarts", "labels": {"k8s.pod.uid": "g-fail-2-uid", "k8s.pod.name": "g-fail-2", "k8s.namespace.name": "ns-mixed", "k8s.node.name": "node-b", "k8s.deployment.name": "dep-y", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "app"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "g-pend-1-uid", "k8s.pod.name": "g-pend-1", "k8s.namespace.name": "ns-mixed", "k8s.node.name": "node-b", "k8s.deployment.name": "dep-y", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "g-pend-1-uid", "k8s.pod.name": "g-pend-1", "k8s.namespace.name": "ns-mixed", "k8s.node.name": "node-b", "k8s.deployment.name": "dep-y", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "g-pend-1-uid", "k8s.pod.name": "g-pend-1", "k8s.namespace.name": "ns-mixed", "k8s.node.name": "node-b", "k8s.deployment.name": "dep-y", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}

View File

@@ -19,3 +19,10 @@
{"metric_name":"k8s.pod.phase","labels":{"k8s.pod.uid":"trans-p-uid","k8s.pod.name":"trans-p","k8s.namespace.name":"ns-x","k8s.node.name":"node-a","k8s.deployment.name":"phase-test","k8s.cluster.name":"cluster-x","k8s.statefulset.name":"","k8s.daemonset.name":"","k8s.job.name":"","k8s.cronjob.name":"","k8s.pod.start_time":"__START_TIME__"},"timestamp":"2025-01-10T10:00:00+00:00","value":1,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.pod.phase","labels":{"k8s.pod.uid":"trans-p-uid","k8s.pod.name":"trans-p","k8s.namespace.name":"ns-x","k8s.node.name":"node-a","k8s.deployment.name":"phase-test","k8s.cluster.name":"cluster-x","k8s.statefulset.name":"","k8s.daemonset.name":"","k8s.job.name":"","k8s.cronjob.name":"","k8s.pod.start_time":"__START_TIME__"},"timestamp":"2025-01-10T10:02:00+00:00","value":1,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.pod.phase","labels":{"k8s.pod.uid":"trans-p-uid","k8s.pod.name":"trans-p","k8s.namespace.name":"ns-x","k8s.node.name":"node-a","k8s.deployment.name":"phase-test","k8s.cluster.name":"cluster-x","k8s.statefulset.name":"","k8s.daemonset.name":"","k8s.job.name":"","k8s.cronjob.name":"","k8s.pod.start_time":"__START_TIME__"},"timestamp":"2025-01-10T10:04:00+00:00","value":2,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "trans-p-uid", "k8s.pod.name": "trans-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "node-a", "k8s.deployment.name": "phase-test", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "trans-p-uid", "k8s.pod.name": "trans-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "node-a", "k8s.deployment.name": "phase-test", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "trans-p-uid", "k8s.pod.name": "trans-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "node-a", "k8s.deployment.name": "phase-test", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.status.reason", "labels": {"k8s.pod.uid": "trans-p-uid", "k8s.pod.name": "trans-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "node-a", "k8s.deployment.name": "phase-test", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "app", "k8s.container.status.reason": "CrashLoopBackOff", "container.id": "aaa"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.status.reason", "labels": {"k8s.pod.uid": "trans-p-uid", "k8s.pod.name": "trans-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "node-a", "k8s.deployment.name": "phase-test", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "app", "k8s.container.status.reason": "CrashLoopBackOff", "container.id": "bbb"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.restarts", "labels": {"k8s.pod.uid": "trans-p-uid", "k8s.pod.name": "trans-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "node-a", "k8s.deployment.name": "phase-test", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "app", "container.id": "aaa"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.restarts", "labels": {"k8s.pod.uid": "trans-p-uid", "k8s.pod.name": "trans-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "node-a", "k8s.deployment.name": "phase-test", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "app", "container.id": "bbb"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}

View File

@@ -40,3 +40,21 @@
{"metric_name":"k8s.pod.phase","labels":{"k8s.pod.uid":"acc-p2-uid","k8s.pod.name":"acc-p2","k8s.namespace.name":"ns-b","k8s.node.name":"node-b","k8s.deployment.name":"dep-2","k8s.cluster.name":"cluster-x","k8s.statefulset.name":"","k8s.daemonset.name":"","k8s.job.name":"","k8s.cronjob.name":"","k8s.pod.start_time":"__START_TIME__"},"timestamp":"2025-01-10T10:00:00+00:00","value":2,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.pod.phase","labels":{"k8s.pod.uid":"acc-p2-uid","k8s.pod.name":"acc-p2","k8s.namespace.name":"ns-b","k8s.node.name":"node-b","k8s.deployment.name":"dep-2","k8s.cluster.name":"cluster-x","k8s.statefulset.name":"","k8s.daemonset.name":"","k8s.job.name":"","k8s.cronjob.name":"","k8s.pod.start_time":"__START_TIME__"},"timestamp":"2025-01-10T10:02:00+00:00","value":2,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name":"k8s.pod.phase","labels":{"k8s.pod.uid":"acc-p2-uid","k8s.pod.name":"acc-p2","k8s.namespace.name":"ns-b","k8s.node.name":"node-b","k8s.deployment.name":"dep-2","k8s.cluster.name":"cluster-x","k8s.statefulset.name":"","k8s.daemonset.name":"","k8s.job.name":"","k8s.cronjob.name":"","k8s.pod.start_time":"__START_TIME__"},"timestamp":"2025-01-10T10:04:00+00:00","value":2,"temporality":"Unspecified","type_":"Gauge","is_monotonic":false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "acc-p1-uid", "k8s.pod.name": "acc-p1", "k8s.namespace.name": "ns-a", "k8s.node.name": "node-a", "k8s.deployment.name": "dep-1", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "acc-p1-uid", "k8s.pod.name": "acc-p1", "k8s.namespace.name": "ns-a", "k8s.node.name": "node-a", "k8s.deployment.name": "dep-1", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "acc-p1-uid", "k8s.pod.name": "acc-p1", "k8s.namespace.name": "ns-a", "k8s.node.name": "node-a", "k8s.deployment.name": "dep-1", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.restarts", "labels": {"k8s.pod.uid": "acc-p1-uid", "k8s.pod.name": "acc-p1", "k8s.namespace.name": "ns-a", "k8s.node.name": "node-a", "k8s.deployment.name": "dep-1", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "app"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.restarts", "labels": {"k8s.pod.uid": "acc-p1-uid", "k8s.pod.name": "acc-p1", "k8s.namespace.name": "ns-a", "k8s.node.name": "node-a", "k8s.deployment.name": "dep-1", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "app"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.restarts", "labels": {"k8s.pod.uid": "acc-p1-uid", "k8s.pod.name": "acc-p1", "k8s.namespace.name": "ns-a", "k8s.node.name": "node-a", "k8s.deployment.name": "dep-1", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "app"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.status.reason", "labels": {"k8s.pod.uid": "acc-p1-uid", "k8s.pod.name": "acc-p1", "k8s.namespace.name": "ns-a", "k8s.node.name": "node-a", "k8s.deployment.name": "dep-1", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "app", "k8s.container.status.reason": "CrashLoopBackOff"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.status.reason", "labels": {"k8s.pod.uid": "acc-p1-uid", "k8s.pod.name": "acc-p1", "k8s.namespace.name": "ns-a", "k8s.node.name": "node-a", "k8s.deployment.name": "dep-1", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "app", "k8s.container.status.reason": "CrashLoopBackOff"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.status.reason", "labels": {"k8s.pod.uid": "acc-p1-uid", "k8s.pod.name": "acc-p1", "k8s.namespace.name": "ns-a", "k8s.node.name": "node-a", "k8s.deployment.name": "dep-1", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "app", "k8s.container.status.reason": "CrashLoopBackOff"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "acc-p2-uid", "k8s.pod.name": "acc-p2", "k8s.namespace.name": "ns-b", "k8s.node.name": "node-b", "k8s.deployment.name": "dep-2", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "acc-p2-uid", "k8s.pod.name": "acc-p2", "k8s.namespace.name": "ns-b", "k8s.node.name": "node-b", "k8s.deployment.name": "dep-2", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.status_reason", "labels": {"k8s.pod.uid": "acc-p2-uid", "k8s.pod.name": "acc-p2", "k8s.namespace.name": "ns-b", "k8s.node.name": "node-b", "k8s.deployment.name": "dep-2", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.restarts", "labels": {"k8s.pod.uid": "acc-p2-uid", "k8s.pod.name": "acc-p2", "k8s.namespace.name": "ns-b", "k8s.node.name": "node-b", "k8s.deployment.name": "dep-2", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "app"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.restarts", "labels": {"k8s.pod.uid": "acc-p2-uid", "k8s.pod.name": "acc-p2", "k8s.namespace.name": "ns-b", "k8s.node.name": "node-b", "k8s.deployment.name": "dep-2", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "app"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.restarts", "labels": {"k8s.pod.uid": "acc-p2-uid", "k8s.pod.name": "acc-p2", "k8s.namespace.name": "ns-b", "k8s.node.name": "node-b", "k8s.deployment.name": "dep-2", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "app"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.status.reason", "labels": {"k8s.pod.uid": "acc-p2-uid", "k8s.pod.name": "acc-p2", "k8s.namespace.name": "ns-b", "k8s.node.name": "node-b", "k8s.deployment.name": "dep-2", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "app", "k8s.container.status.reason": "CrashLoopBackOff"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.status.reason", "labels": {"k8s.pod.uid": "acc-p2-uid", "k8s.pod.name": "acc-p2", "k8s.namespace.name": "ns-b", "k8s.node.name": "node-b", "k8s.deployment.name": "dep-2", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "app", "k8s.container.status.reason": "CrashLoopBackOff"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.container.status.reason", "labels": {"k8s.pod.uid": "acc-p2-uid", "k8s.pod.name": "acc-p2", "k8s.namespace.name": "ns-b", "k8s.node.name": "node-b", "k8s.deployment.name": "dep-2", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "", "k8s.daemonset.name": "", "k8s.job.name": "", "k8s.cronjob.name": "", "k8s.pod.start_time": "__START_TIME__", "k8s.container.name": "app", "k8s.container.status.reason": "CrashLoopBackOff"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}

View File

@@ -9,7 +9,17 @@
"podMemoryRequest": 0.5,
"podMemoryLimit": 0.25,
"podPhase": "running",
"podCountsByPhase": {"pending": 0, "running": 1, "succeeded": 0, "failed": 0, "unknown": 0}
"podCountsByPhase": {"pending": 0, "running": 1, "succeeded": 0, "failed": 0, "unknown": 0},
"podStatus": "running",
"podRestarts": 0,
"podCountsByStatus": {
"pending": 0, "running": 1, "failed": 0, "unknown": 0,
"crashLoopBackOff": 0, "imagePullBackOff": 0, "errImagePull": 0,
"createContainerConfigError": 0, "containerCreating": 0, "oomKilled": 0,
"completed": 0, "error": 0, "containerCannotRun": 0,
"evicted": 0, "nodeAffinity": 0, "nodeLost": 0, "shutdown": 0,
"unexpectedAdmissionError": 0
}
},
{
"podName": "acc-p2",
@@ -20,7 +30,17 @@
"podMemoryRequest": 0.75,
"podMemoryLimit": 0.5,
"podPhase": "running",
"podCountsByPhase": {"pending": 0, "running": 1, "succeeded": 0, "failed": 0, "unknown": 0}
"podCountsByPhase": {"pending": 0, "running": 1, "succeeded": 0, "failed": 0, "unknown": 0},
"podStatus": "running",
"podRestarts": 0,
"podCountsByStatus": {
"pending": 0, "running": 1, "failed": 0, "unknown": 0,
"crashLoopBackOff": 0, "imagePullBackOff": 0, "errImagePull": 0,
"createContainerConfigError": 0, "containerCreating": 0, "oomKilled": 0,
"completed": 0, "error": 0, "containerCannotRun": 0,
"evicted": 0, "nodeAffinity": 0, "nodeLost": 0, "shutdown": 0,
"unexpectedAdmissionError": 0
}
}
]
}

View File

@@ -10,6 +10,7 @@ import requests
from fixtures import types
from fixtures.auth import USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD
from fixtures.fs import get_testdata_file_path
from fixtures.inframonitoring import STATUS_BUCKETS, STATUS_TO_BUCKET
from fixtures.metrics import Metrics
from fixtures.querier import compare_values, get_all_warnings
from fixtures.time import parse_timestamp
@@ -121,6 +122,9 @@ def test_pods_accuracy(
"podMemoryLimit",
"podPhase",
"podCountsByPhase",
"podStatus",
"podCountsByStatus",
"podRestarts",
"podAge",
"meta",
):
@@ -131,6 +135,11 @@ def test_pods_accuracy(
assert bucket in record["podCountsByPhase"], f"missing phase bucket {bucket} in {record['podCountsByPhase']!r}"
assert isinstance(record["podCountsByPhase"][bucket], int)
# All status buckets always present, integer-typed.
for bucket in STATUS_BUCKETS:
assert bucket in record["podCountsByStatus"], f"missing status bucket {bucket} in {record['podCountsByStatus']!r}"
assert isinstance(record["podCountsByStatus"][bucket], int)
# Exact values.
pod_name = record["meta"]["k8s.pod.name"]
exp = exp_by_name[pod_name]
@@ -145,6 +154,9 @@ def test_pods_accuracy(
assert compare_values(record[field], exp[field], 1e-9), f"{pod_name}.{field}: got {record[field]}, expected {exp[field]}"
assert record["podPhase"] == exp["podPhase"]
assert record["podCountsByPhase"] == exp["podCountsByPhase"]
assert record["podStatus"] == exp["podStatus"], f"{pod_name}.podStatus: got {record['podStatus']}, expected {exp['podStatus']}"
assert record["podCountsByStatus"] == exp["podCountsByStatus"], f"{pod_name}.podCountsByStatus mismatch: got {record['podCountsByStatus']}"
assert record["podRestarts"] == exp["podRestarts"], f"{pod_name}.podRestarts: got {record['podRestarts']}, expected {exp['podRestarts']}"
assert record["podAge"] == expected_age_ms, f"{pod_name}.podAge: got {record['podAge']}, expected {expected_age_ms}"
@@ -793,3 +805,343 @@ def test_pods_validation_errors(
error = response.json()["error"]
assert error["code"] == "invalid_input"
assert err_substr.lower() in error["message"].lower(), f"expected substring {err_substr!r} not found in: {error['message']!r}"
@pytest.mark.parametrize(
"pod_name,expected_status",
[
# Expectations are what `kubectl get pods` STATUS would show for the
# seeded K8s state in pods_phases.jsonl (not the query internals).
pytest.param("pend-p", "pending", id="pending_phase_fallback"),
pytest.param("run-p", "crashloopbackoff", id="container_reason_beats_running_phase"),
pytest.param("succ-p", "completed", id="completed_terminated_reason"),
pytest.param("fail-p", "evicted", id="pod_reason_beats_phase"),
pytest.param("unk-p", "crashloopbackoff", id="multi_container_priority"),
],
)
def test_pods_status_list_mode(
signoz: types.SigNoz,
create_user_admin: None, # pylint: disable=unused-argument
get_token,
insert_metrics,
pod_name: str,
expected_status: str,
) -> None:
"""List mode: podStatus is the kubectl-style display status derived from
k8s.pod.phase + k8s.pod.status_reason + k8s.container.status.reason.
Seeded states -> what kubectl would print:
pend-p Pending (unscheduled; phase fallback, no container reason)
run-p CrashLoopBackOff (container crashlooping; phase still Running)
succ-p Completed (container terminated Completed; phase Succeeded)
fail-p Evicted (pod-level Status.Reason overrides phase)
unk-p CrashLoopBackOff (2 containers: OOMKilled + CrashLoopBackOff)
NOTE unk-p: a multi-container pod. kubectl picks the reason by container
order; we pick by reason priority (waiting>terminated), so CrashLoopBackOff
wins over OOMKilled. Documented divergence for multi-container pods — metrics
carry no container ordering.
"""
now = datetime.now(tz=UTC).replace(microsecond=0)
insert_metrics(
_load_pods_metrics(
"inframonitoring/pods_phases.jsonl",
base_time=now - timedelta(minutes=4),
)
)
token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
response = requests.post(
signoz.self.host_configs["8080"].get(ENDPOINT),
headers={"authorization": f"Bearer {token}"},
json={
"start": int((now - timedelta(minutes=5)).timestamp() * 1000),
"end": int(now.timestamp() * 1000),
"limit": 50,
"filter": {"expression": f"k8s.pod.name = '{pod_name}'"},
},
timeout=5,
)
assert response.status_code == HTTPStatus.OK, response.text
data = response.json()["data"]
assert data["total"] == 1
rec = data["records"][0]
assert rec["meta"]["k8s.pod.name"] == pod_name
assert rec["podStatus"] == expected_status
# List mode: pod is its own group -> exactly its status bucket is 1.
bucket = STATUS_TO_BUCKET[expected_status]
assert rec["podCountsByStatus"][bucket] == 1
for other in STATUS_BUCKETS:
if other != bucket:
assert rec["podCountsByStatus"][other] == 0, f"expected {other}=0 when status={expected_status}, got {rec['podCountsByStatus']}"
@pytest.mark.parametrize(
"pod_name,expected_restarts",
[
# Mirrors kubectl RESTARTS (sum across the pod's containers).
pytest.param("run-p", 5, id="single_container"),
pytest.param("succ-p", 0, id="zero_restarts"),
pytest.param("unk-p", 10, id="multi_container_sum"), # 2 + 8
pytest.param("pend-p", -1, id="no_series_sentinel"), # unscheduled -> no metric -> -1
],
)
def test_pods_restarts_list_mode(
signoz: types.SigNoz,
create_user_admin: None, # pylint: disable=unused-argument
get_token,
insert_metrics,
pod_name: str,
expected_restarts: int,
) -> None:
"""podRestarts is the sum of k8s.container.restarts across the pod's
containers (kubectl RESTARTS). pend-p never scheduled so emits no restart
series -> -1 no-data sentinel (kubectl would show 0)."""
now = datetime.now(tz=UTC).replace(microsecond=0)
insert_metrics(
_load_pods_metrics(
"inframonitoring/pods_phases.jsonl",
base_time=now - timedelta(minutes=4),
)
)
token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
response = requests.post(
signoz.self.host_configs["8080"].get(ENDPOINT),
headers={"authorization": f"Bearer {token}"},
json={
"start": int((now - timedelta(minutes=5)).timestamp() * 1000),
"end": int(now.timestamp() * 1000),
"limit": 50,
"filter": {"expression": f"k8s.pod.name = '{pod_name}'"},
},
timeout=5,
)
assert response.status_code == HTTPStatus.OK, response.text
data = response.json()["data"]
assert data["total"] == 1
rec = data["records"][0]
assert rec["meta"]["k8s.pod.name"] == pod_name
assert rec["podRestarts"] == expected_restarts
def test_pods_status_latest_wins(
signoz: types.SigNoz,
create_user_admin: None, # pylint: disable=unused-argument
get_token,
insert_metrics,
) -> None:
"""A stale container reason from an old incarnation must not win. trans-p's
first incarnation (container.id=aaa) reported CrashLoopBackOff, then it
recovered in a new incarnation (container.id=bbb, CrashLoopBackOff=0) while
phase went Running. kubectl shows Running; the frozen stale series is
ignored via argMax-by-latest-timestamp per (pod, container, reason)."""
now = datetime.now(tz=UTC).replace(microsecond=0)
insert_metrics(
_load_pods_metrics(
"inframonitoring/pods_phases_transition.jsonl",
base_time=now - timedelta(minutes=8),
)
)
token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
response = requests.post(
signoz.self.host_configs["8080"].get(ENDPOINT),
headers={"authorization": f"Bearer {token}"},
json={
"start": int((now - timedelta(minutes=10)).timestamp() * 1000),
"end": int(now.timestamp() * 1000),
"limit": 50,
},
timeout=5,
)
assert response.status_code == HTTPStatus.OK, response.text
data = response.json()["data"]
assert data["total"] == 1
rec = data["records"][0]
assert rec["meta"]["k8s.pod.name"] == "trans-p"
assert rec["podStatus"] == "running"
def test_pods_restarts_latest_wins(
signoz: types.SigNoz,
create_user_admin: None, # pylint: disable=unused-argument
get_token,
insert_metrics,
) -> None:
"""restartCount is cumulative per container. Across incarnations
(container.id=aaa reported 1, then container.id=bbb reported 5) podRestarts
is the LATEST value 5 (kubectl RESTARTS), not the sum 6 — incarnations must
not be double-counted."""
now = datetime.now(tz=UTC).replace(microsecond=0)
insert_metrics(
_load_pods_metrics(
"inframonitoring/pods_phases_transition.jsonl",
base_time=now - timedelta(minutes=8),
)
)
token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
response = requests.post(
signoz.self.host_configs["8080"].get(ENDPOINT),
headers={"authorization": f"Bearer {token}"},
json={
"start": int((now - timedelta(minutes=10)).timestamp() * 1000),
"end": int(now.timestamp() * 1000),
"limit": 50,
},
timeout=5,
)
assert response.status_code == HTTPStatus.OK, response.text
data = response.json()["data"]
assert data["total"] == 1
rec = data["records"][0]
assert rec["meta"]["k8s.pod.name"] == "trans-p"
assert rec["podRestarts"] == 5
def test_pods_status_grouped_mode(
signoz: types.SigNoz,
create_user_admin: None, # pylint: disable=unused-argument
get_token,
insert_metrics,
) -> None:
"""groupBy=[k8s.namespace.name] aggregates each pod's display status across
ns-mixed. podStatus is no-data (no single pod identifies the group). Seeded
states -> kubectl: g-run-1/g-run-3 Running, g-run-2 CrashLoopBackOff,
g-fail-1 Error, g-fail-2 Evicted, g-pend-1 Pending."""
now = datetime.now(tz=UTC).replace(microsecond=0)
insert_metrics(
_load_pods_metrics(
"inframonitoring/pods_phases_grouped.jsonl",
base_time=now - timedelta(minutes=4),
)
)
token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
response = requests.post(
signoz.self.host_configs["8080"].get(ENDPOINT),
headers={"authorization": f"Bearer {token}"},
json={
"start": int((now - timedelta(minutes=5)).timestamp() * 1000),
"end": int(now.timestamp() * 1000),
"limit": 50,
"groupBy": [
{
"name": "k8s.namespace.name",
"fieldDataType": "string",
"fieldContext": "resource",
}
],
},
timeout=5,
)
assert response.status_code == HTTPStatus.OK, response.text
data = response.json()["data"]
assert data["total"] == 1
rec = data["records"][0]
assert rec["meta"].get("k8s.namespace.name") == "ns-mixed"
assert rec["podStatus"] == "no_data"
expected_counts = {bucket: 0 for bucket in STATUS_BUCKETS}
expected_counts.update(
{
"running": 2,
"crashLoopBackOff": 1,
"error": 1,
"evicted": 1,
"pending": 1,
}
)
assert rec["podCountsByStatus"] == expected_counts
def test_pods_restarts_grouped_mode(
signoz: types.SigNoz,
create_user_admin: None, # pylint: disable=unused-argument
get_token,
insert_metrics,
) -> None:
"""Grouped podRestarts is the sum of restarts across all pods in the group.
In ns-mixed only g-run-2 has restarts (3); all others 0 -> group total 3."""
now = datetime.now(tz=UTC).replace(microsecond=0)
insert_metrics(
_load_pods_metrics(
"inframonitoring/pods_phases_grouped.jsonl",
base_time=now - timedelta(minutes=4),
)
)
token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
response = requests.post(
signoz.self.host_configs["8080"].get(ENDPOINT),
headers={"authorization": f"Bearer {token}"},
json={
"start": int((now - timedelta(minutes=5)).timestamp() * 1000),
"end": int(now.timestamp() * 1000),
"limit": 50,
"groupBy": [
{
"name": "k8s.namespace.name",
"fieldDataType": "string",
"fieldContext": "resource",
}
],
},
timeout=5,
)
assert response.status_code == HTTPStatus.OK, response.text
data = response.json()["data"]
assert data["total"] == 1
rec = data["records"][0]
assert rec["meta"].get("k8s.namespace.name") == "ns-mixed"
assert rec["podRestarts"] == 3
def test_pods_status_missing_metric_warning(
signoz: types.SigNoz,
create_user_admin: None, # pylint: disable=unused-argument
get_token,
insert_metrics,
) -> None:
"""When the status metrics were never ingested, the status query is gated
off: a warning naming the missing metric(s) is surfaced, podStatus is the
no-data sentinel, and all status buckets are 0. (pods_missing_metrics.jsonl
seeds only k8s.pod.cpu.usage.)"""
now = datetime.now(tz=UTC).replace(microsecond=0)
insert_metrics(
_load_pods_metrics(
"inframonitoring/pods_missing_metrics.jsonl",
base_time=now - timedelta(minutes=4),
)
)
token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
response = requests.post(
signoz.self.host_configs["8080"].get(ENDPOINT),
headers={"authorization": f"Bearer {token}"},
json={
"start": int((now - timedelta(minutes=5)).timestamp() * 1000),
"end": int(now.timestamp() * 1000),
"limit": 50,
"filter": {"expression": "k8s.pod.name = 'miss-p1'"},
},
timeout=5,
)
assert response.status_code == HTTPStatus.OK, response.text
body = response.json()
data = body["data"]
# Collect primary + additional warning messages.
warning = data.get("warning") or {}
msgs = ([warning["message"]] if warning.get("message") else []) + [w["message"] for w in warning.get("warnings", [])]
assert any("Pod status could not be computed" in m for m in msgs), f"status-gate warning missing: {msgs!r}"
assert any("k8s.container.status.reason" in m for m in msgs), f"missing metric not named: {msgs!r}"
rec = data["records"][0]
assert rec["meta"]["k8s.pod.name"] == "miss-p1"
assert rec["podStatus"] == "no_data"
for bucket in STATUS_BUCKETS:
assert rec["podCountsByStatus"][bucket] == 0, f"expected {bucket}=0 when gated off, got {rec['podCountsByStatus']}"
assert rec["podRestarts"] == -1

View File

@@ -10,6 +10,7 @@ import requests
from fixtures import types
from fixtures.auth import USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD
from fixtures.fs import get_testdata_file_path
from fixtures.inframonitoring import expected_status_counts
from fixtures.metrics import Metrics
from fixtures.querier import compare_values, get_all_warnings
@@ -404,6 +405,49 @@ def test_clusters_pod_phase_aggregation(
}
def test_clusters_pod_status_aggregation(
signoz: types.SigNoz,
create_user_admin: None, # pylint: disable=unused-argument
get_token,
insert_metrics,
) -> None:
"""Cluster's pods aggregated by kubectl-style display status. Seeded states
in clusters_pod_phases.jsonl -> what kubectl would show:
pp-run-1/3/4 Running, pp-run-2 CrashLoopBackOff (phase Running),
pp-fail-1 Error, pp-fail-2 Evicted (pod-level), pp-pend-1 Pending.
"""
now = datetime.now(tz=UTC).replace(microsecond=0)
insert_metrics(
Metrics.load_from_file(
get_testdata_file_path("inframonitoring/clusters_pod_phases.jsonl"),
base_time=now - timedelta(minutes=4),
)
)
token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
response = requests.post(
signoz.self.host_configs["8080"].get(ENDPOINT),
headers={"authorization": f"Bearer {token}"},
json={
"start": int((now - timedelta(minutes=5)).timestamp() * 1000),
"end": int(now.timestamp() * 1000),
"limit": 50,
"filter": {"expression": "k8s.cluster.name = 'pp-cluster'"},
},
timeout=5,
)
assert response.status_code == HTTPStatus.OK, response.text
data = response.json()["data"]
assert data["total"] == 1
rec = data["records"][0]
assert rec["clusterName"] == "pp-cluster"
assert rec["podCountsByStatus"] == expected_status_counts(running=3, crashLoopBackOff=1, error=1, evicted=1, pending=1)
# Phase counts unchanged by the status enrichment.
assert rec["podCountsByPhase"] == {"pending": 1, "running": 4, "succeeded": 0, "failed": 2, "unknown": 0}
# All status metrics present -> gate satisfied -> no status warning.
assert all("Pod status could not be computed" not in w["message"] for w in get_all_warnings(response.json()))
@pytest.mark.parametrize(
"group_key,expected",
[

View File

@@ -10,6 +10,7 @@ import requests
from fixtures import types
from fixtures.auth import USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD
from fixtures.fs import get_testdata_file_path
from fixtures.inframonitoring import expected_status_counts
from fixtures.metrics import Metrics
from fixtures.querier import compare_values, get_all_warnings
@@ -385,6 +386,49 @@ def test_deployments_pod_phase_aggregation(
}
def test_deployments_pod_status_aggregation(
signoz: types.SigNoz,
create_user_admin: None, # pylint: disable=unused-argument
get_token,
insert_metrics,
) -> None:
"""Deployment's pods aggregated by kubectl-style display status. Seeded states
in deployments_pod_phases.jsonl -> what kubectl would show:
pp-run-1/3/4 Running, pp-run-2 CrashLoopBackOff (phase Running),
pp-fail-1 Error, pp-fail-2 Evicted (pod-level), pp-pen-1 Pending.
"""
now = datetime.now(tz=UTC).replace(microsecond=0)
insert_metrics(
Metrics.load_from_file(
get_testdata_file_path("inframonitoring/deployments_pod_phases.jsonl"),
base_time=now - timedelta(minutes=4),
)
)
token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
response = requests.post(
signoz.self.host_configs["8080"].get(ENDPOINT),
headers={"authorization": f"Bearer {token}"},
json={
"start": int((now - timedelta(minutes=5)).timestamp() * 1000),
"end": int(now.timestamp() * 1000),
"limit": 50,
"filter": {"expression": "k8s.deployment.name = 'pp-dep'"},
},
timeout=5,
)
assert response.status_code == HTTPStatus.OK, response.text
data = response.json()["data"]
assert data["total"] == 1
rec = data["records"][0]
assert rec["deploymentName"] == "pp-dep"
assert rec["podCountsByStatus"] == expected_status_counts(running=3, crashLoopBackOff=1, error=1, evicted=1, pending=1)
# Phase counts unchanged by the status enrichment.
assert rec["podCountsByPhase"] == {"pending": 1, "running": 4, "succeeded": 0, "failed": 2, "unknown": 0}
# All status metrics present -> gate satisfied -> no status warning.
assert all("Pod status could not be computed" not in w["message"] for w in get_all_warnings(response.json()))
def test_deployments_desired_available_counts(
signoz: types.SigNoz,
create_user_admin: None, # pylint: disable=unused-argument

View File

@@ -45,6 +45,13 @@ _PODS_OPT = [
"k8s.pod.memory_limit_utilization",
]
# Default-off pod-status metrics (k8sclusterreceiver), optional on every tab
# that surfaces pod status counts.
_POD_STATUS_OPT = [
"k8s.pod.status_reason",
"k8s.container.status.reason",
]
# Mirror of checkSpecs: type -> {default|optional: {component: [metrics]}, attrs: {component: [attrs]}}.
SPECS = {
"hosts": {
@@ -58,8 +65,8 @@ SPECS = {
"attrs": {HMR: ["process.pid"]},
},
"pods": {
"default": {KSR: ["k8s.pod.cpu.usage", "k8s.pod.memory.working_set"], KCR: ["k8s.pod.phase"]},
"optional": {KSR: list(_PODS_OPT)},
"default": {KSR: ["k8s.pod.cpu.usage", "k8s.pod.memory.working_set"], KCR: ["k8s.pod.phase", "k8s.container.restarts"]},
"optional": {KSR: list(_PODS_OPT), KCR: ["k8s.pod.status_reason", "k8s.container.status.reason"]},
"attrs": {KAP: ["k8s.pod.uid"]},
},
"nodes": {
@@ -67,37 +74,37 @@ SPECS = {
KSR: ["k8s.node.cpu.usage", "k8s.node.memory.working_set"],
KCR: ["k8s.node.allocatable_cpu", "k8s.node.allocatable_memory", "k8s.node.condition_ready", "k8s.pod.phase"],
},
"optional": {},
"optional": {KCR: list(_POD_STATUS_OPT)},
"attrs": {KAP: ["k8s.node.name"]},
},
"deployments": {
"default": {KSR: ["k8s.pod.cpu.usage", "k8s.pod.memory.working_set"], KCR: ["k8s.pod.phase", "k8s.deployment.desired", "k8s.deployment.available"]},
"optional": {KSR: list(_PODS_OPT)},
"optional": {KSR: list(_PODS_OPT), KCR: list(_POD_STATUS_OPT)},
"attrs": {KAP: ["k8s.deployment.name", "k8s.namespace.name"], RDP: ["k8s.cluster.name"]},
},
"daemonsets": {
"default": {KSR: ["k8s.pod.cpu.usage", "k8s.pod.memory.working_set"], KCR: ["k8s.pod.phase", "k8s.daemonset.desired_scheduled_nodes", "k8s.daemonset.current_scheduled_nodes"]},
"optional": {KSR: list(_PODS_OPT)},
"optional": {KSR: list(_PODS_OPT), KCR: list(_POD_STATUS_OPT)},
"attrs": {KAP: ["k8s.daemonset.name", "k8s.namespace.name"], RDP: ["k8s.cluster.name"]},
},
"statefulsets": {
"default": {KSR: ["k8s.pod.cpu.usage", "k8s.pod.memory.working_set"], KCR: ["k8s.pod.phase", "k8s.statefulset.desired_pods", "k8s.statefulset.current_pods"]},
"optional": {KSR: list(_PODS_OPT)},
"optional": {KSR: list(_PODS_OPT), KCR: list(_POD_STATUS_OPT)},
"attrs": {KAP: ["k8s.statefulset.name", "k8s.namespace.name"], RDP: ["k8s.cluster.name"]},
},
"jobs": {
"default": {KSR: ["k8s.pod.cpu.usage", "k8s.pod.memory.working_set"], KCR: ["k8s.pod.phase", "k8s.job.desired_successful_pods", "k8s.job.active_pods", "k8s.job.failed_pods", "k8s.job.successful_pods"]},
"optional": {KSR: list(_PODS_OPT)},
"optional": {KSR: list(_PODS_OPT), KCR: list(_POD_STATUS_OPT)},
"attrs": {KAP: ["k8s.job.name", "k8s.namespace.name"], RDP: ["k8s.cluster.name"]},
},
"namespaces": {
"default": {KSR: ["k8s.pod.cpu.usage", "k8s.pod.memory.working_set"], KCR: ["k8s.pod.phase"]},
"optional": {},
"optional": {KCR: list(_POD_STATUS_OPT)},
"attrs": {KAP: ["k8s.namespace.name"], RDP: ["k8s.cluster.name"]},
},
"clusters": {
"default": {KSR: ["k8s.node.cpu.usage", "k8s.node.memory.working_set"], KCR: ["k8s.node.allocatable_cpu", "k8s.node.allocatable_memory", "k8s.node.condition_ready", "k8s.pod.phase"]},
"optional": {},
"optional": {KCR: list(_POD_STATUS_OPT)},
"attrs": {RDP: ["k8s.cluster.name"]},
},
"volumes": {