Compare commits

..

1 Commits

48 changed files with 1092 additions and 1399 deletions

View File

@@ -3938,6 +3938,8 @@ components:
items:
$ref: '#/components/schemas/InframonitoringtypesClusterRecord'
type: array
requiredMetricsCheck:
$ref: '#/components/schemas/InframonitoringtypesRequiredMetricsCheck'
total:
type: integer
type:
@@ -3948,6 +3950,7 @@ components:
- type
- records
- total
- requiredMetricsCheck
- endTimeBeforeRetention
type: object
InframonitoringtypesDaemonSetRecord:
@@ -4004,6 +4007,8 @@ components:
items:
$ref: '#/components/schemas/InframonitoringtypesDaemonSetRecord'
type: array
requiredMetricsCheck:
$ref: '#/components/schemas/InframonitoringtypesRequiredMetricsCheck'
total:
type: integer
type:
@@ -4014,6 +4019,7 @@ components:
- type
- records
- total
- requiredMetricsCheck
- endTimeBeforeRetention
type: object
InframonitoringtypesDeploymentRecord:
@@ -4070,6 +4076,8 @@ components:
items:
$ref: '#/components/schemas/InframonitoringtypesDeploymentRecord'
type: array
requiredMetricsCheck:
$ref: '#/components/schemas/InframonitoringtypesRequiredMetricsCheck'
total:
type: integer
type:
@@ -4080,6 +4088,7 @@ components:
- type
- records
- total
- requiredMetricsCheck
- endTimeBeforeRetention
type: object
InframonitoringtypesHostFilter:
@@ -4145,6 +4154,8 @@ components:
items:
$ref: '#/components/schemas/InframonitoringtypesHostRecord'
type: array
requiredMetricsCheck:
$ref: '#/components/schemas/InframonitoringtypesRequiredMetricsCheck'
total:
type: integer
type:
@@ -4155,6 +4166,7 @@ components:
- type
- records
- total
- requiredMetricsCheck
- endTimeBeforeRetention
type: object
InframonitoringtypesJobRecord:
@@ -4217,6 +4229,8 @@ components:
items:
$ref: '#/components/schemas/InframonitoringtypesJobRecord'
type: array
requiredMetricsCheck:
$ref: '#/components/schemas/InframonitoringtypesRequiredMetricsCheck'
total:
type: integer
type:
@@ -4227,6 +4241,7 @@ components:
- type
- records
- total
- requiredMetricsCheck
- endTimeBeforeRetention
type: object
InframonitoringtypesNamespaceRecord:
@@ -4261,6 +4276,8 @@ components:
items:
$ref: '#/components/schemas/InframonitoringtypesNamespaceRecord'
type: array
requiredMetricsCheck:
$ref: '#/components/schemas/InframonitoringtypesRequiredMetricsCheck'
total:
type: integer
type:
@@ -4271,6 +4288,7 @@ components:
- type
- records
- total
- requiredMetricsCheck
- endTimeBeforeRetention
type: object
InframonitoringtypesNodeCondition:
@@ -4335,6 +4353,8 @@ components:
items:
$ref: '#/components/schemas/InframonitoringtypesNodeRecord'
type: array
requiredMetricsCheck:
$ref: '#/components/schemas/InframonitoringtypesRequiredMetricsCheck'
total:
type: integer
type:
@@ -4345,6 +4365,7 @@ components:
- type
- records
- total
- requiredMetricsCheck
- endTimeBeforeRetention
type: object
InframonitoringtypesPodCountsByPhase:
@@ -4430,6 +4451,8 @@ components:
items:
$ref: '#/components/schemas/InframonitoringtypesPodRecord'
type: array
requiredMetricsCheck:
$ref: '#/components/schemas/InframonitoringtypesRequiredMetricsCheck'
total:
type: integer
type:
@@ -4440,6 +4463,7 @@ components:
- type
- records
- total
- requiredMetricsCheck
- endTimeBeforeRetention
type: object
InframonitoringtypesPostableClusters:
@@ -4702,6 +4726,16 @@ components:
- end
- limit
type: object
InframonitoringtypesRequiredMetricsCheck:
properties:
missingMetrics:
items:
type: string
nullable: true
type: array
required:
- missingMetrics
type: object
InframonitoringtypesResponseType:
enum:
- list
@@ -4761,6 +4795,8 @@ components:
items:
$ref: '#/components/schemas/InframonitoringtypesStatefulSetRecord'
type: array
requiredMetricsCheck:
$ref: '#/components/schemas/InframonitoringtypesRequiredMetricsCheck'
total:
type: integer
type:
@@ -4771,6 +4807,7 @@ components:
- type
- records
- total
- requiredMetricsCheck
- endTimeBeforeRetention
type: object
InframonitoringtypesVolumeRecord:
@@ -4818,6 +4855,8 @@ components:
items:
$ref: '#/components/schemas/InframonitoringtypesVolumeRecord'
type: array
requiredMetricsCheck:
$ref: '#/components/schemas/InframonitoringtypesRequiredMetricsCheck'
total:
type: integer
type:
@@ -4828,6 +4867,7 @@ components:
- type
- records
- total
- requiredMetricsCheck
- endTimeBeforeRetention
type: object
LlmpricingruletypesGettablePricingRules:
@@ -14655,10 +14695,10 @@ paths:
for custom groupBy keys; in both modes every row aggregates nodes and pods
in the group. Supports filtering via a filter expression, custom groupBy,
ordering by cpu / cpu_allocatable / memory / memory_allocatable, and pagination
via offset/limit. Also reports whether the requested time range falls before
the data retention boundary. Numeric metric fields (clusterCPU, clusterCPUAllocatable,
clusterMemory, clusterMemoryAllocatable) return -1 as a sentinel when no data
is available for that field.'
via offset/limit. Also reports missing required metrics and whether the requested
time range falls before the data retention boundary. Numeric metric fields
(clusterCPU, clusterCPUAllocatable, clusterMemory, clusterMemoryAllocatable)
return -1 as a sentinel when no data is available for that field.'
operationId: ListClusters
requestBody:
content:
@@ -14731,11 +14771,11 @@ paths:
row aggregates pods owned by daemonsets in the group. Supports filtering via
a filter expression, custom groupBy, ordering by cpu / cpu_request / cpu_limit
/ memory / memory_request / memory_limit / desired_nodes / current_nodes,
and pagination via offset/limit. Also reports whether the requested time range
falls before the data retention boundary. Numeric metric fields (daemonSetCPU,
daemonSetCPURequest, daemonSetCPULimit, daemonSetMemory, daemonSetMemoryRequest,
daemonSetMemoryLimit, desiredNodes, currentNodes) return -1 as a sentinel
when no data is available for that field.'
and pagination via offset/limit. Also reports missing required metrics and
whether the requested time range falls before the data retention boundary.
Numeric metric fields (daemonSetCPU, daemonSetCPURequest, daemonSetCPULimit,
daemonSetMemory, daemonSetMemoryRequest, daemonSetMemoryLimit, desiredNodes,
currentNodes) return -1 as a sentinel when no data is available for that field.'
operationId: ListDaemonSets
requestBody:
content:
@@ -14806,11 +14846,11 @@ paths:
group. Supports filtering via a filter expression, custom groupBy, ordering
by cpu / cpu_request / cpu_limit / memory / memory_request / memory_limit
/ desired_pods / available_pods, and pagination via offset/limit. Also reports
whether the requested time range falls before the data retention boundary.
Numeric metric fields (deploymentCPU, deploymentCPURequest, deploymentCPULimit,
deploymentMemory, deploymentMemoryRequest, deploymentMemoryLimit, desiredPods,
availablePods) return -1 as a sentinel when no data is available for that
field.'
missing required metrics and whether the requested time range falls before
the data retention boundary. Numeric metric fields (deploymentCPU, deploymentCPURequest,
deploymentCPULimit, deploymentMemory, deploymentMemoryRequest, deploymentMemoryLimit,
desiredPods, availablePods) return -1 as a sentinel when no data is available
for that field.'
operationId: ListDeployments
requestBody:
content:
@@ -14875,9 +14915,10 @@ paths:
custom groupBy to aggregate hosts by any attribute, ordering by any of the
five metrics, and pagination via offset/limit. The response type is ''list''
for the default host.name grouping or ''grouped_list'' for custom groupBy
keys. Also reports whether the requested time range falls before the data
retention boundary. Numeric metric fields (cpu, memory, wait, load15, diskUsage)
return -1 as a sentinel when no data is available for that field.'
keys. Also reports missing required metrics and whether the requested time
range falls before the data retention boundary. Numeric metric fields (cpu,
memory, wait, load15, diskUsage) return -1 as a sentinel when no data is available
for that field.'
operationId: ListHosts
requestBody:
content:
@@ -14951,11 +14992,11 @@ paths:
jobs in the group. Supports filtering via a filter expression, custom groupBy,
ordering by cpu / cpu_request / cpu_limit / memory / memory_request / memory_limit
/ desired_successful_pods / active_pods / failed_pods / successful_pods, and
pagination via offset/limit. Also reports whether the requested time range
falls before the data retention boundary. Numeric metric fields (jobCPU, jobCPURequest,
jobCPULimit, jobMemory, jobMemoryRequest, jobMemoryLimit, desiredSuccessfulPods,
activePods, failedPods, successfulPods) return -1 as a sentinel when no data
is available for that field.'
pagination via offset/limit. Also reports missing required metrics and whether
the requested time range falls before the data retention boundary. Numeric
metric fields (jobCPU, jobCPURequest, jobCPULimit, jobMemory, jobMemoryRequest,
jobMemoryLimit, desiredSuccessfulPods, activePods, failedPods, successfulPods)
return -1 as a sentinel when no data is available for that field.'
operationId: ListJobs
requestBody:
content:
@@ -15020,10 +15061,10 @@ paths:
type is ''list'' for the default k8s.namespace.name grouping or ''grouped_list''
for custom groupBy keys; in both modes every row aggregates pods in the group.
Supports filtering via a filter expression, custom groupBy, ordering by cpu
/ memory, and pagination via offset/limit. Also reports whether the requested
time range falls before the data retention boundary. Numeric metric fields
(namespaceCPU, namespaceMemory) return -1 as a sentinel when no data is available
for that field.'
/ memory, and pagination via offset/limit. Also reports missing required metrics
and whether the requested time range falls before the data retention boundary.
Numeric metric fields (namespaceCPU, namespaceMemory) return -1 as a sentinel
when no data is available for that field.'
operationId: ListNamespaces
requestBody:
content:
@@ -15091,10 +15132,10 @@ paths:
for custom groupBy keys (each row aggregates nodes in the group; condition
stays no_data). Supports filtering via a filter expression, custom groupBy,
ordering by cpu / cpu_allocatable / memory / memory_allocatable, and pagination
via offset/limit. Also reports whether the requested time range falls before
the data retention boundary. Numeric metric fields (nodeCPU, nodeCPUAllocatable,
nodeMemory, nodeMemoryAllocatable) return -1 as a sentinel when no data is
available for that field.'
via offset/limit. Also reports missing required metrics and whether the requested
time range falls before the data retention boundary. Numeric metric fields
(nodeCPU, nodeCPUAllocatable, nodeMemory, nodeMemoryAllocatable) return -1
as a sentinel when no data is available for that field.'
operationId: ListNodes
requestBody:
content:
@@ -15163,10 +15204,11 @@ paths:
is one pod with its current phase) or ''grouped_list'' for custom groupBy
keys (each row aggregates pods in the group with per-phase counts under podCountsByPhase:
{ pending, running, succeeded, failed, unknown } derived from each pod''s
latest phase in the window). Also reports whether the requested time range
falls before the data retention boundary. Numeric metric fields (podCPU, podCPURequest,
podCPULimit, podMemory, podMemoryRequest, podMemoryLimit, podAge) return -1
as a sentinel when no data is available for that field.'
latest phase in the window). Also reports missing required metrics and whether
the requested time range falls before the data retention boundary. Numeric
metric fields (podCPU, podCPURequest, podCPULimit, podMemory, podMemoryRequest,
podMemoryLimit, podAge) return -1 as a sentinel when no data is available
for that field.'
operationId: ListPods
requestBody:
content:
@@ -15233,10 +15275,11 @@ paths:
usage, inodes, inodes_free, inodes_used), and pagination via offset/limit.
The response type is ''list'' for the default k8s.persistentvolumeclaim.name
grouping or ''grouped_list'' for custom groupBy keys; in both modes every
row aggregates volumes in the group. Also reports whether the requested time
range falls before the data retention boundary. Numeric metric fields (volumeAvailable,
volumeCapacity, volumeUsage, volumeInodes, volumeInodesFree, volumeInodesUsed)
return -1 as a sentinel when no data is available for that field.'
row aggregates volumes in the group. Also reports missing required metrics
and whether the requested time range falls before the data retention boundary.
Numeric metric fields (volumeAvailable, volumeCapacity, volumeUsage, volumeInodes,
volumeInodesFree, volumeInodesUsed) return -1 as a sentinel when no data is
available for that field.'
operationId: ListVolumes
requestBody:
content:
@@ -15307,10 +15350,11 @@ paths:
statefulsets in the group. Supports filtering via a filter expression, custom
groupBy, ordering by cpu / cpu_request / cpu_limit / memory / memory_request
/ memory_limit / desired_pods / current_pods, and pagination via offset/limit.
Also reports whether the requested time range falls before the data retention
boundary. Numeric metric fields (statefulSetCPU, statefulSetCPURequest, statefulSetCPULimit,
statefulSetMemory, statefulSetMemoryRequest, statefulSetMemoryLimit, desiredPods,
currentPods) return -1 as a sentinel when no data is available for that field.'
Also reports missing required metrics and whether the requested time range
falls before the data retention boundary. Numeric metric fields (statefulSetCPU,
statefulSetCPURequest, statefulSetCPULimit, statefulSetMemory, statefulSetMemoryRequest,
statefulSetMemoryLimit, desiredPods, currentPods) return -1 as a sentinel
when no data is available for that field.'
operationId: ListStatefulSets
requestBody:
content:

View File

@@ -39,7 +39,7 @@ import { GeneratedAPIInstance } from '../../../generatedAPIInstance';
import type { ErrorType, BodyType } from '../../../generatedAPIInstance';
/**
* Returns a paginated list of Kubernetes clusters with key aggregated metrics derived by summing per-node values within the group: CPU usage, CPU allocatable, memory working set, memory allocatable. Each row also reports per-group nodeCountsByReadiness ({ ready, notReady } from each node's latest k8s.node.condition_ready value) and per-group podCountsByPhase ({ pending, running, succeeded, failed, unknown } from each pod's latest k8s.pod.phase value). Each cluster includes metadata attributes (k8s.cluster.name). The response type is 'list' for the default k8s.cluster.name grouping or 'grouped_list' for custom groupBy keys; in both modes every row aggregates nodes and pods in the group. Supports filtering via a filter expression, custom groupBy, ordering by cpu / cpu_allocatable / memory / memory_allocatable, and pagination via offset/limit. Also reports whether the requested time range falls before the data retention boundary. Numeric metric fields (clusterCPU, clusterCPUAllocatable, clusterMemory, clusterMemoryAllocatable) return -1 as a sentinel when no data is available for that field.
* Returns a paginated list of Kubernetes clusters with key aggregated metrics derived by summing per-node values within the group: CPU usage, CPU allocatable, memory working set, memory allocatable. Each row also reports per-group nodeCountsByReadiness ({ ready, notReady } from each node's latest k8s.node.condition_ready value) and per-group podCountsByPhase ({ pending, running, succeeded, failed, unknown } from each pod's latest k8s.pod.phase value). Each cluster includes metadata attributes (k8s.cluster.name). The response type is 'list' for the default k8s.cluster.name grouping or 'grouped_list' for custom groupBy keys; in both modes every row aggregates nodes and pods in the group. Supports filtering via a filter expression, custom groupBy, ordering by cpu / cpu_allocatable / memory / memory_allocatable, and pagination via offset/limit. Also reports missing required metrics and whether the requested time range falls before the data retention boundary. Numeric metric fields (clusterCPU, clusterCPUAllocatable, clusterMemory, clusterMemoryAllocatable) return -1 as a sentinel when no data is available for that field.
* @summary List Clusters for Infra Monitoring
*/
export const listClusters = (
@@ -122,7 +122,7 @@ export const useListClusters = <
return useMutation(getListClustersMutationOptions(options));
};
/**
* Returns a paginated list of Kubernetes DaemonSets with key aggregated pod metrics: CPU usage and memory working set summed across pods owned by the daemonset, plus average CPU/memory request and limit utilization (daemonSetCPURequest, daemonSetCPULimit, daemonSetMemoryRequest, daemonSetMemoryLimit). Each row also reports the latest known node-level counters from kube-state-metrics: desiredNodes (k8s.daemonset.desired_scheduled_nodes, the number of nodes the daemonset wants to run on) and currentNodes (k8s.daemonset.current_scheduled_nodes, the number of nodes the daemonset currently runs on) — note these are node counts, not pod counts. It also reports per-group podCountsByPhase ({ pending, running, succeeded, failed, unknown } from each pod's latest k8s.pod.phase value). Each daemonset includes metadata attributes (k8s.daemonset.name, k8s.namespace.name, k8s.cluster.name). The response type is 'list' for the default k8s.daemonset.name grouping or 'grouped_list' for custom groupBy keys; in both modes every row aggregates pods owned by daemonsets in the group. Supports filtering via a filter expression, custom groupBy, ordering by cpu / cpu_request / cpu_limit / memory / memory_request / memory_limit / desired_nodes / current_nodes, and pagination via offset/limit. Also reports whether the requested time range falls before the data retention boundary. Numeric metric fields (daemonSetCPU, daemonSetCPURequest, daemonSetCPULimit, daemonSetMemory, daemonSetMemoryRequest, daemonSetMemoryLimit, desiredNodes, currentNodes) return -1 as a sentinel when no data is available for that field.
* Returns a paginated list of Kubernetes DaemonSets with key aggregated pod metrics: CPU usage and memory working set summed across pods owned by the daemonset, plus average CPU/memory request and limit utilization (daemonSetCPURequest, daemonSetCPULimit, daemonSetMemoryRequest, daemonSetMemoryLimit). Each row also reports the latest known node-level counters from kube-state-metrics: desiredNodes (k8s.daemonset.desired_scheduled_nodes, the number of nodes the daemonset wants to run on) and currentNodes (k8s.daemonset.current_scheduled_nodes, the number of nodes the daemonset currently runs on) — note these are node counts, not pod counts. It also reports per-group podCountsByPhase ({ pending, running, succeeded, failed, unknown } from each pod's latest k8s.pod.phase value). Each daemonset includes metadata attributes (k8s.daemonset.name, k8s.namespace.name, k8s.cluster.name). The response type is 'list' for the default k8s.daemonset.name grouping or 'grouped_list' for custom groupBy keys; in both modes every row aggregates pods owned by daemonsets in the group. Supports filtering via a filter expression, custom groupBy, ordering by cpu / cpu_request / cpu_limit / memory / memory_request / memory_limit / desired_nodes / current_nodes, and pagination via offset/limit. Also reports missing required metrics and whether the requested time range falls before the data retention boundary. Numeric metric fields (daemonSetCPU, daemonSetCPURequest, daemonSetCPULimit, daemonSetMemory, daemonSetMemoryRequest, daemonSetMemoryLimit, desiredNodes, currentNodes) return -1 as a sentinel when no data is available for that field.
* @summary List DaemonSets for Infra Monitoring
*/
export const listDaemonSets = (
@@ -205,7 +205,7 @@ export const useListDaemonSets = <
return useMutation(getListDaemonSetsMutationOptions(options));
};
/**
* Returns a paginated list of Kubernetes Deployments with key aggregated pod metrics: CPU usage and memory working set summed across pods owned by the deployment, plus average CPU/memory request and limit utilization (deploymentCPURequest, deploymentCPULimit, deploymentMemoryRequest, deploymentMemoryLimit). Each row also reports the latest known desiredPods (k8s.deployment.desired) and availablePods (k8s.deployment.available) replica counts and per-group podCountsByPhase ({ pending, running, succeeded, failed, unknown } from each pod's latest k8s.pod.phase value). Each deployment includes metadata attributes (k8s.deployment.name, k8s.namespace.name, k8s.cluster.name). The response type is 'list' for the default k8s.deployment.name grouping or 'grouped_list' for custom groupBy keys; in both modes every row aggregates pods owned by deployments in the group. Supports filtering via a filter expression, custom groupBy, ordering by cpu / cpu_request / cpu_limit / memory / memory_request / memory_limit / desired_pods / available_pods, and pagination via offset/limit. Also reports whether the requested time range falls before the data retention boundary. Numeric metric fields (deploymentCPU, deploymentCPURequest, deploymentCPULimit, deploymentMemory, deploymentMemoryRequest, deploymentMemoryLimit, desiredPods, availablePods) return -1 as a sentinel when no data is available for that field.
* Returns a paginated list of Kubernetes Deployments with key aggregated pod metrics: CPU usage and memory working set summed across pods owned by the deployment, plus average CPU/memory request and limit utilization (deploymentCPURequest, deploymentCPULimit, deploymentMemoryRequest, deploymentMemoryLimit). Each row also reports the latest known desiredPods (k8s.deployment.desired) and availablePods (k8s.deployment.available) replica counts and per-group podCountsByPhase ({ pending, running, succeeded, failed, unknown } from each pod's latest k8s.pod.phase value). Each deployment includes metadata attributes (k8s.deployment.name, k8s.namespace.name, k8s.cluster.name). The response type is 'list' for the default k8s.deployment.name grouping or 'grouped_list' for custom groupBy keys; in both modes every row aggregates pods owned by deployments in the group. Supports filtering via a filter expression, custom groupBy, ordering by cpu / cpu_request / cpu_limit / memory / memory_request / memory_limit / desired_pods / available_pods, and pagination via offset/limit. Also reports missing required metrics and whether the requested time range falls before the data retention boundary. Numeric metric fields (deploymentCPU, deploymentCPURequest, deploymentCPULimit, deploymentMemory, deploymentMemoryRequest, deploymentMemoryLimit, desiredPods, availablePods) return -1 as a sentinel when no data is available for that field.
* @summary List Deployments for Infra Monitoring
*/
export const listDeployments = (
@@ -288,7 +288,7 @@ export const useListDeployments = <
return useMutation(getListDeploymentsMutationOptions(options));
};
/**
* Returns a paginated list of hosts with key infrastructure metrics: CPU usage (%), memory usage (%), I/O wait (%), disk usage (%), and 15-minute load average. Each host includes its current status (active/inactive based on metrics reported in the last 10 minutes) and metadata attributes (e.g., os.type). Supports filtering via a filter expression, filtering by host status, custom groupBy to aggregate hosts by any attribute, ordering by any of the five metrics, and pagination via offset/limit. The response type is 'list' for the default host.name grouping or 'grouped_list' for custom groupBy keys. Also reports whether the requested time range falls before the data retention boundary. Numeric metric fields (cpu, memory, wait, load15, diskUsage) return -1 as a sentinel when no data is available for that field.
* Returns a paginated list of hosts with key infrastructure metrics: CPU usage (%), memory usage (%), I/O wait (%), disk usage (%), and 15-minute load average. Each host includes its current status (active/inactive based on metrics reported in the last 10 minutes) and metadata attributes (e.g., os.type). Supports filtering via a filter expression, filtering by host status, custom groupBy to aggregate hosts by any attribute, ordering by any of the five metrics, and pagination via offset/limit. The response type is 'list' for the default host.name grouping or 'grouped_list' for custom groupBy keys. Also reports missing required metrics and whether the requested time range falls before the data retention boundary. Numeric metric fields (cpu, memory, wait, load15, diskUsage) return -1 as a sentinel when no data is available for that field.
* @summary List Hosts for Infra Monitoring
*/
export const listHosts = (
@@ -371,7 +371,7 @@ export const useListHosts = <
return useMutation(getListHostsMutationOptions(options));
};
/**
* Returns a paginated list of Kubernetes Jobs with key aggregated pod metrics: CPU usage and memory working set summed across pods owned by the job, plus average CPU/memory request and limit utilization (jobCPURequest, jobCPULimit, jobMemoryRequest, jobMemoryLimit). Each row also reports the latest known job-level counters from kube-state-metrics: desiredSuccessfulPods (k8s.job.desired_successful_pods, the target completion count), activePods (k8s.job.active_pods), failedPods (k8s.job.failed_pods, cumulative across the lifetime of the job), and successfulPods (k8s.job.successful_pods, cumulative). It also reports per-group podCountsByPhase ({ pending, running, succeeded, failed, unknown } from each pod's latest k8s.pod.phase value); note podCountsByPhase.failed (current pod-phase) is distinct from failedPods (cumulative job kube-state-metric). Each job includes metadata attributes (k8s.job.name, k8s.namespace.name, k8s.cluster.name). The response type is 'list' for the default k8s.job.name grouping or 'grouped_list' for custom groupBy keys; in both modes every row aggregates pods owned by jobs in the group. Supports filtering via a filter expression, custom groupBy, ordering by cpu / cpu_request / cpu_limit / memory / memory_request / memory_limit / desired_successful_pods / active_pods / failed_pods / successful_pods, and pagination via offset/limit. Also reports whether the requested time range falls before the data retention boundary. Numeric metric fields (jobCPU, jobCPURequest, jobCPULimit, jobMemory, jobMemoryRequest, jobMemoryLimit, desiredSuccessfulPods, activePods, failedPods, successfulPods) return -1 as a sentinel when no data is available for that field.
* Returns a paginated list of Kubernetes Jobs with key aggregated pod metrics: CPU usage and memory working set summed across pods owned by the job, plus average CPU/memory request and limit utilization (jobCPURequest, jobCPULimit, jobMemoryRequest, jobMemoryLimit). Each row also reports the latest known job-level counters from kube-state-metrics: desiredSuccessfulPods (k8s.job.desired_successful_pods, the target completion count), activePods (k8s.job.active_pods), failedPods (k8s.job.failed_pods, cumulative across the lifetime of the job), and successfulPods (k8s.job.successful_pods, cumulative). It also reports per-group podCountsByPhase ({ pending, running, succeeded, failed, unknown } from each pod's latest k8s.pod.phase value); note podCountsByPhase.failed (current pod-phase) is distinct from failedPods (cumulative job kube-state-metric). Each job includes metadata attributes (k8s.job.name, k8s.namespace.name, k8s.cluster.name). The response type is 'list' for the default k8s.job.name grouping or 'grouped_list' for custom groupBy keys; in both modes every row aggregates pods owned by jobs in the group. Supports filtering via a filter expression, custom groupBy, ordering by cpu / cpu_request / cpu_limit / memory / memory_request / memory_limit / desired_successful_pods / active_pods / failed_pods / successful_pods, and pagination via offset/limit. Also reports missing required metrics and whether the requested time range falls before the data retention boundary. Numeric metric fields (jobCPU, jobCPURequest, jobCPULimit, jobMemory, jobMemoryRequest, jobMemoryLimit, desiredSuccessfulPods, activePods, failedPods, successfulPods) return -1 as a sentinel when no data is available for that field.
* @summary List Jobs for Infra Monitoring
*/
export const listJobs = (
@@ -454,7 +454,7 @@ export const useListJobs = <
return useMutation(getListJobsMutationOptions(options));
};
/**
* Returns a paginated list of Kubernetes namespaces with key aggregated pod metrics: CPU usage and memory working set (summed across pods in the group), plus per-group podCountsByPhase ({ pending, running, succeeded, failed, unknown } from each pod's latest k8s.pod.phase value in the window). Each namespace includes metadata attributes (k8s.namespace.name, k8s.cluster.name). The response type is 'list' for the default k8s.namespace.name grouping or 'grouped_list' for custom groupBy keys; in both modes every row aggregates pods in the group. Supports filtering via a filter expression, custom groupBy, ordering by cpu / memory, and pagination via offset/limit. Also reports whether the requested time range falls before the data retention boundary. Numeric metric fields (namespaceCPU, namespaceMemory) return -1 as a sentinel when no data is available for that field.
* Returns a paginated list of Kubernetes namespaces with key aggregated pod metrics: CPU usage and memory working set (summed across pods in the group), plus per-group podCountsByPhase ({ pending, running, succeeded, failed, unknown } from each pod's latest k8s.pod.phase value in the window). Each namespace includes metadata attributes (k8s.namespace.name, k8s.cluster.name). The response type is 'list' for the default k8s.namespace.name grouping or 'grouped_list' for custom groupBy keys; in both modes every row aggregates pods in the group. Supports filtering via a filter expression, custom groupBy, ordering by cpu / memory, and pagination via offset/limit. Also reports missing required metrics and whether the requested time range falls before the data retention boundary. Numeric metric fields (namespaceCPU, namespaceMemory) return -1 as a sentinel when no data is available for that field.
* @summary List Namespaces for Infra Monitoring
*/
export const listNamespaces = (
@@ -537,7 +537,7 @@ export const useListNamespaces = <
return useMutation(getListNamespacesMutationOptions(options));
};
/**
* Returns a paginated list of Kubernetes nodes with key metrics: CPU usage, CPU allocatable, memory working set, memory allocatable, per-group nodeCountsByReadiness ({ ready, notReady } from each node's latest k8s.node.condition_ready in the window) and per-group podCountsByPhase ({ pending, running, succeeded, failed, unknown } for pods scheduled on the listed nodes). Each node includes metadata attributes (k8s.node.uid, k8s.cluster.name). The response type is 'list' for the default k8s.node.name grouping (each row is one node with its current condition string: ready / not_ready / no_data) or 'grouped_list' for custom groupBy keys (each row aggregates nodes in the group; condition stays no_data). Supports filtering via a filter expression, custom groupBy, ordering by cpu / cpu_allocatable / memory / memory_allocatable, and pagination via offset/limit. Also reports whether the requested time range falls before the data retention boundary. Numeric metric fields (nodeCPU, nodeCPUAllocatable, nodeMemory, nodeMemoryAllocatable) return -1 as a sentinel when no data is available for that field.
* Returns a paginated list of Kubernetes nodes with key metrics: CPU usage, CPU allocatable, memory working set, memory allocatable, per-group nodeCountsByReadiness ({ ready, notReady } from each node's latest k8s.node.condition_ready in the window) and per-group podCountsByPhase ({ pending, running, succeeded, failed, unknown } for pods scheduled on the listed nodes). Each node includes metadata attributes (k8s.node.uid, k8s.cluster.name). The response type is 'list' for the default k8s.node.name grouping (each row is one node with its current condition string: ready / not_ready / no_data) or 'grouped_list' for custom groupBy keys (each row aggregates nodes in the group; condition stays no_data). Supports filtering via a filter expression, custom groupBy, ordering by cpu / cpu_allocatable / memory / memory_allocatable, and pagination via offset/limit. Also reports missing required metrics and whether the requested time range falls before the data retention boundary. Numeric metric fields (nodeCPU, nodeCPUAllocatable, nodeMemory, nodeMemoryAllocatable) return -1 as a sentinel when no data is available for that field.
* @summary List Nodes for Infra Monitoring
*/
export const listNodes = (
@@ -620,7 +620,7 @@ export const useListNodes = <
return useMutation(getListNodesMutationOptions(options));
};
/**
* Returns a paginated list of Kubernetes pods with key metrics: CPU usage, CPU request/limit utilization, memory working set, memory request/limit utilization, current pod phase (pending/running/succeeded/failed/unknown/no_data), and pod age (ms since start time). Each pod includes metadata attributes (namespace, node, workload owner such as deployment/statefulset/daemonset/job/cronjob, cluster). Supports filtering via a filter expression, custom groupBy to aggregate pods by any attribute, ordering by any of the six metrics (cpu, cpu_request, cpu_limit, memory, memory_request, memory_limit), and pagination via offset/limit. The response type is 'list' for the default k8s.pod.uid grouping (each row is one pod with its current phase) or 'grouped_list' for custom groupBy keys (each row aggregates pods in the group with per-phase counts under podCountsByPhase: { pending, running, succeeded, failed, unknown } derived from each pod's latest phase in the window). Also reports whether the requested time range falls before the data retention boundary. Numeric metric fields (podCPU, podCPURequest, podCPULimit, podMemory, podMemoryRequest, podMemoryLimit, podAge) return -1 as a sentinel when no data is available for that field.
* Returns a paginated list of Kubernetes pods with key metrics: CPU usage, CPU request/limit utilization, memory working set, memory request/limit utilization, current pod phase (pending/running/succeeded/failed/unknown/no_data), and pod age (ms since start time). Each pod includes metadata attributes (namespace, node, workload owner such as deployment/statefulset/daemonset/job/cronjob, cluster). Supports filtering via a filter expression, custom groupBy to aggregate pods by any attribute, ordering by any of the six metrics (cpu, cpu_request, cpu_limit, memory, memory_request, memory_limit), and pagination via offset/limit. The response type is 'list' for the default k8s.pod.uid grouping (each row is one pod with its current phase) or 'grouped_list' for custom groupBy keys (each row aggregates pods in the group with per-phase counts under podCountsByPhase: { pending, running, succeeded, failed, unknown } derived from each pod's latest phase in the window). Also reports missing required metrics and whether the requested time range falls before the data retention boundary. Numeric metric fields (podCPU, podCPURequest, podCPULimit, podMemory, podMemoryRequest, podMemoryLimit, podAge) return -1 as a sentinel when no data is available for that field.
* @summary List Pods for Infra Monitoring
*/
export const listPods = (
@@ -703,7 +703,7 @@ export const useListPods = <
return useMutation(getListPodsMutationOptions(options));
};
/**
* Returns a paginated list of Kubernetes persistent volume claims (PVCs) with key volume metrics: available bytes, capacity bytes, usage (capacity - available), inodes, free inodes, and used inodes. Each row also includes metadata attributes (k8s.persistentvolumeclaim.name, k8s.pod.uid, k8s.pod.name, k8s.namespace.name, k8s.node.name, k8s.statefulset.name, k8s.cluster.name). Supports filtering via a filter expression, custom groupBy to aggregate volumes by any attribute, ordering by any of the six metrics (available, capacity, usage, inodes, inodes_free, inodes_used), and pagination via offset/limit. The response type is 'list' for the default k8s.persistentvolumeclaim.name grouping or 'grouped_list' for custom groupBy keys; in both modes every row aggregates volumes in the group. Also reports whether the requested time range falls before the data retention boundary. Numeric metric fields (volumeAvailable, volumeCapacity, volumeUsage, volumeInodes, volumeInodesFree, volumeInodesUsed) return -1 as a sentinel when no data is available for that field.
* Returns a paginated list of Kubernetes persistent volume claims (PVCs) with key volume metrics: available bytes, capacity bytes, usage (capacity - available), inodes, free inodes, and used inodes. Each row also includes metadata attributes (k8s.persistentvolumeclaim.name, k8s.pod.uid, k8s.pod.name, k8s.namespace.name, k8s.node.name, k8s.statefulset.name, k8s.cluster.name). Supports filtering via a filter expression, custom groupBy to aggregate volumes by any attribute, ordering by any of the six metrics (available, capacity, usage, inodes, inodes_free, inodes_used), and pagination via offset/limit. The response type is 'list' for the default k8s.persistentvolumeclaim.name grouping or 'grouped_list' for custom groupBy keys; in both modes every row aggregates volumes in the group. Also reports missing required metrics and whether the requested time range falls before the data retention boundary. Numeric metric fields (volumeAvailable, volumeCapacity, volumeUsage, volumeInodes, volumeInodesFree, volumeInodesUsed) return -1 as a sentinel when no data is available for that field.
* @summary List Volumes for Infra Monitoring
*/
export const listVolumes = (
@@ -786,7 +786,7 @@ export const useListVolumes = <
return useMutation(getListVolumesMutationOptions(options));
};
/**
* Returns a paginated list of Kubernetes StatefulSets with key aggregated pod metrics: CPU usage and memory working set summed across pods owned by the statefulset, plus average CPU/memory request and limit utilization (statefulSetCPURequest, statefulSetCPULimit, statefulSetMemoryRequest, statefulSetMemoryLimit). Each row also reports the latest known desiredPods (k8s.statefulset.desired_pods) and currentPods (k8s.statefulset.current_pods) replica counts and per-group podCountsByPhase ({ pending, running, succeeded, failed, unknown } from each pod's latest k8s.pod.phase value). Each statefulset includes metadata attributes (k8s.statefulset.name, k8s.namespace.name, k8s.cluster.name). The response type is 'list' for the default k8s.statefulset.name grouping or 'grouped_list' for custom groupBy keys; in both modes every row aggregates pods owned by statefulsets in the group. Supports filtering via a filter expression, custom groupBy, ordering by cpu / cpu_request / cpu_limit / memory / memory_request / memory_limit / desired_pods / current_pods, and pagination via offset/limit. Also reports whether the requested time range falls before the data retention boundary. Numeric metric fields (statefulSetCPU, statefulSetCPURequest, statefulSetCPULimit, statefulSetMemory, statefulSetMemoryRequest, statefulSetMemoryLimit, desiredPods, currentPods) return -1 as a sentinel when no data is available for that field.
* Returns a paginated list of Kubernetes StatefulSets with key aggregated pod metrics: CPU usage and memory working set summed across pods owned by the statefulset, plus average CPU/memory request and limit utilization (statefulSetCPURequest, statefulSetCPULimit, statefulSetMemoryRequest, statefulSetMemoryLimit). Each row also reports the latest known desiredPods (k8s.statefulset.desired_pods) and currentPods (k8s.statefulset.current_pods) replica counts and per-group podCountsByPhase ({ pending, running, succeeded, failed, unknown } from each pod's latest k8s.pod.phase value). Each statefulset includes metadata attributes (k8s.statefulset.name, k8s.namespace.name, k8s.cluster.name). The response type is 'list' for the default k8s.statefulset.name grouping or 'grouped_list' for custom groupBy keys; in both modes every row aggregates pods owned by statefulsets in the group. Supports filtering via a filter expression, custom groupBy, ordering by cpu / cpu_request / cpu_limit / memory / memory_request / memory_limit / desired_pods / current_pods, and pagination via offset/limit. Also reports missing required metrics and whether the requested time range falls before the data retention boundary. Numeric metric fields (statefulSetCPU, statefulSetCPURequest, statefulSetCPULimit, statefulSetMemory, statefulSetMemoryRequest, statefulSetMemoryLimit, desiredPods, currentPods) return -1 as a sentinel when no data is available for that field.
* @summary List StatefulSets for Infra Monitoring
*/
export const listStatefulSets = (

View File

@@ -5423,6 +5423,13 @@ export interface InframonitoringtypesClusterRecordDTO {
podCountsByPhase: InframonitoringtypesPodCountsByPhaseDTO;
}
export interface InframonitoringtypesRequiredMetricsCheckDTO {
/**
* @type array,null
*/
missingMetrics: string[] | null;
}
export enum InframonitoringtypesResponseTypeDTO {
list = 'list',
grouped_list = 'grouped_list',
@@ -5458,6 +5465,7 @@ export interface InframonitoringtypesClustersDTO {
* @type array
*/
records: InframonitoringtypesClusterRecordDTO[];
requiredMetricsCheck: InframonitoringtypesRequiredMetricsCheckDTO;
/**
* @type integer
*/
@@ -5535,6 +5543,7 @@ export interface InframonitoringtypesDaemonSetsDTO {
* @type array
*/
records: InframonitoringtypesDaemonSetRecordDTO[];
requiredMetricsCheck: InframonitoringtypesRequiredMetricsCheckDTO;
/**
* @type integer
*/
@@ -5612,6 +5621,7 @@ export interface InframonitoringtypesDeploymentsDTO {
* @type array
*/
records: InframonitoringtypesDeploymentRecordDTO[];
requiredMetricsCheck: InframonitoringtypesRequiredMetricsCheckDTO;
/**
* @type integer
*/
@@ -5697,6 +5707,7 @@ export interface InframonitoringtypesHostsDTO {
* @type array
*/
records: InframonitoringtypesHostRecordDTO[];
requiredMetricsCheck: InframonitoringtypesRequiredMetricsCheckDTO;
/**
* @type integer
*/
@@ -5782,6 +5793,7 @@ export interface InframonitoringtypesJobsDTO {
* @type array
*/
records: InframonitoringtypesJobRecordDTO[];
requiredMetricsCheck: InframonitoringtypesRequiredMetricsCheckDTO;
/**
* @type integer
*/
@@ -5831,6 +5843,7 @@ export interface InframonitoringtypesNamespacesDTO {
* @type array
*/
records: InframonitoringtypesNamespaceRecordDTO[];
requiredMetricsCheck: InframonitoringtypesRequiredMetricsCheckDTO;
/**
* @type integer
*/
@@ -5897,6 +5910,7 @@ export interface InframonitoringtypesNodesDTO {
* @type array
*/
records: InframonitoringtypesNodeRecordDTO[];
requiredMetricsCheck: InframonitoringtypesRequiredMetricsCheckDTO;
/**
* @type integer
*/
@@ -5980,6 +5994,7 @@ export interface InframonitoringtypesPodsDTO {
* @type array
*/
records: InframonitoringtypesPodRecordDTO[];
requiredMetricsCheck: InframonitoringtypesRequiredMetricsCheckDTO;
/**
* @type integer
*/
@@ -6327,6 +6342,7 @@ export interface InframonitoringtypesStatefulSetsDTO {
* @type array
*/
records: InframonitoringtypesStatefulSetRecordDTO[];
requiredMetricsCheck: InframonitoringtypesRequiredMetricsCheckDTO;
/**
* @type integer
*/
@@ -6395,6 +6411,7 @@ export interface InframonitoringtypesVolumesDTO {
* @type array
*/
records: InframonitoringtypesVolumeRecordDTO[];
requiredMetricsCheck: InframonitoringtypesRequiredMetricsCheckDTO;
/**
* @type integer
*/

View File

@@ -16,7 +16,7 @@ func (provider *provider) addInfraMonitoringRoutes(router *mux.Router) error {
ID: "ListHosts",
Tags: []string{"inframonitoring"},
Summary: "List Hosts for Infra Monitoring",
Description: "Returns a paginated list of hosts with key infrastructure metrics: CPU usage (%), memory usage (%), I/O wait (%), disk usage (%), and 15-minute load average. Each host includes its current status (active/inactive based on metrics reported in the last 10 minutes) and metadata attributes (e.g., os.type). Supports filtering via a filter expression, filtering by host status, custom groupBy to aggregate hosts by any attribute, ordering by any of the five metrics, and pagination via offset/limit. The response type is 'list' for the default host.name grouping or 'grouped_list' for custom groupBy keys. Also reports whether the requested time range falls before the data retention boundary. Numeric metric fields (cpu, memory, wait, load15, diskUsage) return -1 as a sentinel when no data is available for that field.",
Description: "Returns a paginated list of hosts with key infrastructure metrics: CPU usage (%), memory usage (%), I/O wait (%), disk usage (%), and 15-minute load average. Each host includes its current status (active/inactive based on metrics reported in the last 10 minutes) and metadata attributes (e.g., os.type). Supports filtering via a filter expression, filtering by host status, custom groupBy to aggregate hosts by any attribute, ordering by any of the five metrics, and pagination via offset/limit. The response type is 'list' for the default host.name grouping or 'grouped_list' for custom groupBy keys. Also reports missing required metrics and whether the requested time range falls before the data retention boundary. Numeric metric fields (cpu, memory, wait, load15, diskUsage) return -1 as a sentinel when no data is available for that field.",
Request: new(inframonitoringtypes.PostableHosts),
RequestContentType: "application/json",
Response: new(inframonitoringtypes.Hosts),
@@ -35,7 +35,7 @@ func (provider *provider) addInfraMonitoringRoutes(router *mux.Router) error {
ID: "ListPods",
Tags: []string{"inframonitoring"},
Summary: "List Pods for Infra Monitoring",
Description: "Returns a paginated list of Kubernetes pods with key metrics: CPU usage, CPU request/limit utilization, memory working set, memory request/limit utilization, current pod phase (pending/running/succeeded/failed/unknown/no_data), and pod age (ms since start time). Each pod includes metadata attributes (namespace, node, workload owner such as deployment/statefulset/daemonset/job/cronjob, cluster). Supports filtering via a filter expression, custom groupBy to aggregate pods by any attribute, ordering by any of the six metrics (cpu, cpu_request, cpu_limit, memory, memory_request, memory_limit), and pagination via offset/limit. The response type is 'list' for the default k8s.pod.uid grouping (each row is one pod with its current phase) or 'grouped_list' for custom groupBy keys (each row aggregates pods in the group with per-phase counts under podCountsByPhase: { pending, running, succeeded, failed, unknown } derived from each pod's latest phase in the window). Also reports whether the requested time range falls before the data retention boundary. Numeric metric fields (podCPU, podCPURequest, podCPULimit, podMemory, podMemoryRequest, podMemoryLimit, podAge) return -1 as a sentinel when no data is available for that field.",
Description: "Returns a paginated list of Kubernetes pods with key metrics: CPU usage, CPU request/limit utilization, memory working set, memory request/limit utilization, current pod phase (pending/running/succeeded/failed/unknown/no_data), and pod age (ms since start time). Each pod includes metadata attributes (namespace, node, workload owner such as deployment/statefulset/daemonset/job/cronjob, cluster). Supports filtering via a filter expression, custom groupBy to aggregate pods by any attribute, ordering by any of the six metrics (cpu, cpu_request, cpu_limit, memory, memory_request, memory_limit), and pagination via offset/limit. The response type is 'list' for the default k8s.pod.uid grouping (each row is one pod with its current phase) or 'grouped_list' for custom groupBy keys (each row aggregates pods in the group with per-phase counts under podCountsByPhase: { pending, running, succeeded, failed, unknown } derived from each pod's latest phase in the window). Also reports missing required metrics and whether the requested time range falls before the data retention boundary. Numeric metric fields (podCPU, podCPURequest, podCPULimit, podMemory, podMemoryRequest, podMemoryLimit, podAge) return -1 as a sentinel when no data is available for that field.",
Request: new(inframonitoringtypes.PostablePods),
RequestContentType: "application/json",
Response: new(inframonitoringtypes.Pods),
@@ -54,7 +54,7 @@ func (provider *provider) addInfraMonitoringRoutes(router *mux.Router) error {
ID: "ListNodes",
Tags: []string{"inframonitoring"},
Summary: "List Nodes for Infra Monitoring",
Description: "Returns a paginated list of Kubernetes nodes with key metrics: CPU usage, CPU allocatable, memory working set, memory allocatable, per-group nodeCountsByReadiness ({ ready, notReady } from each node's latest k8s.node.condition_ready in the window) and per-group podCountsByPhase ({ pending, running, succeeded, failed, unknown } for pods scheduled on the listed nodes). Each node includes metadata attributes (k8s.node.uid, k8s.cluster.name). The response type is 'list' for the default k8s.node.name grouping (each row is one node with its current condition string: ready / not_ready / no_data) or 'grouped_list' for custom groupBy keys (each row aggregates nodes in the group; condition stays no_data). Supports filtering via a filter expression, custom groupBy, ordering by cpu / cpu_allocatable / memory / memory_allocatable, and pagination via offset/limit. Also reports whether the requested time range falls before the data retention boundary. Numeric metric fields (nodeCPU, nodeCPUAllocatable, nodeMemory, nodeMemoryAllocatable) return -1 as a sentinel when no data is available for that field.",
Description: "Returns a paginated list of Kubernetes nodes with key metrics: CPU usage, CPU allocatable, memory working set, memory allocatable, per-group nodeCountsByReadiness ({ ready, notReady } from each node's latest k8s.node.condition_ready in the window) and per-group podCountsByPhase ({ pending, running, succeeded, failed, unknown } for pods scheduled on the listed nodes). Each node includes metadata attributes (k8s.node.uid, k8s.cluster.name). The response type is 'list' for the default k8s.node.name grouping (each row is one node with its current condition string: ready / not_ready / no_data) or 'grouped_list' for custom groupBy keys (each row aggregates nodes in the group; condition stays no_data). Supports filtering via a filter expression, custom groupBy, ordering by cpu / cpu_allocatable / memory / memory_allocatable, and pagination via offset/limit. Also reports missing required metrics and whether the requested time range falls before the data retention boundary. Numeric metric fields (nodeCPU, nodeCPUAllocatable, nodeMemory, nodeMemoryAllocatable) return -1 as a sentinel when no data is available for that field.",
Request: new(inframonitoringtypes.PostableNodes),
RequestContentType: "application/json",
Response: new(inframonitoringtypes.Nodes),
@@ -73,7 +73,7 @@ func (provider *provider) addInfraMonitoringRoutes(router *mux.Router) error {
ID: "ListNamespaces",
Tags: []string{"inframonitoring"},
Summary: "List Namespaces for Infra Monitoring",
Description: "Returns a paginated list of Kubernetes namespaces with key aggregated pod metrics: CPU usage and memory working set (summed across pods in the group), plus per-group podCountsByPhase ({ pending, running, succeeded, failed, unknown } from each pod's latest k8s.pod.phase value in the window). Each namespace includes metadata attributes (k8s.namespace.name, k8s.cluster.name). The response type is 'list' for the default k8s.namespace.name grouping or 'grouped_list' for custom groupBy keys; in both modes every row aggregates pods in the group. Supports filtering via a filter expression, custom groupBy, ordering by cpu / memory, and pagination via offset/limit. Also reports whether the requested time range falls before the data retention boundary. Numeric metric fields (namespaceCPU, namespaceMemory) return -1 as a sentinel when no data is available for that field.",
Description: "Returns a paginated list of Kubernetes namespaces with key aggregated pod metrics: CPU usage and memory working set (summed across pods in the group), plus per-group podCountsByPhase ({ pending, running, succeeded, failed, unknown } from each pod's latest k8s.pod.phase value in the window). Each namespace includes metadata attributes (k8s.namespace.name, k8s.cluster.name). The response type is 'list' for the default k8s.namespace.name grouping or 'grouped_list' for custom groupBy keys; in both modes every row aggregates pods in the group. Supports filtering via a filter expression, custom groupBy, ordering by cpu / memory, and pagination via offset/limit. Also reports missing required metrics and whether the requested time range falls before the data retention boundary. Numeric metric fields (namespaceCPU, namespaceMemory) return -1 as a sentinel when no data is available for that field.",
Request: new(inframonitoringtypes.PostableNamespaces),
RequestContentType: "application/json",
Response: new(inframonitoringtypes.Namespaces),
@@ -92,7 +92,7 @@ func (provider *provider) addInfraMonitoringRoutes(router *mux.Router) error {
ID: "ListClusters",
Tags: []string{"inframonitoring"},
Summary: "List Clusters for Infra Monitoring",
Description: "Returns a paginated list of Kubernetes clusters with key aggregated metrics derived by summing per-node values within the group: CPU usage, CPU allocatable, memory working set, memory allocatable. Each row also reports per-group nodeCountsByReadiness ({ ready, notReady } from each node's latest k8s.node.condition_ready value) and per-group podCountsByPhase ({ pending, running, succeeded, failed, unknown } from each pod's latest k8s.pod.phase value). Each cluster includes metadata attributes (k8s.cluster.name). The response type is 'list' for the default k8s.cluster.name grouping or 'grouped_list' for custom groupBy keys; in both modes every row aggregates nodes and pods in the group. Supports filtering via a filter expression, custom groupBy, ordering by cpu / cpu_allocatable / memory / memory_allocatable, and pagination via offset/limit. Also reports whether the requested time range falls before the data retention boundary. Numeric metric fields (clusterCPU, clusterCPUAllocatable, clusterMemory, clusterMemoryAllocatable) return -1 as a sentinel when no data is available for that field.",
Description: "Returns a paginated list of Kubernetes clusters with key aggregated metrics derived by summing per-node values within the group: CPU usage, CPU allocatable, memory working set, memory allocatable. Each row also reports per-group nodeCountsByReadiness ({ ready, notReady } from each node's latest k8s.node.condition_ready value) and per-group podCountsByPhase ({ pending, running, succeeded, failed, unknown } from each pod's latest k8s.pod.phase value). Each cluster includes metadata attributes (k8s.cluster.name). The response type is 'list' for the default k8s.cluster.name grouping or 'grouped_list' for custom groupBy keys; in both modes every row aggregates nodes and pods in the group. Supports filtering via a filter expression, custom groupBy, ordering by cpu / cpu_allocatable / memory / memory_allocatable, and pagination via offset/limit. Also reports missing required metrics and whether the requested time range falls before the data retention boundary. Numeric metric fields (clusterCPU, clusterCPUAllocatable, clusterMemory, clusterMemoryAllocatable) return -1 as a sentinel when no data is available for that field.",
Request: new(inframonitoringtypes.PostableClusters),
RequestContentType: "application/json",
Response: new(inframonitoringtypes.Clusters),
@@ -111,7 +111,7 @@ func (provider *provider) addInfraMonitoringRoutes(router *mux.Router) error {
ID: "ListVolumes",
Tags: []string{"inframonitoring"},
Summary: "List Volumes for Infra Monitoring",
Description: "Returns a paginated list of Kubernetes persistent volume claims (PVCs) with key volume metrics: available bytes, capacity bytes, usage (capacity - available), inodes, free inodes, and used inodes. Each row also includes metadata attributes (k8s.persistentvolumeclaim.name, k8s.pod.uid, k8s.pod.name, k8s.namespace.name, k8s.node.name, k8s.statefulset.name, k8s.cluster.name). Supports filtering via a filter expression, custom groupBy to aggregate volumes by any attribute, ordering by any of the six metrics (available, capacity, usage, inodes, inodes_free, inodes_used), and pagination via offset/limit. The response type is 'list' for the default k8s.persistentvolumeclaim.name grouping or 'grouped_list' for custom groupBy keys; in both modes every row aggregates volumes in the group. Also reports whether the requested time range falls before the data retention boundary. Numeric metric fields (volumeAvailable, volumeCapacity, volumeUsage, volumeInodes, volumeInodesFree, volumeInodesUsed) return -1 as a sentinel when no data is available for that field.",
Description: "Returns a paginated list of Kubernetes persistent volume claims (PVCs) with key volume metrics: available bytes, capacity bytes, usage (capacity - available), inodes, free inodes, and used inodes. Each row also includes metadata attributes (k8s.persistentvolumeclaim.name, k8s.pod.uid, k8s.pod.name, k8s.namespace.name, k8s.node.name, k8s.statefulset.name, k8s.cluster.name). Supports filtering via a filter expression, custom groupBy to aggregate volumes by any attribute, ordering by any of the six metrics (available, capacity, usage, inodes, inodes_free, inodes_used), and pagination via offset/limit. The response type is 'list' for the default k8s.persistentvolumeclaim.name grouping or 'grouped_list' for custom groupBy keys; in both modes every row aggregates volumes in the group. Also reports missing required metrics and whether the requested time range falls before the data retention boundary. Numeric metric fields (volumeAvailable, volumeCapacity, volumeUsage, volumeInodes, volumeInodesFree, volumeInodesUsed) return -1 as a sentinel when no data is available for that field.",
Request: new(inframonitoringtypes.PostableVolumes),
RequestContentType: "application/json",
Response: new(inframonitoringtypes.Volumes),
@@ -130,7 +130,7 @@ func (provider *provider) addInfraMonitoringRoutes(router *mux.Router) error {
ID: "ListDeployments",
Tags: []string{"inframonitoring"},
Summary: "List Deployments for Infra Monitoring",
Description: "Returns a paginated list of Kubernetes Deployments with key aggregated pod metrics: CPU usage and memory working set summed across pods owned by the deployment, plus average CPU/memory request and limit utilization (deploymentCPURequest, deploymentCPULimit, deploymentMemoryRequest, deploymentMemoryLimit). Each row also reports the latest known desiredPods (k8s.deployment.desired) and availablePods (k8s.deployment.available) replica counts and per-group podCountsByPhase ({ pending, running, succeeded, failed, unknown } from each pod's latest k8s.pod.phase value). Each deployment includes metadata attributes (k8s.deployment.name, k8s.namespace.name, k8s.cluster.name). The response type is 'list' for the default k8s.deployment.name grouping or 'grouped_list' for custom groupBy keys; in both modes every row aggregates pods owned by deployments in the group. Supports filtering via a filter expression, custom groupBy, ordering by cpu / cpu_request / cpu_limit / memory / memory_request / memory_limit / desired_pods / available_pods, and pagination via offset/limit. Also reports whether the requested time range falls before the data retention boundary. Numeric metric fields (deploymentCPU, deploymentCPURequest, deploymentCPULimit, deploymentMemory, deploymentMemoryRequest, deploymentMemoryLimit, desiredPods, availablePods) return -1 as a sentinel when no data is available for that field.",
Description: "Returns a paginated list of Kubernetes Deployments with key aggregated pod metrics: CPU usage and memory working set summed across pods owned by the deployment, plus average CPU/memory request and limit utilization (deploymentCPURequest, deploymentCPULimit, deploymentMemoryRequest, deploymentMemoryLimit). Each row also reports the latest known desiredPods (k8s.deployment.desired) and availablePods (k8s.deployment.available) replica counts and per-group podCountsByPhase ({ pending, running, succeeded, failed, unknown } from each pod's latest k8s.pod.phase value). Each deployment includes metadata attributes (k8s.deployment.name, k8s.namespace.name, k8s.cluster.name). The response type is 'list' for the default k8s.deployment.name grouping or 'grouped_list' for custom groupBy keys; in both modes every row aggregates pods owned by deployments in the group. Supports filtering via a filter expression, custom groupBy, ordering by cpu / cpu_request / cpu_limit / memory / memory_request / memory_limit / desired_pods / available_pods, and pagination via offset/limit. Also reports missing required metrics and whether the requested time range falls before the data retention boundary. Numeric metric fields (deploymentCPU, deploymentCPURequest, deploymentCPULimit, deploymentMemory, deploymentMemoryRequest, deploymentMemoryLimit, desiredPods, availablePods) return -1 as a sentinel when no data is available for that field.",
Request: new(inframonitoringtypes.PostableDeployments),
RequestContentType: "application/json",
Response: new(inframonitoringtypes.Deployments),
@@ -149,7 +149,7 @@ func (provider *provider) addInfraMonitoringRoutes(router *mux.Router) error {
ID: "ListStatefulSets",
Tags: []string{"inframonitoring"},
Summary: "List StatefulSets for Infra Monitoring",
Description: "Returns a paginated list of Kubernetes StatefulSets with key aggregated pod metrics: CPU usage and memory working set summed across pods owned by the statefulset, plus average CPU/memory request and limit utilization (statefulSetCPURequest, statefulSetCPULimit, statefulSetMemoryRequest, statefulSetMemoryLimit). Each row also reports the latest known desiredPods (k8s.statefulset.desired_pods) and currentPods (k8s.statefulset.current_pods) replica counts and per-group podCountsByPhase ({ pending, running, succeeded, failed, unknown } from each pod's latest k8s.pod.phase value). Each statefulset includes metadata attributes (k8s.statefulset.name, k8s.namespace.name, k8s.cluster.name). The response type is 'list' for the default k8s.statefulset.name grouping or 'grouped_list' for custom groupBy keys; in both modes every row aggregates pods owned by statefulsets in the group. Supports filtering via a filter expression, custom groupBy, ordering by cpu / cpu_request / cpu_limit / memory / memory_request / memory_limit / desired_pods / current_pods, and pagination via offset/limit. Also reports whether the requested time range falls before the data retention boundary. Numeric metric fields (statefulSetCPU, statefulSetCPURequest, statefulSetCPULimit, statefulSetMemory, statefulSetMemoryRequest, statefulSetMemoryLimit, desiredPods, currentPods) return -1 as a sentinel when no data is available for that field.",
Description: "Returns a paginated list of Kubernetes StatefulSets with key aggregated pod metrics: CPU usage and memory working set summed across pods owned by the statefulset, plus average CPU/memory request and limit utilization (statefulSetCPURequest, statefulSetCPULimit, statefulSetMemoryRequest, statefulSetMemoryLimit). Each row also reports the latest known desiredPods (k8s.statefulset.desired_pods) and currentPods (k8s.statefulset.current_pods) replica counts and per-group podCountsByPhase ({ pending, running, succeeded, failed, unknown } from each pod's latest k8s.pod.phase value). Each statefulset includes metadata attributes (k8s.statefulset.name, k8s.namespace.name, k8s.cluster.name). The response type is 'list' for the default k8s.statefulset.name grouping or 'grouped_list' for custom groupBy keys; in both modes every row aggregates pods owned by statefulsets in the group. Supports filtering via a filter expression, custom groupBy, ordering by cpu / cpu_request / cpu_limit / memory / memory_request / memory_limit / desired_pods / current_pods, and pagination via offset/limit. Also reports missing required metrics and whether the requested time range falls before the data retention boundary. Numeric metric fields (statefulSetCPU, statefulSetCPURequest, statefulSetCPULimit, statefulSetMemory, statefulSetMemoryRequest, statefulSetMemoryLimit, desiredPods, currentPods) return -1 as a sentinel when no data is available for that field.",
Request: new(inframonitoringtypes.PostableStatefulSets),
RequestContentType: "application/json",
Response: new(inframonitoringtypes.StatefulSets),
@@ -168,7 +168,7 @@ func (provider *provider) addInfraMonitoringRoutes(router *mux.Router) error {
ID: "ListJobs",
Tags: []string{"inframonitoring"},
Summary: "List Jobs for Infra Monitoring",
Description: "Returns a paginated list of Kubernetes Jobs with key aggregated pod metrics: CPU usage and memory working set summed across pods owned by the job, plus average CPU/memory request and limit utilization (jobCPURequest, jobCPULimit, jobMemoryRequest, jobMemoryLimit). Each row also reports the latest known job-level counters from kube-state-metrics: desiredSuccessfulPods (k8s.job.desired_successful_pods, the target completion count), activePods (k8s.job.active_pods), failedPods (k8s.job.failed_pods, cumulative across the lifetime of the job), and successfulPods (k8s.job.successful_pods, cumulative). It also reports per-group podCountsByPhase ({ pending, running, succeeded, failed, unknown } from each pod's latest k8s.pod.phase value); note podCountsByPhase.failed (current pod-phase) is distinct from failedPods (cumulative job kube-state-metric). Each job includes metadata attributes (k8s.job.name, k8s.namespace.name, k8s.cluster.name). The response type is 'list' for the default k8s.job.name grouping or 'grouped_list' for custom groupBy keys; in both modes every row aggregates pods owned by jobs in the group. Supports filtering via a filter expression, custom groupBy, ordering by cpu / cpu_request / cpu_limit / memory / memory_request / memory_limit / desired_successful_pods / active_pods / failed_pods / successful_pods, and pagination via offset/limit. Also reports whether the requested time range falls before the data retention boundary. Numeric metric fields (jobCPU, jobCPURequest, jobCPULimit, jobMemory, jobMemoryRequest, jobMemoryLimit, desiredSuccessfulPods, activePods, failedPods, successfulPods) return -1 as a sentinel when no data is available for that field.",
Description: "Returns a paginated list of Kubernetes Jobs with key aggregated pod metrics: CPU usage and memory working set summed across pods owned by the job, plus average CPU/memory request and limit utilization (jobCPURequest, jobCPULimit, jobMemoryRequest, jobMemoryLimit). Each row also reports the latest known job-level counters from kube-state-metrics: desiredSuccessfulPods (k8s.job.desired_successful_pods, the target completion count), activePods (k8s.job.active_pods), failedPods (k8s.job.failed_pods, cumulative across the lifetime of the job), and successfulPods (k8s.job.successful_pods, cumulative). It also reports per-group podCountsByPhase ({ pending, running, succeeded, failed, unknown } from each pod's latest k8s.pod.phase value); note podCountsByPhase.failed (current pod-phase) is distinct from failedPods (cumulative job kube-state-metric). Each job includes metadata attributes (k8s.job.name, k8s.namespace.name, k8s.cluster.name). The response type is 'list' for the default k8s.job.name grouping or 'grouped_list' for custom groupBy keys; in both modes every row aggregates pods owned by jobs in the group. Supports filtering via a filter expression, custom groupBy, ordering by cpu / cpu_request / cpu_limit / memory / memory_request / memory_limit / desired_successful_pods / active_pods / failed_pods / successful_pods, and pagination via offset/limit. Also reports missing required metrics and whether the requested time range falls before the data retention boundary. Numeric metric fields (jobCPU, jobCPURequest, jobCPULimit, jobMemory, jobMemoryRequest, jobMemoryLimit, desiredSuccessfulPods, activePods, failedPods, successfulPods) return -1 as a sentinel when no data is available for that field.",
Request: new(inframonitoringtypes.PostableJobs),
RequestContentType: "application/json",
Response: new(inframonitoringtypes.Jobs),
@@ -187,7 +187,7 @@ func (provider *provider) addInfraMonitoringRoutes(router *mux.Router) error {
ID: "ListDaemonSets",
Tags: []string{"inframonitoring"},
Summary: "List DaemonSets for Infra Monitoring",
Description: "Returns a paginated list of Kubernetes DaemonSets with key aggregated pod metrics: CPU usage and memory working set summed across pods owned by the daemonset, plus average CPU/memory request and limit utilization (daemonSetCPURequest, daemonSetCPULimit, daemonSetMemoryRequest, daemonSetMemoryLimit). Each row also reports the latest known node-level counters from kube-state-metrics: desiredNodes (k8s.daemonset.desired_scheduled_nodes, the number of nodes the daemonset wants to run on) and currentNodes (k8s.daemonset.current_scheduled_nodes, the number of nodes the daemonset currently runs on) — note these are node counts, not pod counts. It also reports per-group podCountsByPhase ({ pending, running, succeeded, failed, unknown } from each pod's latest k8s.pod.phase value). Each daemonset includes metadata attributes (k8s.daemonset.name, k8s.namespace.name, k8s.cluster.name). The response type is 'list' for the default k8s.daemonset.name grouping or 'grouped_list' for custom groupBy keys; in both modes every row aggregates pods owned by daemonsets in the group. Supports filtering via a filter expression, custom groupBy, ordering by cpu / cpu_request / cpu_limit / memory / memory_request / memory_limit / desired_nodes / current_nodes, and pagination via offset/limit. Also reports whether the requested time range falls before the data retention boundary. Numeric metric fields (daemonSetCPU, daemonSetCPURequest, daemonSetCPULimit, daemonSetMemory, daemonSetMemoryRequest, daemonSetMemoryLimit, desiredNodes, currentNodes) return -1 as a sentinel when no data is available for that field.",
Description: "Returns a paginated list of Kubernetes DaemonSets with key aggregated pod metrics: CPU usage and memory working set summed across pods owned by the daemonset, plus average CPU/memory request and limit utilization (daemonSetCPURequest, daemonSetCPULimit, daemonSetMemoryRequest, daemonSetMemoryLimit). Each row also reports the latest known node-level counters from kube-state-metrics: desiredNodes (k8s.daemonset.desired_scheduled_nodes, the number of nodes the daemonset wants to run on) and currentNodes (k8s.daemonset.current_scheduled_nodes, the number of nodes the daemonset currently runs on) — note these are node counts, not pod counts. It also reports per-group podCountsByPhase ({ pending, running, succeeded, failed, unknown } from each pod's latest k8s.pod.phase value). Each daemonset includes metadata attributes (k8s.daemonset.name, k8s.namespace.name, k8s.cluster.name). The response type is 'list' for the default k8s.daemonset.name grouping or 'grouped_list' for custom groupBy keys; in both modes every row aggregates pods owned by daemonsets in the group. Supports filtering via a filter expression, custom groupBy, ordering by cpu / cpu_request / cpu_limit / memory / memory_request / memory_limit / desired_nodes / current_nodes, and pagination via offset/limit. Also reports missing required metrics and whether the requested time range falls before the data retention boundary. Numeric metric fields (daemonSetCPU, daemonSetCPURequest, daemonSetCPULimit, daemonSetMemory, daemonSetMemoryRequest, daemonSetMemoryLimit, desiredNodes, currentNodes) return -1 as a sentinel when no data is available for that field.",
Request: new(inframonitoringtypes.PostableDaemonSets),
RequestContentType: "application/json",
Response: new(inframonitoringtypes.DaemonSets),

View File

@@ -3,15 +3,16 @@ package flagger
import "github.com/SigNoz/signoz/pkg/types/featuretypes"
var (
FeatureUseSpanMetrics = featuretypes.MustNewName("use_span_metrics")
FeatureKafkaSpanEval = featuretypes.MustNewName("kafka_span_eval")
FeatureHideRootUser = featuretypes.MustNewName("hide_root_user")
FeatureGetMetersFromZeus = featuretypes.MustNewName("get_meters_from_zeus")
FeaturePutMetersInZeus = featuretypes.MustNewName("put_meters_in_zeus")
FeatureUseMeterReporter = featuretypes.MustNewName("use_meter_reporter")
FeatureUseJSONBody = featuretypes.MustNewName("use_json_body")
FeatureUseFineGrainedAuthz = featuretypes.MustNewName("use_fine_grained_authz")
FeatureUseDashboardV2 = featuretypes.MustNewName("use_dashboard_v2")
FeatureUseSpanMetrics = featuretypes.MustNewName("use_span_metrics")
FeatureKafkaSpanEval = featuretypes.MustNewName("kafka_span_eval")
FeatureHideRootUser = featuretypes.MustNewName("hide_root_user")
FeatureGetMetersFromZeus = featuretypes.MustNewName("get_meters_from_zeus")
FeaturePutMetersInZeus = featuretypes.MustNewName("put_meters_in_zeus")
FeatureUseMeterReporter = featuretypes.MustNewName("use_meter_reporter")
FeatureUseJSONBody = featuretypes.MustNewName("use_json_body")
FeatureUseFineGrainedAuthz = featuretypes.MustNewName("use_fine_grained_authz")
FeatureUseDashboardV2 = featuretypes.MustNewName("use_dashboard_v2")
FeatureEnableMetricsReduction = featuretypes.MustNewName("enable_metrics_reduction")
)
func MustNewRegistry() featuretypes.Registry {
@@ -88,6 +89,14 @@ func MustNewRegistry() featuretypes.Registry {
DefaultVariant: featuretypes.MustNewName("disabled"),
Variants: featuretypes.NewBooleanVariants(),
},
&featuretypes.Feature{
Name: FeatureEnableMetricsReduction,
Kind: featuretypes.KindBoolean,
Stage: featuretypes.StageExperimental,
Description: "Controls whether metrics cardinality reduction (buffer/reduced tables) is read by the querier",
DefaultVariant: featuretypes.MustNewName("disabled"),
Variants: featuretypes.NewBooleanVariants(),
},
)
if err != nil {
panic(err)

View File

@@ -341,12 +341,12 @@ func alignedMetricWindow(startMs, endMs int64) (
}
tsAdjustedStartMs, _, distributedTSTable, localTSTable := telemetrymetrics.WhichTSTableToUse(
samplesAdjustedStartMs, flooredEndMs, nil,
samplesAdjustedStartMs, flooredEndMs, false, nil,
)
distributedSamplesTable, localSamplesTable := telemetrymetrics.WhichSamplesTableToUse(
samplesAdjustedStartMs, flooredEndMs,
metrictypes.UnspecifiedType, metrictypes.TimeAggregationUnspecified, nil,
metrictypes.UnspecifiedType, metrictypes.TimeAggregationUnspecified, false, nil,
)
return samplesAdjustedStartMs, flooredEndMs, tsAdjustedStartMs, distributedTSTable, localTSTable, distributedSamplesTable, localSamplesTable
@@ -413,27 +413,64 @@ func (m *module) buildFilterClause(ctx context.Context, filter *qbtypes.Filter,
// NOTE: this method is not specific to infra monitoring — it queries attributes_metadata generically.
// Consider moving to telemetryMetaStore when a second use case emerges.
//
// getEarliestMetricTime returns the earliest first_reported_unix_milli across the
// given metric names. It is used solely for the end-time-before-retention check.
// When none of the metrics have ever been reported, it returns 0.
func (m *module) getEarliestMetricTime(ctx context.Context, metricNames []string) (uint64, error) {
// getMetricsExistenceAndEarliestTime checks which of the given metric names have been
// reported. It returns a list of missing metrics (those not found or with zero count)
// and the earliest first-reported timestamp across all present metrics.
// When all metrics are missing, minFirstReportedUnixMilli is 0.
// TODO(nikhilmantri0902, srikanthccv): This method was designed this way because querier errors if any of the metrics
// in the querier list was never sent, the QueryRange call throws not found error. Modify this method, if QueryRange
// behaviour changes towards this.
func (m *module) getMetricsExistenceAndEarliestTime(ctx context.Context, metricNames []string) ([]string, uint64, error) {
if len(metricNames) == 0 {
return 0, nil
return nil, 0, nil
}
sb := sqlbuilder.NewSelectBuilder()
sb.Select("min(first_reported_unix_milli) AS min_first_reported")
sb.Select("metric_name", "count(*) AS cnt", "min(first_reported_unix_milli) AS min_first_reported")
sb.From(fmt.Sprintf("%s.%s", telemetrymetrics.DBName, telemetrymetrics.AttributesMetadataTableName))
sb.Where(sb.In("metric_name", sqlbuilder.List(metricNames)))
sb.GroupBy("metric_name")
query, args := sb.BuildWithFlavor(sqlbuilder.ClickHouse)
var minFirstReported uint64
if err := m.telemetryStore.ClickhouseDB().QueryRow(ctx, query, args...).Scan(&minFirstReported); err != nil {
return 0, err
rows, err := m.telemetryStore.ClickhouseDB().Query(ctx, query, args...)
if err != nil {
return nil, 0, err
}
defer rows.Close()
type metricInfo struct {
count uint64
minFirstReported uint64
}
found := make(map[string]metricInfo, len(metricNames))
for rows.Next() {
var name string
var cnt, minFR uint64
if err := rows.Scan(&name, &cnt, &minFR); err != nil {
return nil, 0, err
}
found[name] = metricInfo{count: cnt, minFirstReported: minFR}
}
if err := rows.Err(); err != nil {
return nil, 0, err
}
return minFirstReported, nil
var missingMetrics []string
var globalMinFirstReported uint64
for _, name := range metricNames {
info, ok := found[name]
if !ok || info.count == 0 {
missingMetrics = append(missingMetrics, name)
continue
}
if globalMinFirstReported == 0 || info.minFirstReported < globalMinFirstReported {
globalMinFirstReported = info.minFirstReported
}
}
return missingMetrics, globalMinFirstReported, nil
}
// getMetadata fetches the latest values of additionalCols for each unique combination of groupBy keys,

View File

@@ -78,18 +78,26 @@ func (m *module) ListHosts(ctx context.Context, orgID valuer.UUID, req *inframon
resp.Type = inframonitoringtypes.ResponseTypeGroupedList
}
// If req.End is before the earliest reported time for these metrics, return early
// with endTimeBeforeRetention=true.
minFirstReportedUnixMilli, err := m.getEarliestMetricTime(ctx, hostsTableMetricNamesList)
// 1. Check which required metrics exist and get earliest retention time.
// If any required metric is missing, return early with the list of missing metrics.
// 2. If metrics exist but req.End is before the earliest reported time, return early with endTimeBeforeRetention=true.
missingMetrics, minFirstReportedUnixMilli, err := m.getMetricsExistenceAndEarliestTime(ctx, hostsTableMetricNamesList)
if err != nil {
return nil, err
}
if len(missingMetrics) > 0 {
resp.RequiredMetricsCheck = inframonitoringtypes.RequiredMetricsCheck{MissingMetrics: missingMetrics}
resp.Records = []inframonitoringtypes.HostRecord{}
resp.Total = 0
return resp, nil
}
if req.End < int64(minFirstReportedUnixMilli) {
resp.EndTimeBeforeRetention = true
resp.Records = []inframonitoringtypes.HostRecord{}
resp.Total = 0
return resp, nil
}
resp.RequiredMetricsCheck = inframonitoringtypes.RequiredMetricsCheck{MissingMetrics: []string{}}
// TOD(nikhilmantri0902): replace this separate ClickHouse query with a sub-query inside the main query builder query
// once QB supports sub-queries.
@@ -183,16 +191,23 @@ func (m *module) ListPods(ctx context.Context, orgID valuer.UUID, req *inframoni
resp.Type = inframonitoringtypes.ResponseTypeGroupedList
}
minFirstReportedUnixMilli, err := m.getEarliestMetricTime(ctx, podsTableMetricNamesList)
missingMetrics, minFirstReportedUnixMilli, err := m.getMetricsExistenceAndEarliestTime(ctx, podsTableMetricNamesList)
if err != nil {
return nil, err
}
if len(missingMetrics) > 0 {
resp.RequiredMetricsCheck = inframonitoringtypes.RequiredMetricsCheck{MissingMetrics: missingMetrics}
resp.Records = []inframonitoringtypes.PodRecord{}
resp.Total = 0
return resp, nil
}
if req.End < int64(minFirstReportedUnixMilli) {
resp.EndTimeBeforeRetention = true
resp.Records = []inframonitoringtypes.PodRecord{}
resp.Total = 0
return resp, nil
}
resp.RequiredMetricsCheck = inframonitoringtypes.RequiredMetricsCheck{MissingMetrics: []string{}}
metadataMap, err := m.getPodsTableMetadata(ctx, req)
if err != nil {
@@ -261,16 +276,23 @@ func (m *module) ListNodes(ctx context.Context, orgID valuer.UUID, req *inframon
resp.Type = inframonitoringtypes.ResponseTypeGroupedList
}
minFirstReportedUnixMilli, err := m.getEarliestMetricTime(ctx, nodesTableMetricNamesList)
missingMetrics, minFirstReportedUnixMilli, err := m.getMetricsExistenceAndEarliestTime(ctx, nodesTableMetricNamesList)
if err != nil {
return nil, err
}
if len(missingMetrics) > 0 {
resp.RequiredMetricsCheck = inframonitoringtypes.RequiredMetricsCheck{MissingMetrics: missingMetrics}
resp.Records = []inframonitoringtypes.NodeRecord{}
resp.Total = 0
return resp, nil
}
if req.End < int64(minFirstReportedUnixMilli) {
resp.EndTimeBeforeRetention = true
resp.Records = []inframonitoringtypes.NodeRecord{}
resp.Total = 0
return resp, nil
}
resp.RequiredMetricsCheck = inframonitoringtypes.RequiredMetricsCheck{MissingMetrics: []string{}}
metadataMap, err := m.getNodesTableMetadata(ctx, req)
if err != nil {
@@ -344,16 +366,23 @@ func (m *module) ListNamespaces(ctx context.Context, orgID valuer.UUID, req *inf
resp.Type = inframonitoringtypes.ResponseTypeGroupedList
}
minFirstReportedUnixMilli, err := m.getEarliestMetricTime(ctx, namespacesTableMetricNamesList)
missingMetrics, minFirstReportedUnixMilli, err := m.getMetricsExistenceAndEarliestTime(ctx, namespacesTableMetricNamesList)
if err != nil {
return nil, err
}
if len(missingMetrics) > 0 {
resp.RequiredMetricsCheck = inframonitoringtypes.RequiredMetricsCheck{MissingMetrics: missingMetrics}
resp.Records = []inframonitoringtypes.NamespaceRecord{}
resp.Total = 0
return resp, nil
}
if req.End < int64(minFirstReportedUnixMilli) {
resp.EndTimeBeforeRetention = true
resp.Records = []inframonitoringtypes.NamespaceRecord{}
resp.Total = 0
return resp, nil
}
resp.RequiredMetricsCheck = inframonitoringtypes.RequiredMetricsCheck{MissingMetrics: []string{}}
metadataMap, err := m.getNamespacesTableMetadata(ctx, req)
if err != nil {
@@ -421,16 +450,23 @@ func (m *module) ListClusters(ctx context.Context, orgID valuer.UUID, req *infra
resp.Type = inframonitoringtypes.ResponseTypeGroupedList
}
minFirstReportedUnixMilli, err := m.getEarliestMetricTime(ctx, clustersTableMetricNamesList)
missingMetrics, minFirstReportedUnixMilli, err := m.getMetricsExistenceAndEarliestTime(ctx, clustersTableMetricNamesList)
if err != nil {
return nil, err
}
if len(missingMetrics) > 0 {
resp.RequiredMetricsCheck = inframonitoringtypes.RequiredMetricsCheck{MissingMetrics: missingMetrics}
resp.Records = []inframonitoringtypes.ClusterRecord{}
resp.Total = 0
return resp, nil
}
if req.End < int64(minFirstReportedUnixMilli) {
resp.EndTimeBeforeRetention = true
resp.Records = []inframonitoringtypes.ClusterRecord{}
resp.Total = 0
return resp, nil
}
resp.RequiredMetricsCheck = inframonitoringtypes.RequiredMetricsCheck{MissingMetrics: []string{}}
metadataMap, err := m.getClustersTableMetadata(ctx, req)
if err != nil {
@@ -511,16 +547,23 @@ func (m *module) ListVolumes(ctx context.Context, orgID valuer.UUID, req *infram
}
req.Filter.Expression = mergeFilterExpressions(volumesBaseFilterExpr, req.Filter.Expression)
minFirstReportedUnixMilli, err := m.getEarliestMetricTime(ctx, volumesTableMetricNamesList)
missingMetrics, minFirstReportedUnixMilli, err := m.getMetricsExistenceAndEarliestTime(ctx, volumesTableMetricNamesList)
if err != nil {
return nil, err
}
if len(missingMetrics) > 0 {
resp.RequiredMetricsCheck = inframonitoringtypes.RequiredMetricsCheck{MissingMetrics: missingMetrics}
resp.Records = []inframonitoringtypes.VolumeRecord{}
resp.Total = 0
return resp, nil
}
if req.End < int64(minFirstReportedUnixMilli) {
resp.EndTimeBeforeRetention = true
resp.Records = []inframonitoringtypes.VolumeRecord{}
resp.Total = 0
return resp, nil
}
resp.RequiredMetricsCheck = inframonitoringtypes.RequiredMetricsCheck{MissingMetrics: []string{}}
metadataMap, err := m.getVolumesTableMetadata(ctx, req)
if err != nil {
@@ -589,16 +632,23 @@ func (m *module) ListDeployments(ctx context.Context, orgID valuer.UUID, req *in
}
req.Filter.Expression = mergeFilterExpressions(deploymentsBaseFilterExpr, req.Filter.Expression)
minFirstReportedUnixMilli, err := m.getEarliestMetricTime(ctx, deploymentsTableMetricNamesList)
missingMetrics, minFirstReportedUnixMilli, err := m.getMetricsExistenceAndEarliestTime(ctx, deploymentsTableMetricNamesList)
if err != nil {
return nil, err
}
if len(missingMetrics) > 0 {
resp.RequiredMetricsCheck = inframonitoringtypes.RequiredMetricsCheck{MissingMetrics: missingMetrics}
resp.Records = []inframonitoringtypes.DeploymentRecord{}
resp.Total = 0
return resp, nil
}
if req.End < int64(minFirstReportedUnixMilli) {
resp.EndTimeBeforeRetention = true
resp.Records = []inframonitoringtypes.DeploymentRecord{}
resp.Total = 0
return resp, nil
}
resp.RequiredMetricsCheck = inframonitoringtypes.RequiredMetricsCheck{MissingMetrics: []string{}}
metadataMap, err := m.getDeploymentsTableMetadata(ctx, req)
if err != nil {
@@ -672,16 +722,23 @@ func (m *module) ListStatefulSets(ctx context.Context, orgID valuer.UUID, req *i
}
req.Filter.Expression = mergeFilterExpressions(statefulSetsBaseFilterExpr, req.Filter.Expression)
minFirstReportedUnixMilli, err := m.getEarliestMetricTime(ctx, statefulSetsTableMetricNamesList)
missingMetrics, minFirstReportedUnixMilli, err := m.getMetricsExistenceAndEarliestTime(ctx, statefulSetsTableMetricNamesList)
if err != nil {
return nil, err
}
if len(missingMetrics) > 0 {
resp.RequiredMetricsCheck = inframonitoringtypes.RequiredMetricsCheck{MissingMetrics: missingMetrics}
resp.Records = []inframonitoringtypes.StatefulSetRecord{}
resp.Total = 0
return resp, nil
}
if req.End < int64(minFirstReportedUnixMilli) {
resp.EndTimeBeforeRetention = true
resp.Records = []inframonitoringtypes.StatefulSetRecord{}
resp.Total = 0
return resp, nil
}
resp.RequiredMetricsCheck = inframonitoringtypes.RequiredMetricsCheck{MissingMetrics: []string{}}
metadataMap, err := m.getStatefulSetsTableMetadata(ctx, req)
if err != nil {
@@ -757,16 +814,23 @@ func (m *module) ListJobs(ctx context.Context, orgID valuer.UUID, req *inframoni
}
req.Filter.Expression = mergeFilterExpressions(jobsBaseFilterExpr, req.Filter.Expression)
minFirstReportedUnixMilli, err := m.getEarliestMetricTime(ctx, jobsTableMetricNamesList)
missingMetrics, minFirstReportedUnixMilli, err := m.getMetricsExistenceAndEarliestTime(ctx, jobsTableMetricNamesList)
if err != nil {
return nil, err
}
if len(missingMetrics) > 0 {
resp.RequiredMetricsCheck = inframonitoringtypes.RequiredMetricsCheck{MissingMetrics: missingMetrics}
resp.Records = []inframonitoringtypes.JobRecord{}
resp.Total = 0
return resp, nil
}
if req.End < int64(minFirstReportedUnixMilli) {
resp.EndTimeBeforeRetention = true
resp.Records = []inframonitoringtypes.JobRecord{}
resp.Total = 0
return resp, nil
}
resp.RequiredMetricsCheck = inframonitoringtypes.RequiredMetricsCheck{MissingMetrics: []string{}}
metadataMap, err := m.getJobsTableMetadata(ctx, req)
if err != nil {
@@ -842,16 +906,23 @@ func (m *module) ListDaemonSets(ctx context.Context, orgID valuer.UUID, req *inf
}
req.Filter.Expression = mergeFilterExpressions(daemonSetsBaseFilterExpr, req.Filter.Expression)
minFirstReportedUnixMilli, err := m.getEarliestMetricTime(ctx, daemonSetsTableMetricNamesList)
missingMetrics, minFirstReportedUnixMilli, err := m.getMetricsExistenceAndEarliestTime(ctx, daemonSetsTableMetricNamesList)
if err != nil {
return nil, err
}
if len(missingMetrics) > 0 {
resp.RequiredMetricsCheck = inframonitoringtypes.RequiredMetricsCheck{MissingMetrics: missingMetrics}
resp.Records = []inframonitoringtypes.DaemonSetRecord{}
resp.Total = 0
return resp, nil
}
if req.End < int64(minFirstReportedUnixMilli) {
resp.EndTimeBeforeRetention = true
resp.Records = []inframonitoringtypes.DaemonSetRecord{}
resp.Total = 0
return resp, nil
}
resp.RequiredMetricsCheck = inframonitoringtypes.RequiredMetricsCheck{MissingMetrics: []string{}}
metadataMap, err := m.getDaemonSetsTableMetadata(ctx, req)
if err != nil {

View File

@@ -141,7 +141,7 @@ func (m *module) listMetrics(ctx context.Context, orgID valuer.UUID, params *met
sb.Select("DISTINCT metric_name")
if params.Start != nil && params.End != nil {
start, end, distributedTsTable, _ := telemetrymetrics.WhichTSTableToUse(uint64(*params.Start), uint64(*params.End), nil)
start, end, distributedTsTable, _ := telemetrymetrics.WhichTSTableToUse(uint64(*params.Start), uint64(*params.End), false, nil)
sb.From(fmt.Sprintf("%s.%s", telemetrymetrics.DBName, distributedTsTable))
sb.Where(sb.Between("unix_milli", start, end))
} else {
@@ -527,7 +527,7 @@ func (m *module) InspectMetrics(
return nil, err
}
tsStart, _, tsTable, _ := telemetrymetrics.WhichTSTableToUse(start, end, nil)
tsStart, _, tsTable, _ := telemetrymetrics.WhichTSTableToUse(start, end, false, nil)
tsSb := sqlbuilder.NewSelectBuilder()
tsSb.Select("fingerprint", "labels")
tsSb.From(fmt.Sprintf("%s.%s", telemetrymetrics.DBName, tsTable))
@@ -971,8 +971,8 @@ func (m *module) fetchMetricsStatsWithSamples(
}
}
start, end, distributedTsTable, localTsTable := telemetrymetrics.WhichTSTableToUse(uint64(req.Start), uint64(req.End), nil)
distributedSamplesTable, _ := telemetrymetrics.WhichSamplesTableToUse(uint64(req.Start), uint64(req.End), metrictypes.UnspecifiedType, metrictypes.TimeAggregationUnspecified, nil)
start, end, distributedTsTable, localTsTable := telemetrymetrics.WhichTSTableToUse(uint64(req.Start), uint64(req.End), false, nil)
distributedSamplesTable, _ := telemetrymetrics.WhichSamplesTableToUse(uint64(req.Start), uint64(req.End), metrictypes.UnspecifiedType, metrictypes.TimeAggregationUnspecified, false, nil)
countExp := telemetrymetrics.CountExpressionForSamplesTable(distributedSamplesTable)
// Timeseries counts per metric
@@ -1100,7 +1100,7 @@ func (m *module) computeTimeseriesTreemap(ctx context.Context, req *metricsexplo
}
}
start, end, distributedTsTable, _ := telemetrymetrics.WhichTSTableToUse(uint64(req.Start), uint64(req.End), nil)
start, end, distributedTsTable, _ := telemetrymetrics.WhichTSTableToUse(uint64(req.Start), uint64(req.End), false, nil)
totalTSBuilder := sqlbuilder.NewSelectBuilder()
totalTSBuilder.Select("uniq(fingerprint) AS total_time_series")
@@ -1176,8 +1176,8 @@ func (m *module) computeSamplesTreemap(ctx context.Context, req *metricsexplorer
}
}
start, end, distributedTsTable, localTsTable := telemetrymetrics.WhichTSTableToUse(uint64(req.Start), uint64(req.End), nil)
distributedSamplesTable, _ := telemetrymetrics.WhichSamplesTableToUse(uint64(req.Start), uint64(req.End), metrictypes.UnspecifiedType, metrictypes.TimeAggregationUnspecified, nil)
start, end, distributedTsTable, localTsTable := telemetrymetrics.WhichTSTableToUse(uint64(req.Start), uint64(req.End), false, nil)
distributedSamplesTable, _ := telemetrymetrics.WhichSamplesTableToUse(uint64(req.Start), uint64(req.End), metrictypes.UnspecifiedType, metrictypes.TimeAggregationUnspecified, false, nil)
countExp := telemetrymetrics.CountExpressionForSamplesTable(distributedSamplesTable)
candidateLimit := req.Limit + 50

View File

@@ -91,13 +91,22 @@ func (q *builderQuery[T]) Fingerprint() string {
if a.ComparisonSpaceAggregationParam != nil {
spaceAggParamStr = a.ComparisonSpaceAggregationParam.StringValue()
}
aggParts = append(aggParts, fmt.Sprintf("%s:%s:%s:%s:%s",
part := fmt.Sprintf("%s:%s:%s:%s:%s",
a.MetricName,
a.Temporality.StringValue(),
a.TimeAggregation.StringValue(),
a.SpaceAggregation.StringValue(),
spaceAggParamStr,
))
)
if a.Reduced {
oneDay := uint64(24 * time.Hour.Milliseconds())
route := "reduced"
if q.toMS-q.fromMS < oneDay && q.fromMS >= uint64(time.Now().UnixMilli())-oneDay {
route = "buffer"
}
part += ":" + route
}
aggParts = append(aggParts, part)
}
}
parts = append(parts, fmt.Sprintf("aggs=[%s]", strings.Join(aggParts, ",")))

View File

@@ -119,7 +119,7 @@ func (q *querier) QueryRange(ctx context.Context, orgID valuer.UUID, req *qbtype
queries := make(map[string]qbtypes.Query)
steps := make(map[string]qbtypes.Step)
missingMetricQueries, metricWarnings, err := q.resolveMetricMetadata(ctx, req.CompositeQuery.Queries, req.Start, req.End)
missingMetricQueries, metricWarnings, err := q.resolveMetricMetadata(ctx, orgID, req.CompositeQuery.Queries, req.Start, req.End)
if err != nil {
return nil, err
}
@@ -304,7 +304,7 @@ func (q *querier) populateQBEvent(event *qbtypes.QBEvent, queries []qbtypes.Quer
// resolved: never-seen metrics and dormant metrics (seen but no data in
// the query window).
// - err: Internal when a metadata fetch fails.
func (q *querier) resolveMetricMetadata(ctx context.Context, queries []qbtypes.QueryEnvelope, start, end uint64) (missingMetricQueries []string, metricWarnings []string, err error) {
func (q *querier) resolveMetricMetadata(ctx context.Context, orgID valuer.UUID, queries []qbtypes.QueryEnvelope, start, end uint64) (missingMetricQueries []string, metricWarnings []string, err error) {
metricNames := make([]string, 0)
for idx := range queries {
if queries[idx].Type != qbtypes.QueryTypeBuilder {
@@ -325,7 +325,7 @@ func (q *querier) resolveMetricMetadata(ctx context.Context, queries []qbtypes.Q
return nil, nil, nil
}
metricTemporality, metricTypes, err := q.metadataStore.FetchTemporalityAndTypeMulti(ctx, start, end, metricNames...)
metricTemporality, metricTypes, reducedMetricsSet, err := q.metadataStore.FetchTemporalityAndTypeMulti(ctx, orgID, start, end, metricNames...)
if err != nil {
q.logger.WarnContext(ctx, "failed to fetch metric temporality", errors.Attr(err), slog.Any("metrics", metricNames))
return nil, nil, errors.NewInternalf(errors.CodeInternal, "failed to fetch metrics temporality")
@@ -362,6 +362,9 @@ func (q *querier) resolveMetricMetadata(ctx context.Context, queries []qbtypes.Q
if err := spec.Aggregations[i].ValidateForType(); err != nil {
return nil, nil, err
}
if reducedMetricsSet[spec.Aggregations[i].MetricName] {
spec.Aggregations[i].Reduced = true
}
presentAggregations = append(presentAggregations, spec.Aggregations[i])
}
if len(presentAggregations) == 0 {

View File

@@ -2136,12 +2136,12 @@ func (t *telemetryMetaStore) GetAllValues(ctx context.Context, fieldValueSelecto
return values, complete, nil
}
func (t *telemetryMetaStore) FetchTemporality(ctx context.Context, queryTimeRangeStartTs, queryTimeRangeEndTs uint64, metricName string) (metrictypes.Temporality, error) {
func (t *telemetryMetaStore) FetchTemporality(ctx context.Context, orgID valuer.UUID, queryTimeRangeStartTs, queryTimeRangeEndTs uint64, metricName string) (metrictypes.Temporality, error) {
if metricName == "" {
return metrictypes.Unknown, errors.Newf(errors.TypeInternal, errors.CodeInternal, "metric name cannot be empty")
}
temporalityMap, err := t.FetchTemporalityMulti(ctx, queryTimeRangeStartTs, queryTimeRangeEndTs, metricName)
temporalityMap, err := t.FetchTemporalityMulti(ctx, orgID, queryTimeRangeStartTs, queryTimeRangeEndTs, metricName)
if err != nil {
return metrictypes.Unknown, err
}
@@ -2154,25 +2154,27 @@ func (t *telemetryMetaStore) FetchTemporality(ctx context.Context, queryTimeRang
return temporality, nil
}
func (t *telemetryMetaStore) FetchTemporalityMulti(ctx context.Context, queryTimeRangeStartTs, queryTimeRangeEndTs uint64, metricNames ...string) (map[string]metrictypes.Temporality, error) {
temporalities, _, err := t.FetchTemporalityAndTypeMulti(ctx, queryTimeRangeStartTs, queryTimeRangeEndTs, metricNames...)
func (t *telemetryMetaStore) FetchTemporalityMulti(ctx context.Context, orgID valuer.UUID, queryTimeRangeStartTs, queryTimeRangeEndTs uint64, metricNames ...string) (map[string]metrictypes.Temporality, error) {
temporalities, _, _, err := t.FetchTemporalityAndTypeMulti(ctx, orgID, queryTimeRangeStartTs, queryTimeRangeEndTs, metricNames...)
return temporalities, err
}
func (t *telemetryMetaStore) FetchTemporalityAndTypeMulti(ctx context.Context, queryTimeRangeStartTs, queryTimeRangeEndTs uint64, metricNames ...string) (map[string]metrictypes.Temporality, map[string]metrictypes.Type, error) {
func (t *telemetryMetaStore) FetchTemporalityAndTypeMulti(ctx context.Context, orgID valuer.UUID, queryTimeRangeStartTs, queryTimeRangeEndTs uint64, metricNames ...string) (map[string]metrictypes.Temporality, map[string]metrictypes.Type, map[string]bool, error) {
if len(metricNames) == 0 {
return make(map[string]metrictypes.Temporality), make(map[string]metrictypes.Type), nil
return make(map[string]metrictypes.Temporality), make(map[string]metrictypes.Type), make(map[string]bool), nil
}
reductionEnabled := t.fl.BooleanOrEmpty(ctx, flagger.FeatureEnableMetricsReduction, featuretypes.NewFlaggerEvaluationContext(orgID))
temporalities := make(map[string]metrictypes.Temporality)
types := make(map[string]metrictypes.Type)
metricsTemporality, metricTypes, err := t.fetchMetricsTemporalityAndType(ctx, queryTimeRangeStartTs, queryTimeRangeEndTs, metricNames...)
metricsTemporality, metricTypes, reduced, err := t.fetchMetricsTemporalityAndType(ctx, queryTimeRangeStartTs, queryTimeRangeEndTs, reductionEnabled, metricNames...)
if err != nil {
return nil, nil, err
return nil, nil, nil, err
}
meterMetricsTemporality, meterMetricsTypes, err := t.fetchMeterSourceMetricsTemporalityAndType(ctx, metricNames...)
if err != nil {
return nil, nil, err
return nil, nil, nil, err
}
// For metrics not found in the database, set to Unknown
@@ -2197,10 +2199,10 @@ func (t *telemetryMetaStore) FetchTemporalityAndTypeMulti(ctx context.Context, q
}
}
return temporalities, types, nil
return temporalities, types, reduced, nil
}
func (t *telemetryMetaStore) fetchMetricsTemporalityAndType(ctx context.Context, queryTimeRangeStartTs, queryTimeRangeEndTs uint64, metricNames ...string) (map[string][]metrictypes.Temporality, map[string]metrictypes.Type, error) {
func (t *telemetryMetaStore) fetchMetricsTemporalityAndType(ctx context.Context, queryTimeRangeStartTs, queryTimeRangeEndTs uint64, reductionEnabled bool, metricNames ...string) (map[string][]metrictypes.Temporality, map[string]metrictypes.Type, map[string]bool, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalMetrics.StringValue(),
instrumentationtypes.CodeNamespace: "metadata",
@@ -2208,48 +2210,58 @@ func (t *telemetryMetaStore) fetchMetricsTemporalityAndType(ctx context.Context,
})
temporalities := make(map[string][]metrictypes.Temporality)
types := make(map[string]metrictypes.Type)
reduced := make(map[string]bool)
adjustedStartTs, adjustedEndTs, tsTableName, _ := telemetrymetrics.WhichTSTableToUse(queryTimeRangeStartTs, queryTimeRangeEndTs, nil)
adjustedStartTs, adjustedEndTs, tsTableName, _ := telemetrymetrics.WhichTSTableToUse(queryTimeRangeStartTs, queryTimeRangeEndTs, false, nil)
// Build query to fetch temporality for all metrics
// We use attr_string_value where attr_name = '__temporality__'
// Note: The columns are mixed in the current data - temporality column contains metric_name
// and metric_name column contains temporality value, so we use the correct mapping
sb := sqlbuilder.Select(
"metric_name",
"temporality",
"any(type) AS type",
"any(is_monotonic) as is_monotonic",
).
From(t.metricsDBName + "." + tsTableName)
cols := []string{"metric_name", "temporality", "any(type) AS type", "any(is_monotonic) as is_monotonic"}
// Filter by metric names (in the temporality column due to data mix-up)
// When reduction is enabled, fold the reduced-catalog presence check into the
// same query so a metric's reduced status comes back in one round trip.
var reducedArgs []any
if reductionEnabled {
rs := sqlbuilder.NewSelectBuilder()
rs.Select("metric_name")
rs.From(t.metricsDBName + "." + telemetrymetrics.TimeseriesV4ReducedTableName)
rs.Where(rs.In("metric_name", metricNames), rs.GTE("unix_milli", adjustedStartTs), rs.LT("unix_milli", adjustedEndTs))
rs.GroupBy("metric_name")
rsQuery, rsArgs := rs.BuildWithFlavor(sqlbuilder.ClickHouse)
cols = append(cols, fmt.Sprintf("metric_name GLOBAL IN (%s) AS reduced", rsQuery))
reducedArgs = rsArgs
}
sb := sqlbuilder.NewSelectBuilder()
sb.Select(cols...)
sb.From(t.metricsDBName + "." + tsTableName)
sb.Where(
sb.In("metric_name", metricNames),
sb.GTE("unix_milli", adjustedStartTs),
sb.LT("unix_milli", adjustedEndTs),
)
sb.GroupBy("metric_name", "temporality")
query, args := sb.BuildWithFlavor(sqlbuilder.ClickHouse)
query, args := sb.BuildWithFlavor(sqlbuilder.ClickHouse, reducedArgs...)
t.logger.DebugContext(ctx, "fetching metric temporality", slog.String("query", query), slog.Any("args", args))
rows, err := t.telemetrystore.ClickhouseDB().Query(ctx, query, args...)
if err != nil {
return nil, nil, errors.Wrapf(err, errors.TypeInternal, errors.CodeInternal, "failed to fetch metric temporality")
return nil, nil, nil, errors.Wrapf(err, errors.TypeInternal, errors.CodeInternal, "failed to fetch metric temporality")
}
defer rows.Close()
// Process results
for rows.Next() {
var metricName string
var temporality metrictypes.Temporality
var metricType metrictypes.Type
var isMonotonic bool
if err := rows.Scan(&metricName, &temporality, &metricType, &isMonotonic); err != nil {
return nil, nil, errors.Wrapf(err, errors.TypeInternal, errors.CodeInternal, "failed to scan temporality result")
var isReduced uint8
dest := []any{&metricName, &temporality, &metricType, &isMonotonic}
if reductionEnabled {
dest = append(dest, &isReduced)
}
if err := rows.Scan(dest...); err != nil {
return nil, nil, nil, errors.Wrapf(err, errors.TypeInternal, errors.CodeInternal, "failed to scan temporality result")
}
if temporality != metrictypes.Unknown {
temporalities[metricName] = append(temporalities[metricName], temporality)
@@ -2258,12 +2270,15 @@ func (t *telemetryMetaStore) fetchMetricsTemporalityAndType(ctx context.Context,
metricType = metrictypes.GaugeType
}
types[metricName] = metricType
if isReduced != 0 {
reduced[metricName] = true
}
}
if err := rows.Err(); err != nil {
return nil, nil, errors.Wrapf(err, errors.TypeInternal, errors.CodeInternal, "error iterating over metrics temporality rows")
return nil, nil, nil, errors.Wrapf(err, errors.TypeInternal, errors.CodeInternal, "error iterating over metrics temporality rows")
}
return temporalities, types, nil
return temporalities, types, reduced, nil
}
func (t *telemetryMetaStore) fetchMeterSourceMetricsTemporalityAndType(ctx context.Context, metricNames ...string) (map[string]metrictypes.Temporality, map[string]metrictypes.Type, error) {

View File

@@ -0,0 +1,157 @@
package telemetrymetrics
import (
"context"
"testing"
"time"
"github.com/SigNoz/signoz/pkg/flagger"
"github.com/SigNoz/signoz/pkg/instrumentation/instrumentationtest"
"github.com/SigNoz/signoz/pkg/types/metrictypes"
qbtypes "github.com/SigNoz/signoz/pkg/types/querybuildertypes/querybuildertypesv5"
"github.com/SigNoz/signoz/pkg/types/telemetrytypes"
"github.com/SigNoz/signoz/pkg/types/telemetrytypes/telemetrytypestest"
"github.com/stretchr/testify/require"
)
func reducedQuery(metric string, ty metrictypes.Type, temp metrictypes.Temporality, ta metrictypes.TimeAggregation, sa metrictypes.SpaceAggregation) qbtypes.QueryBuilderQuery[qbtypes.MetricAggregation] {
return qbtypes.QueryBuilderQuery[qbtypes.MetricAggregation]{
Signal: telemetrytypes.SignalMetrics,
StepInterval: qbtypes.Step{Duration: 5 * time.Minute},
Aggregations: []qbtypes.MetricAggregation{{
MetricName: metric,
Type: ty,
Temporality: temp,
TimeAggregation: ta,
SpaceAggregation: sa,
Reduced: true,
}},
}
}
func TestReducedStatementBuilder(t *testing.T) {
cases := []struct {
name string
query qbtypes.QueryBuilderQuery[qbtypes.MetricAggregation]
expected qbtypes.Statement
}{
{
name: "gauge_sum_latest",
query: reducedQuery("test.metric", metrictypes.GaugeType, metrictypes.Unspecified, metrictypes.TimeAggregationLatest, metrictypes.SpaceAggregationSum),
expected: qbtypes.Statement{
Query: "SELECT * FROM (WITH __temporal_aggregation_cte AS (SELECT fingerprint, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), toIntervalSecond(300)) AS ts, anyLast(last) AS per_series_value FROM signoz_metrics.distributed_samples_v4_agg_5m AS points INNER JOIN (SELECT fingerprint FROM signoz_metrics.time_series_v4_1day WHERE metric_name IN (?) AND unix_milli >= ? AND unix_milli <= ? AND LOWER(temporality) LIKE LOWER(?) AND __normalized = ? GROUP BY fingerprint) AS filtered_time_series ON points.fingerprint = filtered_time_series.fingerprint WHERE metric_name IN (?) AND unix_milli >= ? AND unix_milli < ? GROUP BY fingerprint, ts ORDER BY fingerprint, ts), __spatial_aggregation_cte AS (SELECT ts, sum(per_series_value) AS value FROM __temporal_aggregation_cte WHERE isNaN(per_series_value) = ? GROUP BY ts) SELECT * FROM __spatial_aggregation_cte ORDER BY ts) UNION ALL SELECT * FROM (WITH __temporal_aggregation_cte AS (SELECT fingerprint, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), toIntervalSecond(300)) AS ts, argMax(value, unix_milli) AS per_series_value FROM (SELECT reduced_fingerprint AS fingerprint, unix_milli, argMax(`sum_last`, computed_at) AS value FROM signoz_metrics.distributed_samples_v4_reduced_last_60s WHERE metric_name IN (?) AND unix_milli >= ? AND unix_milli < ? GROUP BY reduced_fingerprint, unix_milli) AS points INNER JOIN (SELECT fingerprint FROM signoz_metrics.distributed_time_series_v4_reduced WHERE metric_name IN (?) AND unix_milli >= ? AND unix_milli <= ? AND __normalized = ? GROUP BY fingerprint) AS filtered_time_series ON points.fingerprint = filtered_time_series.fingerprint GROUP BY fingerprint, ts), __spatial_aggregation_cte AS (SELECT ts, sum(per_series_value) AS value FROM __temporal_aggregation_cte GROUP BY ts) SELECT * FROM __spatial_aggregation_cte ORDER BY ts) ORDER BY ts",
Args: []any{"test.metric", uint64(1746921600000), uint64(1747172760000), "unspecified", false, "test.metric", uint64(1746999900000), uint64(1747172760000), 0, "test.metric", uint64(1746999900000), uint64(1747172760000), "test.metric", uint64(1746999900000), uint64(1747172760000), false},
},
},
{
name: "gauge_avg_avg",
query: reducedQuery("test.metric", metrictypes.GaugeType, metrictypes.Unspecified, metrictypes.TimeAggregationAvg, metrictypes.SpaceAggregationAvg),
expected: qbtypes.Statement{
Query: "SELECT * FROM (WITH __temporal_aggregation_cte AS (SELECT fingerprint, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), toIntervalSecond(300)) AS ts, sum(sum) / sum(count) AS per_series_value FROM signoz_metrics.distributed_samples_v4_agg_5m AS points INNER JOIN (SELECT fingerprint FROM signoz_metrics.time_series_v4_1day WHERE metric_name IN (?) AND unix_milli >= ? AND unix_milli <= ? AND LOWER(temporality) LIKE LOWER(?) AND __normalized = ? GROUP BY fingerprint) AS filtered_time_series ON points.fingerprint = filtered_time_series.fingerprint WHERE metric_name IN (?) AND unix_milli >= ? AND unix_milli < ? GROUP BY fingerprint, ts ORDER BY fingerprint, ts), __spatial_aggregation_cte AS (SELECT ts, avg(per_series_value) AS value FROM __temporal_aggregation_cte WHERE isNaN(per_series_value) = ? GROUP BY ts) SELECT * FROM __spatial_aggregation_cte ORDER BY ts) UNION ALL SELECT * FROM (WITH __temporal_aggregation_cte AS (SELECT fingerprint, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), toIntervalSecond(300)) AS ts, avg(value) AS per_series_value, avg(weight) AS per_series_weight FROM (SELECT reduced_fingerprint AS fingerprint, unix_milli, argMax(`sum_last`, computed_at) AS value, argMax(`count_series`, computed_at) AS weight FROM signoz_metrics.distributed_samples_v4_reduced_last_60s WHERE metric_name IN (?) AND unix_milli >= ? AND unix_milli < ? GROUP BY reduced_fingerprint, unix_milli) AS points INNER JOIN (SELECT fingerprint FROM signoz_metrics.distributed_time_series_v4_reduced WHERE metric_name IN (?) AND unix_milli >= ? AND unix_milli <= ? AND __normalized = ? GROUP BY fingerprint) AS filtered_time_series ON points.fingerprint = filtered_time_series.fingerprint GROUP BY fingerprint, ts), __spatial_aggregation_cte AS (SELECT ts, sum(per_series_value) / sum(per_series_weight) AS value FROM __temporal_aggregation_cte GROUP BY ts) SELECT * FROM __spatial_aggregation_cte ORDER BY ts) ORDER BY ts",
Args: []any{"test.metric", uint64(1746921600000), uint64(1747172760000), "unspecified", false, "test.metric", uint64(1746999900000), uint64(1747172760000), 0, "test.metric", uint64(1746999900000), uint64(1747172760000), "test.metric", uint64(1746999900000), uint64(1747172760000), false},
},
},
{
name: "gauge_min_min",
query: reducedQuery("test.metric", metrictypes.GaugeType, metrictypes.Unspecified, metrictypes.TimeAggregationMin, metrictypes.SpaceAggregationMin),
expected: qbtypes.Statement{
Query: "SELECT * FROM (WITH __temporal_aggregation_cte AS (SELECT fingerprint, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), toIntervalSecond(300)) AS ts, min(min) AS per_series_value FROM signoz_metrics.distributed_samples_v4_agg_5m AS points INNER JOIN (SELECT fingerprint FROM signoz_metrics.time_series_v4_1day WHERE metric_name IN (?) AND unix_milli >= ? AND unix_milli <= ? AND LOWER(temporality) LIKE LOWER(?) AND __normalized = ? GROUP BY fingerprint) AS filtered_time_series ON points.fingerprint = filtered_time_series.fingerprint WHERE metric_name IN (?) AND unix_milli >= ? AND unix_milli < ? GROUP BY fingerprint, ts ORDER BY fingerprint, ts), __spatial_aggregation_cte AS (SELECT ts, min(per_series_value) AS value FROM __temporal_aggregation_cte WHERE isNaN(per_series_value) = ? GROUP BY ts) SELECT * FROM __spatial_aggregation_cte ORDER BY ts) UNION ALL SELECT * FROM (WITH __temporal_aggregation_cte AS (SELECT fingerprint, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), toIntervalSecond(300)) AS ts, min(value) AS per_series_value FROM (SELECT reduced_fingerprint AS fingerprint, unix_milli, argMax(`min`, computed_at) AS value FROM signoz_metrics.distributed_samples_v4_reduced_last_60s WHERE metric_name IN (?) AND unix_milli >= ? AND unix_milli < ? GROUP BY reduced_fingerprint, unix_milli) AS points INNER JOIN (SELECT fingerprint FROM signoz_metrics.distributed_time_series_v4_reduced WHERE metric_name IN (?) AND unix_milli >= ? AND unix_milli <= ? AND __normalized = ? GROUP BY fingerprint) AS filtered_time_series ON points.fingerprint = filtered_time_series.fingerprint GROUP BY fingerprint, ts), __spatial_aggregation_cte AS (SELECT ts, min(per_series_value) AS value FROM __temporal_aggregation_cte GROUP BY ts) SELECT * FROM __spatial_aggregation_cte ORDER BY ts) ORDER BY ts",
Args: []any{"test.metric", uint64(1746921600000), uint64(1747172760000), "unspecified", false, "test.metric", uint64(1746999900000), uint64(1747172760000), 0, "test.metric", uint64(1746999900000), uint64(1747172760000), "test.metric", uint64(1746999900000), uint64(1747172760000), false},
},
},
{
name: "gauge_max_max",
query: reducedQuery("test.metric", metrictypes.GaugeType, metrictypes.Unspecified, metrictypes.TimeAggregationMax, metrictypes.SpaceAggregationMax),
expected: qbtypes.Statement{
Query: "SELECT * FROM (WITH __temporal_aggregation_cte AS (SELECT fingerprint, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), toIntervalSecond(300)) AS ts, max(max) AS per_series_value FROM signoz_metrics.distributed_samples_v4_agg_5m AS points INNER JOIN (SELECT fingerprint FROM signoz_metrics.time_series_v4_1day WHERE metric_name IN (?) AND unix_milli >= ? AND unix_milli <= ? AND LOWER(temporality) LIKE LOWER(?) AND __normalized = ? GROUP BY fingerprint) AS filtered_time_series ON points.fingerprint = filtered_time_series.fingerprint WHERE metric_name IN (?) AND unix_milli >= ? AND unix_milli < ? GROUP BY fingerprint, ts ORDER BY fingerprint, ts), __spatial_aggregation_cte AS (SELECT ts, max(per_series_value) AS value FROM __temporal_aggregation_cte WHERE isNaN(per_series_value) = ? GROUP BY ts) SELECT * FROM __spatial_aggregation_cte ORDER BY ts) UNION ALL SELECT * FROM (WITH __temporal_aggregation_cte AS (SELECT fingerprint, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), toIntervalSecond(300)) AS ts, max(value) AS per_series_value FROM (SELECT reduced_fingerprint AS fingerprint, unix_milli, argMax(`max`, computed_at) AS value FROM signoz_metrics.distributed_samples_v4_reduced_last_60s WHERE metric_name IN (?) AND unix_milli >= ? AND unix_milli < ? GROUP BY reduced_fingerprint, unix_milli) AS points INNER JOIN (SELECT fingerprint FROM signoz_metrics.distributed_time_series_v4_reduced WHERE metric_name IN (?) AND unix_milli >= ? AND unix_milli <= ? AND __normalized = ? GROUP BY fingerprint) AS filtered_time_series ON points.fingerprint = filtered_time_series.fingerprint GROUP BY fingerprint, ts), __spatial_aggregation_cte AS (SELECT ts, max(per_series_value) AS value FROM __temporal_aggregation_cte GROUP BY ts) SELECT * FROM __spatial_aggregation_cte ORDER BY ts) ORDER BY ts",
Args: []any{"test.metric", uint64(1746921600000), uint64(1747172760000), "unspecified", false, "test.metric", uint64(1746999900000), uint64(1747172760000), 0, "test.metric", uint64(1746999900000), uint64(1747172760000), "test.metric", uint64(1746999900000), uint64(1747172760000), false},
},
},
{
name: "counter_sum_rate",
query: reducedQuery("test.metric", metrictypes.SumType, metrictypes.Cumulative, metrictypes.TimeAggregationRate, metrictypes.SpaceAggregationSum),
expected: qbtypes.Statement{
Query: "SELECT * FROM (WITH __temporal_aggregation_cte AS (SELECT ts, multiIf(row_number() OVER rate_window = 1, nan, (per_series_value - lagInFrame(per_series_value, 1) OVER rate_window) < 0, per_series_value / (ts - lagInFrame(ts, 1) OVER rate_window), (per_series_value - lagInFrame(per_series_value, 1) OVER rate_window) / (ts - lagInFrame(ts, 1) OVER rate_window)) AS per_series_value FROM (SELECT fingerprint, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), toIntervalSecond(300)) AS ts, max(max) AS per_series_value FROM signoz_metrics.distributed_samples_v4_agg_5m AS points INNER JOIN (SELECT fingerprint FROM signoz_metrics.time_series_v4_1day WHERE metric_name IN (?) AND unix_milli >= ? AND unix_milli <= ? AND LOWER(temporality) LIKE LOWER(?) AND __normalized = ? GROUP BY fingerprint) AS filtered_time_series ON points.fingerprint = filtered_time_series.fingerprint WHERE metric_name IN (?) AND unix_milli >= ? AND unix_milli < ? GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WINDOW rate_window AS (PARTITION BY fingerprint ORDER BY fingerprint, ts)), __spatial_aggregation_cte AS (SELECT ts, sum(per_series_value) AS value FROM __temporal_aggregation_cte WHERE isNaN(per_series_value) = ? GROUP BY ts) SELECT * FROM __spatial_aggregation_cte ORDER BY ts) UNION ALL SELECT * FROM (WITH __temporal_aggregation_cte AS (SELECT fingerprint, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), toIntervalSecond(300)) AS ts, sum(value) / 300 AS per_series_value FROM (SELECT reduced_fingerprint AS fingerprint, unix_milli, argMax(`sum`, computed_at) AS value FROM signoz_metrics.distributed_samples_v4_reduced_sum_60s WHERE metric_name IN (?) AND unix_milli >= ? AND unix_milli < ? GROUP BY reduced_fingerprint, unix_milli) AS points INNER JOIN (SELECT fingerprint FROM signoz_metrics.distributed_time_series_v4_reduced WHERE metric_name IN (?) AND unix_milli >= ? AND unix_milli <= ? AND __normalized = ? GROUP BY fingerprint) AS filtered_time_series ON points.fingerprint = filtered_time_series.fingerprint GROUP BY fingerprint, ts), __spatial_aggregation_cte AS (SELECT ts, sum(per_series_value) AS value FROM __temporal_aggregation_cte GROUP BY ts) SELECT * FROM __spatial_aggregation_cte ORDER BY ts) ORDER BY ts",
Args: []any{"test.metric", uint64(1746921600000), uint64(1747172760000), "cumulative", false, "test.metric", uint64(1746999600000), uint64(1747172760000), 0, "test.metric", uint64(1746999600000), uint64(1747172760000), "test.metric", uint64(1746999600000), uint64(1747172760000), false},
},
},
{
name: "counter_avg_increase",
query: reducedQuery("test.metric", metrictypes.SumType, metrictypes.Cumulative, metrictypes.TimeAggregationIncrease, metrictypes.SpaceAggregationAvg),
expected: qbtypes.Statement{
Query: "SELECT * FROM (WITH __temporal_aggregation_cte AS (SELECT ts, multiIf(row_number() OVER rate_window = 1, nan, (per_series_value - lagInFrame(per_series_value, 1) OVER rate_window) < 0, per_series_value, per_series_value - lagInFrame(per_series_value, 1) OVER rate_window) AS per_series_value FROM (SELECT fingerprint, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), toIntervalSecond(300)) AS ts, max(max) AS per_series_value FROM signoz_metrics.distributed_samples_v4_agg_5m AS points INNER JOIN (SELECT fingerprint FROM signoz_metrics.time_series_v4_1day WHERE metric_name IN (?) AND unix_milli >= ? AND unix_milli <= ? AND LOWER(temporality) LIKE LOWER(?) AND __normalized = ? GROUP BY fingerprint) AS filtered_time_series ON points.fingerprint = filtered_time_series.fingerprint WHERE metric_name IN (?) AND unix_milli >= ? AND unix_milli < ? GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WINDOW rate_window AS (PARTITION BY fingerprint ORDER BY fingerprint, ts)), __spatial_aggregation_cte AS (SELECT ts, avg(per_series_value) AS value FROM __temporal_aggregation_cte WHERE isNaN(per_series_value) = ? GROUP BY ts) SELECT * FROM __spatial_aggregation_cte ORDER BY ts) UNION ALL SELECT * FROM (WITH __temporal_aggregation_cte AS (SELECT fingerprint, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), toIntervalSecond(300)) AS ts, sum(value) AS per_series_value, avg(weight) AS per_series_weight FROM (SELECT reduced_fingerprint AS fingerprint, unix_milli, argMax(`sum`, computed_at) AS value, argMax(`count_series`, computed_at) AS weight FROM signoz_metrics.distributed_samples_v4_reduced_sum_60s WHERE metric_name IN (?) AND unix_milli >= ? AND unix_milli < ? GROUP BY reduced_fingerprint, unix_milli) AS points INNER JOIN (SELECT fingerprint FROM signoz_metrics.distributed_time_series_v4_reduced WHERE metric_name IN (?) AND unix_milli >= ? AND unix_milli <= ? AND __normalized = ? GROUP BY fingerprint) AS filtered_time_series ON points.fingerprint = filtered_time_series.fingerprint GROUP BY fingerprint, ts), __spatial_aggregation_cte AS (SELECT ts, sum(per_series_value) / sum(per_series_weight) AS value FROM __temporal_aggregation_cte GROUP BY ts) SELECT * FROM __spatial_aggregation_cte ORDER BY ts) ORDER BY ts",
Args: []any{"test.metric", uint64(1746921600000), uint64(1747172760000), "cumulative", false, "test.metric", uint64(1746999600000), uint64(1747172760000), 0, "test.metric", uint64(1746999600000), uint64(1747172760000), "test.metric", uint64(1746999600000), uint64(1747172760000), false},
},
},
{
name: "counter_min_omitted",
query: reducedQuery("test.metric", metrictypes.SumType, metrictypes.Cumulative, metrictypes.TimeAggregationRate, metrictypes.SpaceAggregationMin),
expected: qbtypes.Statement{
Query: "WITH __temporal_aggregation_cte AS (SELECT ts, multiIf(row_number() OVER rate_window = 1, nan, (per_series_value - lagInFrame(per_series_value, 1) OVER rate_window) < 0, per_series_value / (ts - lagInFrame(ts, 1) OVER rate_window), (per_series_value - lagInFrame(per_series_value, 1) OVER rate_window) / (ts - lagInFrame(ts, 1) OVER rate_window)) AS per_series_value FROM (SELECT fingerprint, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), toIntervalSecond(300)) AS ts, max(max) AS per_series_value FROM signoz_metrics.distributed_samples_v4_agg_5m AS points INNER JOIN (SELECT fingerprint FROM signoz_metrics.time_series_v4_1day WHERE metric_name IN (?) AND unix_milli >= ? AND unix_milli <= ? AND LOWER(temporality) LIKE LOWER(?) AND __normalized = ? GROUP BY fingerprint) AS filtered_time_series ON points.fingerprint = filtered_time_series.fingerprint WHERE metric_name IN (?) AND unix_milli >= ? AND unix_milli < ? GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WINDOW rate_window AS (PARTITION BY fingerprint ORDER BY fingerprint, ts)), __spatial_aggregation_cte AS (SELECT ts, min(per_series_value) AS value FROM __temporal_aggregation_cte WHERE isNaN(per_series_value) = ? GROUP BY ts) SELECT * FROM __spatial_aggregation_cte ORDER BY ts",
Args: []any{"test.metric", uint64(1746921600000), uint64(1747172760000), "cumulative", false, "test.metric", uint64(1746999600000), uint64(1747172760000), 0},
},
},
{
name: "counter_max_omitted",
query: reducedQuery("test.metric", metrictypes.SumType, metrictypes.Cumulative, metrictypes.TimeAggregationRate, metrictypes.SpaceAggregationMax),
expected: qbtypes.Statement{
Query: "WITH __temporal_aggregation_cte AS (SELECT ts, multiIf(row_number() OVER rate_window = 1, nan, (per_series_value - lagInFrame(per_series_value, 1) OVER rate_window) < 0, per_series_value / (ts - lagInFrame(ts, 1) OVER rate_window), (per_series_value - lagInFrame(per_series_value, 1) OVER rate_window) / (ts - lagInFrame(ts, 1) OVER rate_window)) AS per_series_value FROM (SELECT fingerprint, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), toIntervalSecond(300)) AS ts, max(max) AS per_series_value FROM signoz_metrics.distributed_samples_v4_agg_5m AS points INNER JOIN (SELECT fingerprint FROM signoz_metrics.time_series_v4_1day WHERE metric_name IN (?) AND unix_milli >= ? AND unix_milli <= ? AND LOWER(temporality) LIKE LOWER(?) AND __normalized = ? GROUP BY fingerprint) AS filtered_time_series ON points.fingerprint = filtered_time_series.fingerprint WHERE metric_name IN (?) AND unix_milli >= ? AND unix_milli < ? GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WINDOW rate_window AS (PARTITION BY fingerprint ORDER BY fingerprint, ts)), __spatial_aggregation_cte AS (SELECT ts, max(per_series_value) AS value FROM __temporal_aggregation_cte WHERE isNaN(per_series_value) = ? GROUP BY ts) SELECT * FROM __spatial_aggregation_cte ORDER BY ts",
Args: []any{"test.metric", uint64(1746921600000), uint64(1747172760000), "cumulative", false, "test.metric", uint64(1746999600000), uint64(1747172760000), 0},
},
},
{
name: "histogram_p99",
query: reducedQuery("test.metric", metrictypes.HistogramType, metrictypes.Cumulative, metrictypes.TimeAggregationUnspecified, metrictypes.SpaceAggregationPercentile99),
expected: qbtypes.Statement{
Query: "SELECT * FROM (WITH __temporal_aggregation_cte AS (SELECT ts, `le`, multiIf(row_number() OVER rate_window = 1, nan, (per_series_value - lagInFrame(per_series_value, 1) OVER rate_window) < 0, per_series_value / (ts - lagInFrame(ts, 1) OVER rate_window), (per_series_value - lagInFrame(per_series_value, 1) OVER rate_window) / (ts - lagInFrame(ts, 1) OVER rate_window)) AS per_series_value FROM (SELECT fingerprint, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), toIntervalSecond(300)) AS ts, `le`, max(max) AS per_series_value FROM signoz_metrics.distributed_samples_v4_agg_5m AS points INNER JOIN (SELECT fingerprint, JSONExtractString(labels, 'le') AS `le` FROM signoz_metrics.time_series_v4_1day WHERE metric_name IN (?) AND unix_milli >= ? AND unix_milli <= ? AND LOWER(temporality) LIKE LOWER(?) AND __normalized = ? GROUP BY fingerprint, `le`) AS filtered_time_series ON points.fingerprint = filtered_time_series.fingerprint WHERE metric_name IN (?) AND unix_milli >= ? AND unix_milli < ? GROUP BY fingerprint, ts, `le` ORDER BY fingerprint, ts) WINDOW rate_window AS (PARTITION BY fingerprint ORDER BY fingerprint, ts)), __spatial_aggregation_cte AS (SELECT ts, `le`, sum(per_series_value) AS value FROM __temporal_aggregation_cte WHERE isNaN(per_series_value) = ? GROUP BY ts, `le`) SELECT ts, histogramQuantile(arrayMap(x -> toFloat64(x), groupArray(le)), groupArray(value), 0.990) AS value FROM __spatial_aggregation_cte GROUP BY ts ORDER BY ts) UNION ALL SELECT * FROM (WITH __temporal_aggregation_cte AS (SELECT fingerprint, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), toIntervalSecond(300)) AS ts, `le`, sum(value) / 300 AS per_series_value FROM (SELECT reduced_fingerprint AS fingerprint, unix_milli, argMax(`sum`, computed_at) AS value FROM signoz_metrics.distributed_samples_v4_reduced_sum_60s WHERE metric_name IN (?) AND unix_milli >= ? AND unix_milli < ? GROUP BY reduced_fingerprint, unix_milli) AS points INNER JOIN (SELECT fingerprint, JSONExtractString(labels, 'le') AS `le` FROM signoz_metrics.distributed_time_series_v4_reduced WHERE metric_name IN (?) AND unix_milli >= ? AND unix_milli <= ? AND __normalized = ? GROUP BY fingerprint, `le`) AS filtered_time_series ON points.fingerprint = filtered_time_series.fingerprint GROUP BY fingerprint, ts, `le`), __spatial_aggregation_cte AS (SELECT ts, `le`, sum(per_series_value) AS value FROM __temporal_aggregation_cte GROUP BY ts, `le`) SELECT ts, histogramQuantile(arrayMap(x -> toFloat64(x), groupArray(le)), groupArray(value), 0.990) AS value FROM __spatial_aggregation_cte GROUP BY ts ORDER BY ts) ORDER BY ts",
Args: []any{"test.metric", uint64(1746921600000), uint64(1747172760000), "cumulative", false, "test.metric", uint64(1746999900000), uint64(1747172760000), 0, "test.metric", uint64(1746999900000), uint64(1747172760000), "test.metric", uint64(1746999900000), uint64(1747172760000), false},
},
},
{
name: "summary_avg",
query: reducedQuery("test.metric", metrictypes.SummaryType, metrictypes.Unspecified, metrictypes.TimeAggregationAvg, metrictypes.SpaceAggregationAvg),
expected: qbtypes.Statement{
Query: "SELECT * FROM (WITH __temporal_aggregation_cte AS (SELECT fingerprint, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), toIntervalSecond(300)) AS ts, sum(sum) / sum(count) AS per_series_value FROM signoz_metrics.distributed_samples_v4_agg_5m AS points INNER JOIN (SELECT fingerprint FROM signoz_metrics.time_series_v4_1day WHERE metric_name IN (?) AND unix_milli >= ? AND unix_milli <= ? AND LOWER(temporality) LIKE LOWER(?) AND __normalized = ? GROUP BY fingerprint) AS filtered_time_series ON points.fingerprint = filtered_time_series.fingerprint WHERE metric_name IN (?) AND unix_milli >= ? AND unix_milli < ? GROUP BY fingerprint, ts ORDER BY fingerprint, ts), __spatial_aggregation_cte AS (SELECT ts, avg(per_series_value) AS value FROM __temporal_aggregation_cte WHERE isNaN(per_series_value) = ? GROUP BY ts) SELECT * FROM __spatial_aggregation_cte ORDER BY ts) UNION ALL SELECT * FROM (WITH __temporal_aggregation_cte AS (SELECT fingerprint, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), toIntervalSecond(300)) AS ts, avg(value) AS per_series_value, avg(weight) AS per_series_weight FROM (SELECT reduced_fingerprint AS fingerprint, unix_milli, argMax(`sum_last`, computed_at) AS value, argMax(`count_series`, computed_at) AS weight FROM signoz_metrics.distributed_samples_v4_reduced_last_60s WHERE metric_name IN (?) AND unix_milli >= ? AND unix_milli < ? GROUP BY reduced_fingerprint, unix_milli) AS points INNER JOIN (SELECT fingerprint FROM signoz_metrics.distributed_time_series_v4_reduced WHERE metric_name IN (?) AND unix_milli >= ? AND unix_milli <= ? AND __normalized = ? GROUP BY fingerprint) AS filtered_time_series ON points.fingerprint = filtered_time_series.fingerprint GROUP BY fingerprint, ts), __spatial_aggregation_cte AS (SELECT ts, sum(per_series_value) / sum(per_series_weight) AS value FROM __temporal_aggregation_cte GROUP BY ts) SELECT * FROM __spatial_aggregation_cte ORDER BY ts) ORDER BY ts",
Args: []any{"test.metric", uint64(1746921600000), uint64(1747172760000), "unspecified", false, "test.metric", uint64(1746999900000), uint64(1747172760000), 0, "test.metric", uint64(1746999900000), uint64(1747172760000), "test.metric", uint64(1746999900000), uint64(1747172760000), false},
},
},
}
fm := NewFieldMapper()
cb := NewConditionBuilder(fm)
fl, err := flagger.New(context.Background(), instrumentationtest.New().ToProviderSettings(), flagger.Config{}, flagger.MustNewRegistry())
require.NoError(t, err)
sb := NewMetricQueryStatementBuilder(instrumentationtest.New().ToProviderSettings(), telemetrytypestest.NewMockMetadataStore(), fm, cb, fl)
const start, end = uint64(1747000000000), uint64(1747172800000)
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
got, err := sb.Build(context.Background(), start, end, qbtypes.RequestTypeTimeSeries, c.query, nil)
require.NoError(t, err)
require.Equal(t, c.expected.Query, got.Query)
require.Equal(t, c.expected.Args, got.Args)
})
}
t.Run("buffer_recent_window", func(t *testing.T) {
now := time.Now().UnixMilli()
q := reducedQuery("test.metric", metrictypes.GaugeType, metrictypes.Unspecified, metrictypes.TimeAggregationLatest, metrictypes.SpaceAggregationSum)
got, err := sb.Build(context.Background(), uint64(now-2*time.Hour.Milliseconds()), uint64(now), qbtypes.RequestTypeTimeSeries, q, nil)
require.NoError(t, err)
require.Contains(t, got.Query, "signoz_metrics.distributed_samples_v4_buffer")
require.Contains(t, got.Query, "signoz_metrics.time_series_v4_buffer")
require.Contains(t, got.Query, "is_reduced")
require.NotContains(t, got.Query, "UNION ALL")
})
t.Run("not_reduced", func(t *testing.T) {
q := reducedQuery("test.metric", metrictypes.GaugeType, metrictypes.Unspecified, metrictypes.TimeAggregationLatest, metrictypes.SpaceAggregationSum)
q.Aggregations[0].Reduced = false
got, err := sb.Build(context.Background(), start, end, qbtypes.RequestTypeTimeSeries, q, nil)
require.NoError(t, err)
require.NotContains(t, got.Query, "UNION ALL")
require.NotContains(t, got.Query, "reduced")
require.NotContains(t, got.Query, "buffer")
})
}

View File

@@ -4,6 +4,7 @@ import (
"context"
"fmt"
"log/slog"
"time"
"github.com/SigNoz/signoz/pkg/factory"
"github.com/SigNoz/signoz/pkg/flagger"
@@ -180,19 +181,30 @@ func (b *MetricQueryStatementBuilder) buildPipelineStatement(
query.Aggregations[0].SpaceAggregation = metrictypes.SpaceAggregationSum
}
agg := query.Aggregations[0]
// A reduced metric reads the raw buffer for recent short windows, and
// samples_v4/agg (unioned with the reduced tables) otherwise. The buffer is
// shaped exactly like samples_v4 / time_series_v4, so once the table names are
// chosen the rest of the pipeline is unchanged.
useBuffer := agg.Reduced &&
end-start < oneDayInMilliseconds &&
start >= uint64(time.Now().UnixMilli())-oneDayInMilliseconds
samplesTable, _ := WhichSamplesTableToUse(start, end, agg.Type, agg.TimeAggregation, useBuffer, agg.TableHints)
tsStart, tsEnd, _, tsTable := WhichTSTableToUse(start, end, useBuffer, agg.TableHints)
var timeSeriesCTE string
var timeSeriesCTEArgs []any
var err error
// time_series_cte
// this is applicable for all the queries
if timeSeriesCTE, timeSeriesCTEArgs, err = b.buildTimeSeriesCTE(ctx, start, end, query, keys, variables); err != nil {
if timeSeriesCTE, timeSeriesCTEArgs, err = b.buildTimeSeriesCTE(ctx, tsStart, tsEnd, query, keys, variables, tsTable); err != nil {
return nil, err
}
if qbtypes.CanShortCircuitDelta(query.Aggregations[0]) {
// spatial_aggregation_cte directly for certain delta queries
if frag, args, err := b.buildTemporalAggDeltaFastPath(start, end, query, timeSeriesCTE, timeSeriesCTEArgs); err != nil {
if frag, args, err := b.buildTemporalAggDeltaFastPath(start, end, query, samplesTable, timeSeriesCTE, timeSeriesCTEArgs); err != nil {
return nil, err
} else if frag != "" {
cteFragments = append(cteFragments, frag)
@@ -200,7 +212,7 @@ func (b *MetricQueryStatementBuilder) buildPipelineStatement(
}
} else {
// temporal_aggregation_cte
if frag, args, err := b.buildTemporalAggregationCTE(ctx, start, end, query, keys, timeSeriesCTE, timeSeriesCTEArgs); err != nil {
if frag, args, err := b.buildTemporalAggregationCTE(ctx, start, end, query, keys, samplesTable, timeSeriesCTE, timeSeriesCTEArgs); err != nil {
return nil, err
} else if frag != "" {
cteFragments = append(cteFragments, frag)
@@ -214,18 +226,188 @@ func (b *MetricQueryStatementBuilder) buildPipelineStatement(
}
}
var reducedFragments []string
var reducedArgs [][]any
if agg.Reduced && !useBuffer {
var tsCTE string
var tsArgs []any
if tsCTE, tsArgs, err = b.buildReducedTimeSeriesCTE(ctx, start, end, query, keys, variables); err != nil {
return nil, err
}
if temporalFrag, temporalArgs, ok := b.buildReducedTemporalAggregationCTE(start, end, query, tsCTE, tsArgs); ok {
spatialFrag, spatialArgs := b.buildReducedSpatialAggregationCTE(query)
reducedFragments = []string{temporalFrag, spatialFrag}
reducedArgs = [][]any{temporalArgs, spatialArgs}
}
}
// reset the query to the original state
query.Aggregations[0].SpaceAggregation = origSpaceAgg
query.Aggregations[0].TimeAggregation = origTimeAgg
query.GroupBy = origGroupBy
// final SELECT
return b.BuildFinalSelect(cteFragments, cteArgs, query)
mainStmt, err := b.BuildFinalSelect(cteFragments, cteArgs, query)
if err != nil {
return nil, err
}
if reducedFragments == nil {
return mainStmt, nil
}
reducedStmt, err := b.BuildFinalSelect(reducedFragments, reducedArgs, query)
if err != nil {
return nil, err
}
return unionStatements(mainStmt, reducedStmt, query)
}
func unionStatements(main, reduced *qbtypes.Statement, query qbtypes.QueryBuilderQuery[qbtypes.MetricAggregation]) (*qbtypes.Statement, error) {
orderBy := "ts"
for _, g := range query.GroupBy {
orderBy = fmt.Sprintf("`%s`, ", g.Name) + orderBy
}
q := fmt.Sprintf("SELECT * FROM (%s) UNION ALL SELECT * FROM (%s) ORDER BY %s", main.Query, reduced.Query, orderBy)
args := append(append([]any{}, main.Args...), reduced.Args...)
warnings := append(append([]string{}, main.Warnings...), reduced.Warnings...)
return &qbtypes.Statement{Query: q, Args: args, Warnings: warnings}, nil
}
func (b *MetricQueryStatementBuilder) buildReducedTimeSeriesCTE(
ctx context.Context,
start, end uint64,
query qbtypes.QueryBuilderQuery[qbtypes.MetricAggregation],
keys map[string][]*telemetrytypes.TelemetryFieldKey,
variables map[string]qbtypes.VariableItem,
) (string, []any, error) {
sb := sqlbuilder.NewSelectBuilder()
var preparedWhereClause querybuilder.PreparedWhereClause
var err error
if query.Filter != nil && query.Filter.Expression != "" {
preparedWhereClause, err = querybuilder.PrepareWhereClause(query.Filter.Expression, querybuilder.FilterExprVisitorOpts{
Context: ctx,
Logger: b.logger,
FieldMapper: b.fm,
ConditionBuilder: b.cb,
FieldKeys: keys,
FullTextColumn: &telemetrytypes.TelemetryFieldKey{Name: "labels"},
Variables: variables,
StartNs: start,
EndNs: end,
})
if err != nil {
return "", nil, err
}
}
sb.From(fmt.Sprintf("%s.%s", DBName, TimeseriesV4ReducedTableName))
sb.Select("fingerprint")
for _, g := range query.GroupBy {
col, err := b.fm.ColumnExpressionFor(ctx, start, end, &g.TelemetryFieldKey, keys)
if err != nil {
return "", nil, err
}
sb.SelectMore(col)
}
sb.Where(
sb.In("metric_name", query.Aggregations[0].MetricName),
sb.GTE("unix_milli", start),
sb.LTE("unix_milli", end),
sb.EQ("__normalized", false),
)
if !preparedWhereClause.IsEmpty() {
sb.AddWhereClause(preparedWhereClause.WhereClause)
}
sb.GroupBy("fingerprint")
sb.GroupBy(querybuilder.GroupByKeys(query.GroupBy)...)
q, args := sb.BuildWithFlavor(sqlbuilder.ClickHouse)
return fmt.Sprintf("(%s) AS filtered_time_series", q), args, nil
}
func (b *MetricQueryStatementBuilder) buildReducedTemporalAggregationCTE(
start, end uint64,
query qbtypes.QueryBuilderQuery[qbtypes.MetricAggregation],
timeSeriesCTE string,
timeSeriesCTEArgs []any,
) (string, []any, bool) {
agg := query.Aggregations[0]
stepSec := int64(query.StepInterval.Seconds())
value, weight, ok := ReducedValueColumn(agg.Type, agg.SpaceAggregation)
if !ok {
return "", nil, false
}
// dedup recomputed buckets: latest computed_at wins per (series, 60s bucket)
dedup := sqlbuilder.NewSelectBuilder()
dedup.Select("reduced_fingerprint AS fingerprint", "unix_milli")
dedup.SelectMore(fmt.Sprintf("argMax(%s, computed_at) AS value", value))
if weight != "" {
dedup.SelectMore(fmt.Sprintf("argMax(%s, computed_at) AS weight", weight))
}
dedup.From(fmt.Sprintf("%s.%s", DBName, WhichReducedSamplesTableToUse(agg.Type)))
dedup.Where(
dedup.In("metric_name", agg.MetricName),
dedup.GTE("unix_milli", start),
dedup.LT("unix_milli", end),
)
dedup.GroupBy("reduced_fingerprint", "unix_milli")
dedupQuery, dedupArgs := dedup.BuildWithFlavor(sqlbuilder.ClickHouse)
sb := sqlbuilder.NewSelectBuilder()
sb.Select("fingerprint")
sb.SelectMore(fmt.Sprintf("toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), toIntervalSecond(%d)) AS ts", stepSec))
for _, g := range query.GroupBy {
sb.SelectMore(fmt.Sprintf("`%s`", g.Name))
}
sb.SelectMore(fmt.Sprintf("%s AS per_series_value", ReducedTimeAggregationColumn(agg.TimeAggregation, stepSec)))
if weight != "" {
// count_series is a series count, not additive over time, so the avg
// denominator is reduced with avg
sb.SelectMore("avg(weight) AS per_series_weight")
}
sb.From(fmt.Sprintf("(%s) AS points", dedupQuery))
sb.JoinWithOption(sqlbuilder.InnerJoin, timeSeriesCTE, "points.fingerprint = filtered_time_series.fingerprint")
sb.GroupBy("fingerprint", "ts")
sb.GroupBy(querybuilder.GroupByKeys(query.GroupBy)...)
initArgs := append(append([]any{}, dedupArgs...), timeSeriesCTEArgs...)
q, args := sb.BuildWithFlavor(sqlbuilder.ClickHouse, initArgs...)
return fmt.Sprintf("__temporal_aggregation_cte AS (%s)", q), args, true
}
func (b *MetricQueryStatementBuilder) buildReducedSpatialAggregationCTE(
query qbtypes.QueryBuilderQuery[qbtypes.MetricAggregation],
) (string, []any) {
spatial := "sum(per_series_value)"
switch query.Aggregations[0].SpaceAggregation {
case metrictypes.SpaceAggregationAvg:
spatial = "sum(per_series_value) / sum(per_series_weight)"
case metrictypes.SpaceAggregationMin:
spatial = "min(per_series_value)"
case metrictypes.SpaceAggregationMax:
spatial = "max(per_series_value)"
}
sb := sqlbuilder.NewSelectBuilder()
sb.Select("ts")
for _, g := range query.GroupBy {
sb.SelectMore(fmt.Sprintf("`%s`", g.Name))
}
sb.SelectMore(spatial + " AS value")
sb.From("__temporal_aggregation_cte")
sb.GroupBy("ts")
sb.GroupBy(querybuilder.GroupByKeys(query.GroupBy)...)
q, args := sb.BuildWithFlavor(sqlbuilder.ClickHouse)
return fmt.Sprintf("__spatial_aggregation_cte AS (%s)", q), args
}
func (b *MetricQueryStatementBuilder) buildTemporalAggDeltaFastPath(
start, end uint64,
query qbtypes.QueryBuilderQuery[qbtypes.MetricAggregation],
samplesTable string,
timeSeriesCTE string,
timeSeriesCTEArgs []any,
) (string, []any, error) {
@@ -242,8 +424,7 @@ func (b *MetricQueryStatementBuilder) buildTemporalAggDeltaFastPath(
}
aggCol, err := AggregationColumnForSamplesTable(
start, end, query.Aggregations[0].Type, query.Aggregations[0].Temporality,
query.Aggregations[0].TimeAggregation, query.Aggregations[0].TableHints,
samplesTable, query.Aggregations[0].Temporality, query.Aggregations[0].TimeAggregation,
)
if err != nil {
return "", nil, err
@@ -260,8 +441,7 @@ func (b *MetricQueryStatementBuilder) buildTemporalAggDeltaFastPath(
sb.SelectMore(fmt.Sprintf("%s AS value", aggCol))
tbl, _ := WhichSamplesTableToUse(start, end, query.Aggregations[0].Type, query.Aggregations[0].TimeAggregation, query.Aggregations[0].TableHints)
sb.From(fmt.Sprintf("%s.%s AS points", DBName, tbl))
sb.From(fmt.Sprintf("%s.%s AS points", DBName, samplesTable))
sb.JoinWithOption(sqlbuilder.InnerJoin, timeSeriesCTE, "points.fingerprint = filtered_time_series.fingerprint")
sb.Where(
sb.In("metric_name", query.Aggregations[0].MetricName),
@@ -281,6 +461,7 @@ func (b *MetricQueryStatementBuilder) buildTimeSeriesCTE(
query qbtypes.QueryBuilderQuery[qbtypes.MetricAggregation],
keys map[string][]*telemetrytypes.TelemetryFieldKey,
variables map[string]qbtypes.VariableItem,
tsTable string,
) (string, []any, error) {
sb := sqlbuilder.NewSelectBuilder()
@@ -304,8 +485,7 @@ func (b *MetricQueryStatementBuilder) buildTimeSeriesCTE(
}
}
start, end, _, tbl := WhichTSTableToUse(start, end, query.Aggregations[0].TableHints)
sb.From(fmt.Sprintf("%s.%s", DBName, tbl))
sb.From(fmt.Sprintf("%s.%s", DBName, tsTable))
sb.Select("fingerprint")
for _, g := range query.GroupBy {
@@ -331,6 +511,12 @@ func (b *MetricQueryStatementBuilder) buildTimeSeriesCTE(
sb.EQ("__normalized", false),
)
// the buffer holds both raw rows and the reduced catalog rows; the raw read
// only wants the original series
if tsTable == TimeseriesV4BufferLocalTableName {
sb.Where(sb.EQ("is_reduced", false))
}
if !preparedWhereClause.IsEmpty() {
sb.AddWhereClause(preparedWhereClause.WhereClause)
}
@@ -347,21 +533,23 @@ func (b *MetricQueryStatementBuilder) buildTemporalAggregationCTE(
start, end uint64,
query qbtypes.QueryBuilderQuery[qbtypes.MetricAggregation],
_ map[string][]*telemetrytypes.TelemetryFieldKey,
samplesTable string,
timeSeriesCTE string,
timeSeriesCTEArgs []any,
) (string, []any, error) {
if query.Aggregations[0].Temporality == metrictypes.Delta {
return b.buildTemporalAggDelta(ctx, start, end, query, timeSeriesCTE, timeSeriesCTEArgs)
return b.buildTemporalAggDelta(ctx, start, end, query, samplesTable, timeSeriesCTE, timeSeriesCTEArgs)
} else if query.Aggregations[0].Temporality != metrictypes.Multiple {
return b.buildTemporalAggCumulativeOrUnspecified(ctx, start, end, query, timeSeriesCTE, timeSeriesCTEArgs)
return b.buildTemporalAggCumulativeOrUnspecified(ctx, start, end, query, samplesTable, timeSeriesCTE, timeSeriesCTEArgs)
}
return b.buildTemporalAggForMultipleTemporalities(ctx, start, end, query, timeSeriesCTE, timeSeriesCTEArgs)
return b.buildTemporalAggForMultipleTemporalities(ctx, start, end, query, samplesTable, timeSeriesCTE, timeSeriesCTEArgs)
}
func (b *MetricQueryStatementBuilder) buildTemporalAggDelta(
_ context.Context,
start, end uint64,
query qbtypes.QueryBuilderQuery[qbtypes.MetricAggregation],
samplesTable string,
timeSeriesCTE string,
timeSeriesCTEArgs []any,
) (string, []any, error) {
@@ -378,7 +566,7 @@ func (b *MetricQueryStatementBuilder) buildTemporalAggDelta(
sb.SelectMore(fmt.Sprintf("`%s`", g.Name))
}
aggCol, err := AggregationColumnForSamplesTable(start, end, query.Aggregations[0].Type, query.Aggregations[0].Temporality, query.Aggregations[0].TimeAggregation, query.Aggregations[0].TableHints)
aggCol, err := AggregationColumnForSamplesTable(samplesTable, query.Aggregations[0].Temporality, query.Aggregations[0].TimeAggregation)
if err != nil {
return "", nil, err
}
@@ -389,8 +577,7 @@ func (b *MetricQueryStatementBuilder) buildTemporalAggDelta(
sb.SelectMore(fmt.Sprintf("%s AS per_series_value", aggCol))
tbl, _ := WhichSamplesTableToUse(start, end, query.Aggregations[0].Type, query.Aggregations[0].TimeAggregation, query.Aggregations[0].TableHints)
sb.From(fmt.Sprintf("%s.%s AS points", DBName, tbl))
sb.From(fmt.Sprintf("%s.%s AS points", DBName, samplesTable))
sb.JoinWithOption(sqlbuilder.InnerJoin, timeSeriesCTE, "points.fingerprint = filtered_time_series.fingerprint")
sb.Where(
sb.In("metric_name", query.Aggregations[0].MetricName),
@@ -409,6 +596,7 @@ func (b *MetricQueryStatementBuilder) buildTemporalAggCumulativeOrUnspecified(
_ context.Context,
start, end uint64,
query qbtypes.QueryBuilderQuery[qbtypes.MetricAggregation],
samplesTable string,
timeSeriesCTE string,
timeSeriesCTEArgs []any,
) (string, []any, error) {
@@ -424,14 +612,13 @@ func (b *MetricQueryStatementBuilder) buildTemporalAggCumulativeOrUnspecified(
baseSb.SelectMore(fmt.Sprintf("`%s`", g.Name))
}
aggCol, err := AggregationColumnForSamplesTable(start, end, query.Aggregations[0].Type, query.Aggregations[0].Temporality, query.Aggregations[0].TimeAggregation, query.Aggregations[0].TableHints)
aggCol, err := AggregationColumnForSamplesTable(samplesTable, query.Aggregations[0].Temporality, query.Aggregations[0].TimeAggregation)
if err != nil {
return "", nil, err
}
baseSb.SelectMore(fmt.Sprintf("%s AS per_series_value", aggCol))
tbl, _ := WhichSamplesTableToUse(start, end, query.Aggregations[0].Type, query.Aggregations[0].TimeAggregation, query.Aggregations[0].TableHints)
baseSb.From(fmt.Sprintf("%s.%s AS points", DBName, tbl))
baseSb.From(fmt.Sprintf("%s.%s AS points", DBName, samplesTable))
baseSb.JoinWithOption(sqlbuilder.InnerJoin, timeSeriesCTE, "points.fingerprint = filtered_time_series.fingerprint")
baseSb.Where(
baseSb.In("metric_name", query.Aggregations[0].MetricName),
@@ -475,6 +662,7 @@ func (b *MetricQueryStatementBuilder) buildTemporalAggForMultipleTemporalities(
_ context.Context,
start, end uint64,
query qbtypes.QueryBuilderQuery[qbtypes.MetricAggregation],
samplesTable string,
timeSeriesCTE string,
timeSeriesCTEArgs []any,
) (string, []any, error) {
@@ -489,11 +677,11 @@ func (b *MetricQueryStatementBuilder) buildTemporalAggForMultipleTemporalities(
sb.SelectMore(fmt.Sprintf("`%s`", g.Name))
}
aggForDeltaTemporality, err := AggregationColumnForSamplesTable(start, end, query.Aggregations[0].Type, metrictypes.Delta, query.Aggregations[0].TimeAggregation, query.Aggregations[0].TableHints)
aggForDeltaTemporality, err := AggregationColumnForSamplesTable(samplesTable, metrictypes.Delta, query.Aggregations[0].TimeAggregation)
if err != nil {
return "", nil, err
}
aggForCumulativeTemporality, err := AggregationColumnForSamplesTable(start, end, query.Aggregations[0].Type, metrictypes.Cumulative, query.Aggregations[0].TimeAggregation, query.Aggregations[0].TableHints)
aggForCumulativeTemporality, err := AggregationColumnForSamplesTable(samplesTable, metrictypes.Cumulative, query.Aggregations[0].TimeAggregation)
if err != nil {
return "", nil, err
}
@@ -521,8 +709,7 @@ func (b *MetricQueryStatementBuilder) buildTemporalAggForMultipleTemporalities(
sb.SelectMore(expr)
}
tbl, _ := WhichSamplesTableToUse(start, end, query.Aggregations[0].Type, query.Aggregations[0].TimeAggregation, query.Aggregations[0].TableHints)
sb.From(fmt.Sprintf("%s.%s AS points", DBName, tbl))
sb.From(fmt.Sprintf("%s.%s AS points", DBName, samplesTable))
sb.JoinWithOption(sqlbuilder.InnerJoin, timeSeriesCTE, "points.fingerprint = filtered_time_series.fingerprint")
sb.Where(
sb.In("metric_name", query.Aggregations[0].MetricName),

View File

@@ -30,6 +30,17 @@ const (
TimeseriesV41weekLocalTableName = "time_series_v4_1week"
AttributesMetadataTableName = "distributed_metadata"
AttributesMetadataLocalTableName = "metadata"
// The buffer holds raw points for ~24h; the reduced tables hold 60s
// aggregates of dropped-label series.
SamplesV4BufferTableName = "distributed_samples_v4_buffer"
SamplesV4BufferLocalTableName = "samples_v4_buffer"
TimeseriesV4BufferTableName = "distributed_time_series_v4_buffer"
TimeseriesV4BufferLocalTableName = "time_series_v4_buffer"
SamplesV4ReducedLastTableName = "distributed_samples_v4_reduced_last_60s"
SamplesV4ReducedSumTableName = "distributed_samples_v4_reduced_sum_60s"
TimeseriesV4ReducedTableName = "distributed_time_series_v4_reduced"
TimeseriesV4ReducedLocalTableName = "time_series_v4_reduced"
)
var (
@@ -49,8 +60,16 @@ var (
// in that order.
func WhichTSTableToUse(
start, end uint64,
useBuffer bool,
tableHints *metrictypes.MetricTableHints,
) (uint64, uint64, string, string) {
// the buffer holds the recent raw window for reduced metrics and has the same
// shape as time_series_v4; round the start to the hour like the v4 table.
if useBuffer {
start = start - (start % (oneHourInMilliseconds))
return start, end, TimeseriesV4BufferTableName, TimeseriesV4BufferLocalTableName
}
// if we have a hint for the table, we need to use it
// the hint will be used to override the default table selection logic
if tableHints != nil {
@@ -149,14 +168,20 @@ func WhichSamplesTableToUse(
start, end uint64,
metricType metrictypes.Type,
timeAggregation metrictypes.TimeAggregation,
useBuffer bool,
tableHints *metrictypes.MetricTableHints,
) (string, string) {
// the buffer holds the recent raw window for reduced metrics; same shape as samples_v4
if useBuffer {
return SamplesV4BufferTableName, SamplesV4BufferLocalTableName
}
// if we have a hint for the table, we need to use it
// the hint will be used to override the default table selection logic.
// SamplesTableName is the distributed name; derive the local via switch.
if tableHints != nil && tableHints.SamplesTableName != "" {
switch tableHints.SamplesTableName {
case SamplesV4TableName:
case SamplesV4TableName, SamplesV4BufferTableName:
return SamplesV4TableName, SamplesV4LocalTableName
case SamplesV4Agg5mTableName:
return SamplesV4Agg5mTableName, SamplesV4Agg5mLocalTableName
@@ -188,13 +213,10 @@ func WhichSamplesTableToUse(
}
func AggregationColumnForSamplesTable(
start, end uint64,
metricType metrictypes.Type,
tableName string,
temporality metrictypes.Temporality,
timeAggregation metrictypes.TimeAggregation,
tableHints *metrictypes.MetricTableHints,
) (string, error) {
tableName, _ := WhichSamplesTableToUse(start, end, metricType, timeAggregation, tableHints)
var aggregationColumn string
switch temporality {
case metrictypes.Delta:
@@ -202,7 +224,7 @@ func AggregationColumnForSamplesTable(
// although it doesn't make sense to use anyLast, avg, min, max, count on delta metrics,
// we are keeping it here to make sure that query will not be invalid
switch tableName {
case SamplesV4TableName:
case SamplesV4TableName, SamplesV4BufferTableName:
switch timeAggregation {
case metrictypes.TimeAggregationLatest:
aggregationColumn = "anyLast(value)"
@@ -244,7 +266,7 @@ func AggregationColumnForSamplesTable(
// for cumulative metrics, we only support `RATE`/`INCREASE`. The max value in window is
// used to calculate the sum which is then divided by the window size to get the rate
switch tableName {
case SamplesV4TableName:
case SamplesV4TableName, SamplesV4BufferTableName:
switch timeAggregation {
case metrictypes.TimeAggregationLatest:
aggregationColumn = "anyLast(value)"
@@ -284,7 +306,7 @@ func AggregationColumnForSamplesTable(
}
case metrictypes.Unspecified:
switch tableName {
case SamplesV4TableName:
case SamplesV4TableName, SamplesV4BufferTableName:
switch timeAggregation {
case metrictypes.TimeAggregationLatest:
aggregationColumn = "anyLast(value)"
@@ -332,6 +354,65 @@ func AggregationColumnForSamplesTable(
return aggregationColumn, nil
}
// WhichReducedSamplesTableToUse returns the 60s reduced samples table for a metric
// type: the last_60s table for gauge-like series, the sum_60s table for counters
// and histograms.
func WhichReducedSamplesTableToUse(metricType metrictypes.Type) string {
if metricType == metrictypes.SumType || metricType == metrictypes.HistogramType {
return SamplesV4ReducedSumTableName
}
return SamplesV4ReducedLastTableName
}
// ReducedValueColumn returns the reduced value column (and the avg-denominator
// weight) for a space aggregation. The reduced columns are pre-aggregated across
// the original series, so the space aggregation picks the underlying value; the
// sum table only has `sum`, so min/max across series have no column (ok=false).
func ReducedValueColumn(metricType metrictypes.Type, space metrictypes.SpaceAggregation) (value, weight string, ok bool) {
if metricType == metrictypes.SumType || metricType == metrictypes.HistogramType {
switch space {
case metrictypes.SpaceAggregationSum:
return "`sum`", "", true
case metrictypes.SpaceAggregationAvg:
return "`sum`", "`count_series`", true
}
return "", "", false
}
switch space {
case metrictypes.SpaceAggregationSum:
return "`sum_last`", "", true
case metrictypes.SpaceAggregationAvg:
return "`sum_last`", "`count_series`", true
case metrictypes.SpaceAggregationMin:
return "`min`", "", true
case metrictypes.SpaceAggregationMax:
return "`max`", "", true
}
return "", "", false
}
// ReducedTimeAggregationColumn applies the time aggregation to the reduced `value`
// column over the step's 60s buckets. latest uses argMax over the bucket timestamp
// (the buckets have no read order); rate divides the per-step sum by the step.
func ReducedTimeAggregationColumn(timeAggregation metrictypes.TimeAggregation, stepSec int64) string {
switch timeAggregation {
case metrictypes.TimeAggregationLatest:
return "argMax(value, unix_milli)"
case metrictypes.TimeAggregationAvg:
return "avg(value)"
case metrictypes.TimeAggregationMin:
return "min(value)"
case metrictypes.TimeAggregationMax:
return "max(value)"
case metrictypes.TimeAggregationCount:
return "count(value)"
case metrictypes.TimeAggregationRate:
return fmt.Sprintf("sum(value) / %d", stepSec)
default: // sum, increase
return "sum(value)"
}
}
func AggregationQueryForHistogramCountWithParams(param *metrictypes.ComparisonSpaceAggregationParam) (string, error) {
if param == nil {
return "", errors.NewInvalidInputf(errors.CodeInvalidInput, "no aggregation param provided for histogram count")

View File

@@ -12,6 +12,7 @@ type Clusters struct {
Type ResponseType `json:"type" required:"true"`
Records []ClusterRecord `json:"records" required:"true" nullable:"false"`
Total int `json:"total" required:"true"`
RequiredMetricsCheck RequiredMetricsCheck `json:"requiredMetricsCheck" required:"true"`
EndTimeBeforeRetention bool `json:"endTimeBeforeRetention" required:"true"`
Warning *qbtypes.QueryWarnData `json:"warning,omitempty"`
}

View File

@@ -12,6 +12,7 @@ type DaemonSets struct {
Type ResponseType `json:"type" required:"true"`
Records []DaemonSetRecord `json:"records" required:"true" nullable:"false"`
Total int `json:"total" required:"true"`
RequiredMetricsCheck RequiredMetricsCheck `json:"requiredMetricsCheck" required:"true"`
EndTimeBeforeRetention bool `json:"endTimeBeforeRetention" required:"true"`
Warning *qbtypes.QueryWarnData `json:"warning,omitempty"`
}

View File

@@ -12,6 +12,7 @@ type Deployments struct {
Type ResponseType `json:"type" required:"true"`
Records []DeploymentRecord `json:"records" required:"true" nullable:"false"`
Total int `json:"total" required:"true"`
RequiredMetricsCheck RequiredMetricsCheck `json:"requiredMetricsCheck" required:"true"`
EndTimeBeforeRetention bool `json:"endTimeBeforeRetention" required:"true"`
Warning *qbtypes.QueryWarnData `json:"warning,omitempty"`
}

View File

@@ -12,6 +12,7 @@ type Hosts struct {
Type ResponseType `json:"type" required:"true"`
Records []HostRecord `json:"records" required:"true" nullable:"false"`
Total int `json:"total" required:"true"`
RequiredMetricsCheck RequiredMetricsCheck `json:"requiredMetricsCheck" required:"true"`
EndTimeBeforeRetention bool `json:"endTimeBeforeRetention" required:"true"`
Warning *qbtypes.QueryWarnData `json:"warning,omitempty"`
}
@@ -29,6 +30,10 @@ type HostRecord struct {
Meta map[string]string `json:"meta" required:"true"`
}
type RequiredMetricsCheck struct {
MissingMetrics []string `json:"missingMetrics" required:"true"`
}
type PostableHosts struct {
Start int64 `json:"start" required:"true"`
End int64 `json:"end" required:"true"`

View File

@@ -12,6 +12,7 @@ type Jobs struct {
Type ResponseType `json:"type" required:"true"`
Records []JobRecord `json:"records" required:"true" nullable:"false"`
Total int `json:"total" required:"true"`
RequiredMetricsCheck RequiredMetricsCheck `json:"requiredMetricsCheck" required:"true"`
EndTimeBeforeRetention bool `json:"endTimeBeforeRetention" required:"true"`
Warning *qbtypes.QueryWarnData `json:"warning,omitempty"`
}

View File

@@ -12,6 +12,7 @@ type Namespaces struct {
Type ResponseType `json:"type" required:"true"`
Records []NamespaceRecord `json:"records" required:"true" nullable:"false"`
Total int `json:"total" required:"true"`
RequiredMetricsCheck RequiredMetricsCheck `json:"requiredMetricsCheck" required:"true"`
EndTimeBeforeRetention bool `json:"endTimeBeforeRetention" required:"true"`
Warning *qbtypes.QueryWarnData `json:"warning,omitempty"`
}

View File

@@ -12,6 +12,7 @@ type Nodes struct {
Type ResponseType `json:"type" required:"true"`
Records []NodeRecord `json:"records" required:"true" nullable:"false"`
Total int `json:"total" required:"true"`
RequiredMetricsCheck RequiredMetricsCheck `json:"requiredMetricsCheck" required:"true"`
EndTimeBeforeRetention bool `json:"endTimeBeforeRetention" required:"true"`
Warning *qbtypes.QueryWarnData `json:"warning,omitempty"`
}

View File

@@ -12,6 +12,7 @@ type Pods struct {
Type ResponseType `json:"type" required:"true"`
Records []PodRecord `json:"records" required:"true" nullable:"false"`
Total int `json:"total" required:"true"`
RequiredMetricsCheck RequiredMetricsCheck `json:"requiredMetricsCheck" required:"true"`
EndTimeBeforeRetention bool `json:"endTimeBeforeRetention" required:"true"`
Warning *qbtypes.QueryWarnData `json:"warning,omitempty"`
}

View File

@@ -12,6 +12,7 @@ type StatefulSets struct {
Type ResponseType `json:"type" required:"true"`
Records []StatefulSetRecord `json:"records" required:"true" nullable:"false"`
Total int `json:"total" required:"true"`
RequiredMetricsCheck RequiredMetricsCheck `json:"requiredMetricsCheck" required:"true"`
EndTimeBeforeRetention bool `json:"endTimeBeforeRetention" required:"true"`
Warning *qbtypes.QueryWarnData `json:"warning,omitempty"`
}

View File

@@ -12,6 +12,7 @@ type Volumes struct {
Type ResponseType `json:"type" required:"true"`
Records []VolumeRecord `json:"records" required:"true" nullable:"false"`
Total int `json:"total" required:"true"`
RequiredMetricsCheck RequiredMetricsCheck `json:"requiredMetricsCheck" required:"true"`
EndTimeBeforeRetention bool `json:"endTimeBeforeRetention" required:"true"`
Warning *qbtypes.QueryWarnData `json:"warning,omitempty"`
}

View File

@@ -480,7 +480,9 @@ type MetricAggregation struct {
// value filter to apply to the query
ValueFilter *metrictypes.MetricValueFilter `json:"-"`
// reduce to operator for metric scalar requests
ReduceTo ReduceTo `json:"reduceTo,omitempty"`
ReduceTo ReduceTo `json:"reduceTo,omitzero"`
Reduced bool `json:"-"`
}
// Copy creates a deep copy of MetricAggregation.

View File

@@ -4,6 +4,7 @@ import (
"context"
"github.com/SigNoz/signoz/pkg/types/metrictypes"
"github.com/SigNoz/signoz/pkg/valuer"
)
// MetadataStore is the interface for the telemetry metadata store.
@@ -26,12 +27,12 @@ type MetadataStore interface {
GetAllValues(ctx context.Context, fieldValueSelector *FieldValueSelector) (*TelemetryFieldValues, bool, error)
// FetchTemporality fetches the temporality for metric
FetchTemporality(ctx context.Context, queryTimeRangeStartTs, queryTimeRangeEndTs uint64, metricName string) (metrictypes.Temporality, error)
FetchTemporality(ctx context.Context, orgID valuer.UUID, queryTimeRangeStartTs, queryTimeRangeEndTs uint64, metricName string) (metrictypes.Temporality, error)
// FetchTemporalityMulti fetches the temporality for multiple metrics
FetchTemporalityMulti(ctx context.Context, queryTimeRangeStartTs, queryTimeRangeEndTs uint64, metricNames ...string) (map[string]metrictypes.Temporality, error)
FetchTemporalityMulti(ctx context.Context, orgID valuer.UUID, queryTimeRangeStartTs, queryTimeRangeEndTs uint64, metricNames ...string) (map[string]metrictypes.Temporality, error)
FetchTemporalityAndTypeMulti(ctx context.Context, queryTimeRangeStartTs, queryTimeRangeEndTs uint64, metricNames ...string) (map[string]metrictypes.Temporality, map[string]metrictypes.Type, error)
FetchTemporalityAndTypeMulti(ctx context.Context, orgID valuer.UUID, queryTimeRangeStartTs, queryTimeRangeEndTs uint64, metricNames ...string) (map[string]metrictypes.Temporality, map[string]metrictypes.Type, map[string]bool, error)
// ListLogsJSONIndexes lists the JSON indexes for the logs table.
ListLogsJSONIndexes(ctx context.Context, filters ...string) ([]TelemetryFieldKeySkipIndex, error)

View File

@@ -6,6 +6,7 @@ import (
"github.com/SigNoz/signoz/pkg/types/metrictypes"
"github.com/SigNoz/signoz/pkg/types/telemetrytypes"
"github.com/SigNoz/signoz/pkg/valuer"
)
// MockMetadataStore implements the MetadataStore interface for testing purposes.
@@ -16,6 +17,7 @@ type MockMetadataStore struct {
AllValuesMap map[string]*telemetrytypes.TelemetryFieldValues
TemporalityMap map[string]metrictypes.Temporality
TypeMap map[string]metrictypes.Type
ReducedMap map[string]bool
PromotedPathsMap map[string]bool
LogsJSONIndexes []telemetrytypes.TelemetryFieldKeySkipIndex
ColumnEvolutionMetadataMap map[string][]*telemetrytypes.EvolutionEntry
@@ -306,7 +308,7 @@ func (m *MockMetadataStore) SetAllValues(lookupKey string, values *telemetrytype
}
// FetchTemporality fetches the temporality for a metric.
func (m *MockMetadataStore) FetchTemporality(ctx context.Context, queryTimeRangeStartTs, queryTimeRangeEndTs uint64, metricName string) (metrictypes.Temporality, error) {
func (m *MockMetadataStore) FetchTemporality(ctx context.Context, orgID valuer.UUID, queryTimeRangeStartTs, queryTimeRangeEndTs uint64, metricName string) (metrictypes.Temporality, error) {
if temporality, exists := m.TemporalityMap[metricName]; exists {
return temporality, nil
}
@@ -314,7 +316,7 @@ func (m *MockMetadataStore) FetchTemporality(ctx context.Context, queryTimeRange
}
// FetchTemporalityMulti fetches the temporality for multiple metrics.
func (m *MockMetadataStore) FetchTemporalityMulti(ctx context.Context, queryTimeRangeStartTs, queryTimeRangeEndTs uint64, metricNames ...string) (map[string]metrictypes.Temporality, error) {
func (m *MockMetadataStore) FetchTemporalityMulti(ctx context.Context, orgID valuer.UUID, queryTimeRangeStartTs, queryTimeRangeEndTs uint64, metricNames ...string) (map[string]metrictypes.Temporality, error) {
result := make(map[string]metrictypes.Temporality)
for _, metricName := range metricNames {
@@ -329,9 +331,10 @@ func (m *MockMetadataStore) FetchTemporalityMulti(ctx context.Context, queryTime
}
// FetchTemporalityMulti fetches the temporality for multiple metrics.
func (m *MockMetadataStore) FetchTemporalityAndTypeMulti(ctx context.Context, queryTimeRangeStartTs, queryTimeRangeEndTs uint64, metricNames ...string) (map[string]metrictypes.Temporality, map[string]metrictypes.Type, error) {
func (m *MockMetadataStore) FetchTemporalityAndTypeMulti(ctx context.Context, orgID valuer.UUID, queryTimeRangeStartTs, queryTimeRangeEndTs uint64, metricNames ...string) (map[string]metrictypes.Temporality, map[string]metrictypes.Type, map[string]bool, error) {
temporalities := make(map[string]metrictypes.Temporality)
types := make(map[string]metrictypes.Type)
reduced := make(map[string]bool)
for _, metricName := range metricNames {
if temporality, exists := m.TemporalityMap[metricName]; exists {
@@ -344,9 +347,12 @@ func (m *MockMetadataStore) FetchTemporalityAndTypeMulti(ctx context.Context, qu
} else {
types[metricName] = metrictypes.UnspecifiedType
}
if m.ReducedMap[metricName] {
reduced[metricName] = true
}
}
return temporalities, types, nil
return temporalities, types, reduced, nil
}
// SetTemporality sets the temporality for a metric in the mock store.

View File

@@ -1,36 +0,0 @@
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "acc-c1-n1", "k8s.node.uid": "acc-c1-n1-uid", "k8s.cluster.name": "kp-cluster", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "acc-c1-n1", "k8s.node.uid": "acc-c1-n1-uid", "k8s.cluster.name": "kp-cluster", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "acc-c1-n1", "k8s.node.uid": "acc-c1-n1-uid", "k8s.cluster.name": "kp-cluster", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "acc-c1-n1", "k8s.node.uid": "acc-c1-n1-uid", "k8s.cluster.name": "kp-cluster"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "acc-c1-n1", "k8s.node.uid": "acc-c1-n1-uid", "k8s.cluster.name": "kp-cluster"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "acc-c1-n1", "k8s.node.uid": "acc-c1-n1-uid", "k8s.cluster.name": "kp-cluster"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "acc-c1-n1", "k8s.node.uid": "acc-c1-n1-uid", "k8s.cluster.name": "kp-cluster"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "acc-c1-n1", "k8s.node.uid": "acc-c1-n1-uid", "k8s.cluster.name": "kp-cluster"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "acc-c1-n1", "k8s.node.uid": "acc-c1-n1-uid", "k8s.cluster.name": "kp-cluster"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "acc-c1-n1", "k8s.node.uid": "acc-c1-n1-uid", "k8s.cluster.name": "kp-cluster"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "acc-c1-n1", "k8s.node.uid": "acc-c1-n1-uid", "k8s.cluster.name": "kp-cluster"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "acc-c1-n1", "k8s.node.uid": "acc-c1-n1-uid", "k8s.cluster.name": "kp-cluster"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "acc-c1-n1", "k8s.node.uid": "acc-c1-n1-uid", "k8s.cluster.name": "kp-cluster"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "acc-c1-n1", "k8s.node.uid": "acc-c1-n1-uid", "k8s.cluster.name": "kp-cluster"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "acc-c1-n1", "k8s.node.uid": "acc-c1-n1-uid", "k8s.cluster.name": "kp-cluster"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "acc-c1-n1-p-uid", "k8s.pod.name": "acc-c1-n1-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "acc-c1-n1", "k8s.cluster.name": "kp-cluster"}, "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-c1-n1-p-uid", "k8s.pod.name": "acc-c1-n1-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "acc-c1-n1", "k8s.cluster.name": "kp-cluster"}, "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-c1-n1-p-uid", "k8s.pod.name": "acc-c1-n1-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "acc-c1-n1", "k8s.cluster.name": "kp-cluster"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "acc-c1-n2", "k8s.node.uid": "acc-c1-n2-uid", "k8s.cluster.name": "kp-cluster", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "acc-c1-n2", "k8s.node.uid": "acc-c1-n2-uid", "k8s.cluster.name": "kp-cluster", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "acc-c1-n2", "k8s.node.uid": "acc-c1-n2-uid", "k8s.cluster.name": "kp-cluster", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "acc-c1-n2", "k8s.node.uid": "acc-c1-n2-uid", "k8s.cluster.name": "kp-cluster"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "acc-c1-n2", "k8s.node.uid": "acc-c1-n2-uid", "k8s.cluster.name": "kp-cluster"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "acc-c1-n2", "k8s.node.uid": "acc-c1-n2-uid", "k8s.cluster.name": "kp-cluster"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "acc-c1-n2", "k8s.node.uid": "acc-c1-n2-uid", "k8s.cluster.name": "kp-cluster"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "acc-c1-n2", "k8s.node.uid": "acc-c1-n2-uid", "k8s.cluster.name": "kp-cluster"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "acc-c1-n2", "k8s.node.uid": "acc-c1-n2-uid", "k8s.cluster.name": "kp-cluster"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "acc-c1-n2", "k8s.node.uid": "acc-c1-n2-uid", "k8s.cluster.name": "kp-cluster"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "acc-c1-n2", "k8s.node.uid": "acc-c1-n2-uid", "k8s.cluster.name": "kp-cluster"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "acc-c1-n2", "k8s.node.uid": "acc-c1-n2-uid", "k8s.cluster.name": "kp-cluster"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "acc-c1-n2", "k8s.node.uid": "acc-c1-n2-uid", "k8s.cluster.name": "kp-cluster"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "acc-c1-n2", "k8s.node.uid": "acc-c1-n2-uid", "k8s.cluster.name": "kp-cluster"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "acc-c1-n2", "k8s.node.uid": "acc-c1-n2-uid", "k8s.cluster.name": "kp-cluster"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "acc-c1-n2-p-uid", "k8s.pod.name": "acc-c1-n2-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "acc-c1-n2", "k8s.cluster.name": "kp-cluster"}, "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-c1-n2-p-uid", "k8s.pod.name": "acc-c1-n2-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "acc-c1-n2", "k8s.cluster.name": "kp-cluster"}, "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-c1-n2-p-uid", "k8s.pod.name": "acc-c1-n2-p", "k8s.namespace.name": "ns-x", "k8s.node.name": "acc-c1-n2", "k8s.cluster.name": "kp-cluster"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}

View File

@@ -1,48 +0,0 @@
{"metric_name": "k8s.pod.cpu.usage", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.node.name": "node-a", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.4, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu.usage", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.node.name": "node-a", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.4, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu.usage", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.node.name": "node-a", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.4, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_request_utilization", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.node.name": "node-a", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.4, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_request_utilization", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.node.name": "node-a", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.4, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_request_utilization", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.node.name": "node-a", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.4, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_limit_utilization", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.node.name": "node-a", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.3, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_limit_utilization", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.node.name": "node-a", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.3, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_limit_utilization", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.node.name": "node-a", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.3, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory.working_set", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.node.name": "node-a", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 100000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory.working_set", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.node.name": "node-a", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 100000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory.working_set", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.node.name": "node-a", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 100000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_request_utilization", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.node.name": "node-a", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.4, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_request_utilization", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.node.name": "node-a", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.4, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_request_utilization", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.node.name": "node-a", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.4, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_limit_utilization", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.node.name": "node-a", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.3, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_limit_utilization", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.node.name": "node-a", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.3, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_limit_utilization", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.node.name": "node-a", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.3, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.node.name": "node-a", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "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-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.node.name": "node-a", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "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-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.node.name": "node-a", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu.usage", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.node.name": "node-b", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu.usage", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.node.name": "node-b", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu.usage", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.node.name": "node-b", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_request_utilization", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.node.name": "node-b", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_request_utilization", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.node.name": "node-b", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_request_utilization", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.node.name": "node-b", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_limit_utilization", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.node.name": "node-b", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_limit_utilization", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.node.name": "node-b", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_limit_utilization", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.node.name": "node-b", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory.working_set", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.node.name": "node-b", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 200000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory.working_set", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.node.name": "node-b", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 200000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory.working_set", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.node.name": "node-b", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 200000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_request_utilization", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.node.name": "node-b", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_request_utilization", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.node.name": "node-b", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_request_utilization", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.node.name": "node-b", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_limit_utilization", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.node.name": "node-b", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_limit_utilization", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.node.name": "node-b", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_limit_utilization", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.node.name": "node-b", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.node.name": "node-b", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "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-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.node.name": "node-b", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "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-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.node.name": "node-b", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.daemonset.desired_scheduled_nodes", "labels": {"k8s.daemonset.name": "kp-ds", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 3, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.daemonset.current_scheduled_nodes", "labels": {"k8s.daemonset.name": "kp-ds", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.daemonset.desired_scheduled_nodes", "labels": {"k8s.daemonset.name": "kp-ds", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 3, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.daemonset.current_scheduled_nodes", "labels": {"k8s.daemonset.name": "kp-ds", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.daemonset.desired_scheduled_nodes", "labels": {"k8s.daemonset.name": "kp-ds", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 3, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.daemonset.current_scheduled_nodes", "labels": {"k8s.daemonset.name": "kp-ds", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}

View File

@@ -1,48 +0,0 @@
{"metric_name": "k8s.pod.cpu.usage", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.deployment.name": "kp-dep", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.4, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu.usage", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.deployment.name": "kp-dep", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.4, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu.usage", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.deployment.name": "kp-dep", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.4, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_request_utilization", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.deployment.name": "kp-dep", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.4, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_request_utilization", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.deployment.name": "kp-dep", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.4, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_request_utilization", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.deployment.name": "kp-dep", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.4, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_limit_utilization", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.deployment.name": "kp-dep", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.3, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_limit_utilization", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.deployment.name": "kp-dep", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.3, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_limit_utilization", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.deployment.name": "kp-dep", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.3, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory.working_set", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.deployment.name": "kp-dep", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 100000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory.working_set", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.deployment.name": "kp-dep", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 100000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory.working_set", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.deployment.name": "kp-dep", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 100000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_request_utilization", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.deployment.name": "kp-dep", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.4, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_request_utilization", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.deployment.name": "kp-dep", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.4, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_request_utilization", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.deployment.name": "kp-dep", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.4, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_limit_utilization", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.deployment.name": "kp-dep", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.3, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_limit_utilization", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.deployment.name": "kp-dep", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.3, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_limit_utilization", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.deployment.name": "kp-dep", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.3, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.deployment.name": "kp-dep", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "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-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.deployment.name": "kp-dep", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "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-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.deployment.name": "kp-dep", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu.usage", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.deployment.name": "kp-dep", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu.usage", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.deployment.name": "kp-dep", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu.usage", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.deployment.name": "kp-dep", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_request_utilization", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.deployment.name": "kp-dep", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_request_utilization", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.deployment.name": "kp-dep", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_request_utilization", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.deployment.name": "kp-dep", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_limit_utilization", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.deployment.name": "kp-dep", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_limit_utilization", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.deployment.name": "kp-dep", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_limit_utilization", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.deployment.name": "kp-dep", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory.working_set", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.deployment.name": "kp-dep", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 200000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory.working_set", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.deployment.name": "kp-dep", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 200000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory.working_set", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.deployment.name": "kp-dep", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 200000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_request_utilization", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.deployment.name": "kp-dep", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_request_utilization", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.deployment.name": "kp-dep", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_request_utilization", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.deployment.name": "kp-dep", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_limit_utilization", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.deployment.name": "kp-dep", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_limit_utilization", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.deployment.name": "kp-dep", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_limit_utilization", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.deployment.name": "kp-dep", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.deployment.name": "kp-dep", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "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-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.deployment.name": "kp-dep", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "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-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.deployment.name": "kp-dep", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.deployment.desired", "labels": {"k8s.deployment.name": "kp-dep", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 3, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.deployment.available", "labels": {"k8s.deployment.name": "kp-dep", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.deployment.desired", "labels": {"k8s.deployment.name": "kp-dep", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 3, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.deployment.available", "labels": {"k8s.deployment.name": "kp-dep", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.deployment.desired", "labels": {"k8s.deployment.name": "kp-dep", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 3, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.deployment.available", "labels": {"k8s.deployment.name": "kp-dep", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}

View File

@@ -1,36 +0,0 @@
{"metric_name": "system.cpu.time", "labels": {"host.name": "kp-h1", "os.type": "linux", "state": "user"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 100, "temporality": "Cumulative", "type_": "Sum", "is_monotonic": true}
{"metric_name": "system.cpu.time", "labels": {"host.name": "kp-h1", "os.type": "linux", "state": "user"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 200, "temporality": "Cumulative", "type_": "Sum", "is_monotonic": true}
{"metric_name": "system.cpu.time", "labels": {"host.name": "kp-h1", "os.type": "linux", "state": "user"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 300, "temporality": "Cumulative", "type_": "Sum", "is_monotonic": true}
{"metric_name": "system.cpu.time", "labels": {"host.name": "kp-h1", "os.type": "linux", "state": "system"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 50, "temporality": "Cumulative", "type_": "Sum", "is_monotonic": true}
{"metric_name": "system.cpu.time", "labels": {"host.name": "kp-h1", "os.type": "linux", "state": "system"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 100, "temporality": "Cumulative", "type_": "Sum", "is_monotonic": true}
{"metric_name": "system.cpu.time", "labels": {"host.name": "kp-h1", "os.type": "linux", "state": "system"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 150, "temporality": "Cumulative", "type_": "Sum", "is_monotonic": true}
{"metric_name": "system.cpu.time", "labels": {"host.name": "kp-h1", "os.type": "linux", "state": "idle"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 400, "temporality": "Cumulative", "type_": "Sum", "is_monotonic": true}
{"metric_name": "system.cpu.time", "labels": {"host.name": "kp-h1", "os.type": "linux", "state": "idle"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 600, "temporality": "Cumulative", "type_": "Sum", "is_monotonic": true}
{"metric_name": "system.cpu.time", "labels": {"host.name": "kp-h1", "os.type": "linux", "state": "idle"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 800, "temporality": "Cumulative", "type_": "Sum", "is_monotonic": true}
{"metric_name": "system.cpu.time", "labels": {"host.name": "kp-h1", "os.type": "linux", "state": "wait"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 10, "temporality": "Cumulative", "type_": "Sum", "is_monotonic": true}
{"metric_name": "system.cpu.time", "labels": {"host.name": "kp-h1", "os.type": "linux", "state": "wait"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 20, "temporality": "Cumulative", "type_": "Sum", "is_monotonic": true}
{"metric_name": "system.cpu.time", "labels": {"host.name": "kp-h1", "os.type": "linux", "state": "wait"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 30, "temporality": "Cumulative", "type_": "Sum", "is_monotonic": true}
{"metric_name": "system.memory.usage", "labels": {"host.name": "kp-h1", "os.type": "linux", "state": "used", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 2000000000, "temporality": "Unspecified", "type_": "Sum", "is_monotonic": false}
{"metric_name": "system.memory.usage", "labels": {"host.name": "kp-h1", "os.type": "linux", "state": "used", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 2100000000, "temporality": "Unspecified", "type_": "Sum", "is_monotonic": false}
{"metric_name": "system.memory.usage", "labels": {"host.name": "kp-h1", "os.type": "linux", "state": "used", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 2200000000, "temporality": "Unspecified", "type_": "Sum", "is_monotonic": false}
{"metric_name": "system.memory.usage", "labels": {"host.name": "kp-h1", "os.type": "linux", "state": "free", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 6000000000, "temporality": "Unspecified", "type_": "Sum", "is_monotonic": false}
{"metric_name": "system.memory.usage", "labels": {"host.name": "kp-h1", "os.type": "linux", "state": "free", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 5900000000, "temporality": "Unspecified", "type_": "Sum", "is_monotonic": false}
{"metric_name": "system.memory.usage", "labels": {"host.name": "kp-h1", "os.type": "linux", "state": "free", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 5800000000, "temporality": "Unspecified", "type_": "Sum", "is_monotonic": false}
{"metric_name": "system.memory.usage", "labels": {"host.name": "kp-h1", "os.type": "linux", "state": "buffered", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 500000000, "temporality": "Unspecified", "type_": "Sum", "is_monotonic": false}
{"metric_name": "system.memory.usage", "labels": {"host.name": "kp-h1", "os.type": "linux", "state": "buffered", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 500000000, "temporality": "Unspecified", "type_": "Sum", "is_monotonic": false}
{"metric_name": "system.memory.usage", "labels": {"host.name": "kp-h1", "os.type": "linux", "state": "buffered", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 500000000, "temporality": "Unspecified", "type_": "Sum", "is_monotonic": false}
{"metric_name": "system.memory.usage", "labels": {"host.name": "kp-h1", "os.type": "linux", "state": "cached", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1500000000, "temporality": "Unspecified", "type_": "Sum", "is_monotonic": false}
{"metric_name": "system.memory.usage", "labels": {"host.name": "kp-h1", "os.type": "linux", "state": "cached", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1500000000, "temporality": "Unspecified", "type_": "Sum", "is_monotonic": false}
{"metric_name": "system.memory.usage", "labels": {"host.name": "kp-h1", "os.type": "linux", "state": "cached", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1500000000, "temporality": "Unspecified", "type_": "Sum", "is_monotonic": false}
{"metric_name": "system.cpu.load_average.15m", "labels": {"host.name": "kp-h1", "os.type": "linux"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "system.cpu.load_average.15m", "labels": {"host.name": "kp-h1", "os.type": "linux"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1.55, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "system.cpu.load_average.15m", "labels": {"host.name": "kp-h1", "os.type": "linux"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1.6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "system.filesystem.usage", "labels": {"host.name": "kp-h1", "os.type": "linux", "state": "used", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 50000000000, "temporality": "Unspecified", "type_": "Sum", "is_monotonic": false}
{"metric_name": "system.filesystem.usage", "labels": {"host.name": "kp-h1", "os.type": "linux", "state": "used", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 51000000000, "temporality": "Unspecified", "type_": "Sum", "is_monotonic": false}
{"metric_name": "system.filesystem.usage", "labels": {"host.name": "kp-h1", "os.type": "linux", "state": "used", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 52000000000, "temporality": "Unspecified", "type_": "Sum", "is_monotonic": false}
{"metric_name": "system.filesystem.usage", "labels": {"host.name": "kp-h1", "os.type": "linux", "state": "free", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 50000000000, "temporality": "Unspecified", "type_": "Sum", "is_monotonic": false}
{"metric_name": "system.filesystem.usage", "labels": {"host.name": "kp-h1", "os.type": "linux", "state": "free", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 49000000000, "temporality": "Unspecified", "type_": "Sum", "is_monotonic": false}
{"metric_name": "system.filesystem.usage", "labels": {"host.name": "kp-h1", "os.type": "linux", "state": "free", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 48000000000, "temporality": "Unspecified", "type_": "Sum", "is_monotonic": false}
{"metric_name": "system.filesystem.usage", "labels": {"host.name": "kp-h1", "os.type": "linux", "state": "reserved", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 5000000000, "temporality": "Unspecified", "type_": "Sum", "is_monotonic": false}
{"metric_name": "system.filesystem.usage", "labels": {"host.name": "kp-h1", "os.type": "linux", "state": "reserved", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 5000000000, "temporality": "Unspecified", "type_": "Sum", "is_monotonic": false}
{"metric_name": "system.filesystem.usage", "labels": {"host.name": "kp-h1", "os.type": "linux", "state": "reserved", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 5000000000, "temporality": "Unspecified", "type_": "Sum", "is_monotonic": false}

View File

@@ -1,54 +0,0 @@
{"metric_name": "k8s.pod.cpu.usage", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.4, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu.usage", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.4, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu.usage", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.4, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_request_utilization", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.4, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_request_utilization", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.4, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_request_utilization", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.4, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_limit_utilization", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.3, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_limit_utilization", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.3, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_limit_utilization", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.3, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory.working_set", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 100000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory.working_set", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 100000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory.working_set", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 100000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_request_utilization", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.4, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_request_utilization", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.4, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_request_utilization", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.4, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_limit_utilization", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.3, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_limit_utilization", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.3, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_limit_utilization", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.3, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "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-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "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-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu.usage", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu.usage", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu.usage", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_request_utilization", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_request_utilization", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_request_utilization", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_limit_utilization", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_limit_utilization", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_limit_utilization", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory.working_set", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 200000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory.working_set", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 200000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory.working_set", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 200000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_request_utilization", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_request_utilization", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_request_utilization", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_limit_utilization", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_limit_utilization", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_limit_utilization", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "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-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "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-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.job.active_pods", "labels": {"k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "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.job.failed_pods", "labels": {"k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.job.successful_pods", "labels": {"k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "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.job.desired_successful_pods", "labels": {"k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.job.active_pods", "labels": {"k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "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.job.failed_pods", "labels": {"k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.job.successful_pods", "labels": {"k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "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.job.desired_successful_pods", "labels": {"k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.job.active_pods", "labels": {"k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.job.failed_pods", "labels": {"k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.job.successful_pods", "labels": {"k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.job.desired_successful_pods", "labels": {"k8s.job.name": "kp-job", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}

View File

@@ -1,18 +0,0 @@
{"metric_name": "k8s.pod.cpu.usage", "labels": {"k8s.pod.uid": "acc-p1a-uid", "k8s.pod.name": "acc-p1a", "k8s.namespace.name": "kp-ns", "k8s.cluster.name": "cluster-x", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu.usage", "labels": {"k8s.pod.uid": "acc-p1a-uid", "k8s.pod.name": "acc-p1a", "k8s.namespace.name": "kp-ns", "k8s.cluster.name": "cluster-x", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu.usage", "labels": {"k8s.pod.uid": "acc-p1a-uid", "k8s.pod.name": "acc-p1a", "k8s.namespace.name": "kp-ns", "k8s.cluster.name": "cluster-x", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory.working_set", "labels": {"k8s.pod.uid": "acc-p1a-uid", "k8s.pod.name": "acc-p1a", "k8s.namespace.name": "kp-ns", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 100000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory.working_set", "labels": {"k8s.pod.uid": "acc-p1a-uid", "k8s.pod.name": "acc-p1a", "k8s.namespace.name": "kp-ns", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 100000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory.working_set", "labels": {"k8s.pod.uid": "acc-p1a-uid", "k8s.pod.name": "acc-p1a", "k8s.namespace.name": "kp-ns", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 100000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "acc-p1a-uid", "k8s.pod.name": "acc-p1a", "k8s.namespace.name": "kp-ns", "k8s.cluster.name": "cluster-x"}, "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-p1a-uid", "k8s.pod.name": "acc-p1a", "k8s.namespace.name": "kp-ns", "k8s.cluster.name": "cluster-x"}, "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-p1a-uid", "k8s.pod.name": "acc-p1a", "k8s.namespace.name": "kp-ns", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu.usage", "labels": {"k8s.pod.uid": "acc-p1b-uid", "k8s.pod.name": "acc-p1b", "k8s.namespace.name": "kp-ns", "k8s.cluster.name": "cluster-x", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu.usage", "labels": {"k8s.pod.uid": "acc-p1b-uid", "k8s.pod.name": "acc-p1b", "k8s.namespace.name": "kp-ns", "k8s.cluster.name": "cluster-x", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu.usage", "labels": {"k8s.pod.uid": "acc-p1b-uid", "k8s.pod.name": "acc-p1b", "k8s.namespace.name": "kp-ns", "k8s.cluster.name": "cluster-x", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory.working_set", "labels": {"k8s.pod.uid": "acc-p1b-uid", "k8s.pod.name": "acc-p1b", "k8s.namespace.name": "kp-ns", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 100000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory.working_set", "labels": {"k8s.pod.uid": "acc-p1b-uid", "k8s.pod.name": "acc-p1b", "k8s.namespace.name": "kp-ns", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 100000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory.working_set", "labels": {"k8s.pod.uid": "acc-p1b-uid", "k8s.pod.name": "acc-p1b", "k8s.namespace.name": "kp-ns", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 100000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "acc-p1b-uid", "k8s.pod.name": "acc-p1b", "k8s.namespace.name": "kp-ns", "k8s.cluster.name": "cluster-x"}, "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-p1b-uid", "k8s.pod.name": "acc-p1b", "k8s.namespace.name": "kp-ns", "k8s.cluster.name": "cluster-x"}, "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-p1b-uid", "k8s.pod.name": "acc-p1b", "k8s.namespace.name": "kp-ns", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}

View File

@@ -1,18 +0,0 @@
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "kp-n1", "k8s.node.uid": "kp-n1-uid", "k8s.cluster.name": "cluster-x", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "kp-n1", "k8s.node.uid": "kp-n1-uid", "k8s.cluster.name": "cluster-x", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.cpu.usage", "labels": {"k8s.node.name": "kp-n1", "k8s.node.uid": "kp-n1-uid", "k8s.cluster.name": "cluster-x", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "kp-n1", "k8s.node.uid": "kp-n1-uid", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "kp-n1", "k8s.node.uid": "kp-n1-uid", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_cpu", "labels": {"k8s.node.name": "kp-n1", "k8s.node.uid": "kp-n1-uid", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 4.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "kp-n1", "k8s.node.uid": "kp-n1-uid", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 2000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "kp-n1", "k8s.node.uid": "kp-n1-uid", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 2000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.memory.working_set", "labels": {"k8s.node.name": "kp-n1", "k8s.node.uid": "kp-n1-uid", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 2000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "kp-n1", "k8s.node.uid": "kp-n1-uid", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "kp-n1", "k8s.node.uid": "kp-n1-uid", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.allocatable_memory", "labels": {"k8s.node.name": "kp-n1", "k8s.node.uid": "kp-n1-uid", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 8000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.node.condition_ready", "labels": {"k8s.node.name": "kp-n1", "k8s.node.uid": "kp-n1-uid", "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.node.condition_ready", "labels": {"k8s.node.name": "kp-n1", "k8s.node.uid": "kp-n1-uid", "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.node.condition_ready", "labels": {"k8s.node.name": "kp-n1", "k8s.node.uid": "kp-n1-uid", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "acc-pod-1a-uid", "k8s.pod.name": "acc-pod-1a", "k8s.namespace.name": "ns-a", "k8s.node.name": "kp-n1", "k8s.cluster.name": "cluster-x", "k8s.node.uid": "kp-n1-uid"}, "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-pod-1a-uid", "k8s.pod.name": "acc-pod-1a", "k8s.namespace.name": "ns-a", "k8s.node.name": "kp-n1", "k8s.cluster.name": "cluster-x", "k8s.node.uid": "kp-n1-uid"}, "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-pod-1a-uid", "k8s.pod.name": "acc-pod-1a", "k8s.namespace.name": "ns-a", "k8s.node.name": "kp-n1", "k8s.cluster.name": "cluster-x", "k8s.node.uid": "kp-n1-uid"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}

View File

@@ -1,21 +0,0 @@
{"metric_name": "k8s.pod.cpu.usage", "labels": {"k8s.pod.uid": "kp-p1-uid", "k8s.pod.name": "kp-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__", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu.usage", "labels": {"k8s.pod.uid": "kp-p1-uid", "k8s.pod.name": "kp-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__", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu.usage", "labels": {"k8s.pod.uid": "kp-p1-uid", "k8s.pod.name": "kp-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__", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_request_utilization", "labels": {"k8s.pod.uid": "kp-p1-uid", "k8s.pod.name": "kp-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": 0.25, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_request_utilization", "labels": {"k8s.pod.uid": "kp-p1-uid", "k8s.pod.name": "kp-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": 0.25, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_request_utilization", "labels": {"k8s.pod.uid": "kp-p1-uid", "k8s.pod.name": "kp-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": 0.25, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_limit_utilization", "labels": {"k8s.pod.uid": "kp-p1-uid", "k8s.pod.name": "kp-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": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_limit_utilization", "labels": {"k8s.pod.uid": "kp-p1-uid", "k8s.pod.name": "kp-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": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_limit_utilization", "labels": {"k8s.pod.uid": "kp-p1-uid", "k8s.pod.name": "kp-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": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory.working_set", "labels": {"k8s.pod.uid": "kp-p1-uid", "k8s.pod.name": "kp-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": 524288000, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory.working_set", "labels": {"k8s.pod.uid": "kp-p1-uid", "k8s.pod.name": "kp-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": 524288000, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory.working_set", "labels": {"k8s.pod.uid": "kp-p1-uid", "k8s.pod.name": "kp-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": 524288000, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_request_utilization", "labels": {"k8s.pod.uid": "kp-p1-uid", "k8s.pod.name": "kp-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": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_request_utilization", "labels": {"k8s.pod.uid": "kp-p1-uid", "k8s.pod.name": "kp-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": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_request_utilization", "labels": {"k8s.pod.uid": "kp-p1-uid", "k8s.pod.name": "kp-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": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_limit_utilization", "labels": {"k8s.pod.uid": "kp-p1-uid", "k8s.pod.name": "kp-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": 0.25, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_limit_utilization", "labels": {"k8s.pod.uid": "kp-p1-uid", "k8s.pod.name": "kp-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": 0.25, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_limit_utilization", "labels": {"k8s.pod.uid": "kp-p1-uid", "k8s.pod.name": "kp-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": 0.25, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "kp-p1-uid", "k8s.pod.name": "kp-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": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "kp-p1-uid", "k8s.pod.name": "kp-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": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "kp-p1-uid", "k8s.pod.name": "kp-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": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}

View File

@@ -1,48 +0,0 @@
{"metric_name": "k8s.pod.cpu.usage", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.4, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu.usage", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.4, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu.usage", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.4, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_request_utilization", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.4, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_request_utilization", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.4, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_request_utilization", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.4, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_limit_utilization", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.3, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_limit_utilization", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.3, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_limit_utilization", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.3, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory.working_set", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 100000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory.working_set", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 100000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory.working_set", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 100000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_request_utilization", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.4, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_request_utilization", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.4, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_request_utilization", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.4, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_limit_utilization", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.3, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_limit_utilization", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.3, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_limit_utilization", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.3, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "acc-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "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-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "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-1-p1-uid", "k8s.pod.name": "acc-1-p1", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu.usage", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu.usage", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu.usage", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_request_utilization", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_request_utilization", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_request_utilization", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_limit_utilization", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_limit_utilization", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.cpu_limit_utilization", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory.working_set", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 200000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory.working_set", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 200000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory.working_set", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 200000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_request_utilization", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_request_utilization", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_request_utilization", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.6, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_limit_utilization", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_limit_utilization", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.memory_limit_utilization", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 0.5, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.pod.phase", "labels": {"k8s.pod.uid": "acc-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "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-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "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-1-p2-uid", "k8s.pod.name": "acc-1-p2", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.statefulset.desired_pods", "labels": {"k8s.statefulset.name": "kp-sts", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 3, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.statefulset.current_pods", "labels": {"k8s.statefulset.name": "kp-sts", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.statefulset.desired_pods", "labels": {"k8s.statefulset.name": "kp-sts", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 3, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.statefulset.current_pods", "labels": {"k8s.statefulset.name": "kp-sts", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.statefulset.desired_pods", "labels": {"k8s.statefulset.name": "kp-sts", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 3, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.statefulset.current_pods", "labels": {"k8s.statefulset.name": "kp-sts", "k8s.namespace.name": "ns-acc", "k8s.cluster.name": "cluster-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 2, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}

View File

@@ -1,12 +0,0 @@
{"metric_name": "k8s.volume.capacity", "labels": {"k8s.persistentvolumeclaim.name": "fop-pvc", "k8s.pod.uid": "fop-pvc-uid", "k8s.pod.name": "pod-fop-pvc", "k8s.namespace.name": "ns-acc", "k8s.node.name": "node-x", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "ss-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 100000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.volume.capacity", "labels": {"k8s.persistentvolumeclaim.name": "fop-pvc", "k8s.pod.uid": "fop-pvc-uid", "k8s.pod.name": "pod-fop-pvc", "k8s.namespace.name": "ns-acc", "k8s.node.name": "node-x", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "ss-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 100000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.volume.capacity", "labels": {"k8s.persistentvolumeclaim.name": "fop-pvc", "k8s.pod.uid": "fop-pvc-uid", "k8s.pod.name": "pod-fop-pvc", "k8s.namespace.name": "ns-acc", "k8s.node.name": "node-x", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "ss-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 100000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.volume.inodes", "labels": {"k8s.persistentvolumeclaim.name": "fop-pvc", "k8s.pod.uid": "fop-pvc-uid", "k8s.pod.name": "pod-fop-pvc", "k8s.namespace.name": "ns-acc", "k8s.node.name": "node-x", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "ss-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.volume.inodes", "labels": {"k8s.persistentvolumeclaim.name": "fop-pvc", "k8s.pod.uid": "fop-pvc-uid", "k8s.pod.name": "pod-fop-pvc", "k8s.namespace.name": "ns-acc", "k8s.node.name": "node-x", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "ss-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.volume.inodes", "labels": {"k8s.persistentvolumeclaim.name": "fop-pvc", "k8s.pod.uid": "fop-pvc-uid", "k8s.pod.name": "pod-fop-pvc", "k8s.namespace.name": "ns-acc", "k8s.node.name": "node-x", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "ss-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.volume.inodes.free", "labels": {"k8s.persistentvolumeclaim.name": "fop-pvc", "k8s.pod.uid": "fop-pvc-uid", "k8s.pod.name": "pod-fop-pvc", "k8s.namespace.name": "ns-acc", "k8s.node.name": "node-x", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "ss-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 800000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.volume.inodes.free", "labels": {"k8s.persistentvolumeclaim.name": "fop-pvc", "k8s.pod.uid": "fop-pvc-uid", "k8s.pod.name": "pod-fop-pvc", "k8s.namespace.name": "ns-acc", "k8s.node.name": "node-x", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "ss-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 800000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.volume.inodes.free", "labels": {"k8s.persistentvolumeclaim.name": "fop-pvc", "k8s.pod.uid": "fop-pvc-uid", "k8s.pod.name": "pod-fop-pvc", "k8s.namespace.name": "ns-acc", "k8s.node.name": "node-x", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "ss-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 800000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.volume.inodes.used", "labels": {"k8s.persistentvolumeclaim.name": "fop-pvc", "k8s.pod.uid": "fop-pvc-uid", "k8s.pod.name": "pod-fop-pvc", "k8s.namespace.name": "ns-acc", "k8s.node.name": "node-x", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "ss-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 200000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.volume.inodes.used", "labels": {"k8s.persistentvolumeclaim.name": "fop-pvc", "k8s.pod.uid": "fop-pvc-uid", "k8s.pod.name": "pod-fop-pvc", "k8s.namespace.name": "ns-acc", "k8s.node.name": "node-x", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "ss-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 200000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.volume.inodes.used", "labels": {"k8s.persistentvolumeclaim.name": "fop-pvc", "k8s.pod.uid": "fop-pvc-uid", "k8s.pod.name": "pod-fop-pvc", "k8s.namespace.name": "ns-acc", "k8s.node.name": "node-x", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "ss-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 200000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}

View File

@@ -1,15 +0,0 @@
{"metric_name": "k8s.volume.available", "labels": {"k8s.persistentvolumeclaim.name": "kp-pvc", "k8s.pod.uid": "kp-pvc-uid", "k8s.pod.name": "pod-kp-pvc", "k8s.namespace.name": "ns-acc", "k8s.node.name": "node-x", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "ss-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 30000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.volume.available", "labels": {"k8s.persistentvolumeclaim.name": "kp-pvc", "k8s.pod.uid": "kp-pvc-uid", "k8s.pod.name": "pod-kp-pvc", "k8s.namespace.name": "ns-acc", "k8s.node.name": "node-x", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "ss-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 30000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.volume.available", "labels": {"k8s.persistentvolumeclaim.name": "kp-pvc", "k8s.pod.uid": "kp-pvc-uid", "k8s.pod.name": "pod-kp-pvc", "k8s.namespace.name": "ns-acc", "k8s.node.name": "node-x", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "ss-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 30000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.volume.capacity", "labels": {"k8s.persistentvolumeclaim.name": "kp-pvc", "k8s.pod.uid": "kp-pvc-uid", "k8s.pod.name": "pod-kp-pvc", "k8s.namespace.name": "ns-acc", "k8s.node.name": "node-x", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "ss-x", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 100000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.volume.capacity", "labels": {"k8s.persistentvolumeclaim.name": "kp-pvc", "k8s.pod.uid": "kp-pvc-uid", "k8s.pod.name": "pod-kp-pvc", "k8s.namespace.name": "ns-acc", "k8s.node.name": "node-x", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "ss-x", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 100000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.volume.capacity", "labels": {"k8s.persistentvolumeclaim.name": "kp-pvc", "k8s.pod.uid": "kp-pvc-uid", "k8s.pod.name": "pod-kp-pvc", "k8s.namespace.name": "ns-acc", "k8s.node.name": "node-x", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "ss-x", "deployment.environment": "prod"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 100000000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.volume.inodes", "labels": {"k8s.persistentvolumeclaim.name": "kp-pvc", "k8s.pod.uid": "kp-pvc-uid", "k8s.pod.name": "pod-kp-pvc", "k8s.namespace.name": "ns-acc", "k8s.node.name": "node-x", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "ss-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 1000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.volume.inodes", "labels": {"k8s.persistentvolumeclaim.name": "kp-pvc", "k8s.pod.uid": "kp-pvc-uid", "k8s.pod.name": "pod-kp-pvc", "k8s.namespace.name": "ns-acc", "k8s.node.name": "node-x", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "ss-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 1000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.volume.inodes", "labels": {"k8s.persistentvolumeclaim.name": "kp-pvc", "k8s.pod.uid": "kp-pvc-uid", "k8s.pod.name": "pod-kp-pvc", "k8s.namespace.name": "ns-acc", "k8s.node.name": "node-x", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "ss-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 1000000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.volume.inodes.free", "labels": {"k8s.persistentvolumeclaim.name": "kp-pvc", "k8s.pod.uid": "kp-pvc-uid", "k8s.pod.name": "pod-kp-pvc", "k8s.namespace.name": "ns-acc", "k8s.node.name": "node-x", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "ss-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 800000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.volume.inodes.free", "labels": {"k8s.persistentvolumeclaim.name": "kp-pvc", "k8s.pod.uid": "kp-pvc-uid", "k8s.pod.name": "pod-kp-pvc", "k8s.namespace.name": "ns-acc", "k8s.node.name": "node-x", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "ss-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 800000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.volume.inodes.free", "labels": {"k8s.persistentvolumeclaim.name": "kp-pvc", "k8s.pod.uid": "kp-pvc-uid", "k8s.pod.name": "pod-kp-pvc", "k8s.namespace.name": "ns-acc", "k8s.node.name": "node-x", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "ss-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 800000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.volume.inodes.used", "labels": {"k8s.persistentvolumeclaim.name": "kp-pvc", "k8s.pod.uid": "kp-pvc-uid", "k8s.pod.name": "pod-kp-pvc", "k8s.namespace.name": "ns-acc", "k8s.node.name": "node-x", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "ss-x"}, "timestamp": "2025-01-10T10:00:00+00:00", "value": 200000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.volume.inodes.used", "labels": {"k8s.persistentvolumeclaim.name": "kp-pvc", "k8s.pod.uid": "kp-pvc-uid", "k8s.pod.name": "pod-kp-pvc", "k8s.namespace.name": "ns-acc", "k8s.node.name": "node-x", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "ss-x"}, "timestamp": "2025-01-10T10:02:00+00:00", "value": 200000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}
{"metric_name": "k8s.volume.inodes.used", "labels": {"k8s.persistentvolumeclaim.name": "kp-pvc", "k8s.pod.uid": "kp-pvc-uid", "k8s.pod.name": "pod-kp-pvc", "k8s.namespace.name": "ns-acc", "k8s.node.name": "node-x", "k8s.cluster.name": "cluster-x", "k8s.statefulset.name": "ss-x"}, "timestamp": "2025-01-10T10:04:00+00:00", "value": 200000.0, "temporality": "Unspecified", "type_": "Gauge", "is_monotonic": false}

View File

@@ -11,7 +11,7 @@ from fixtures import types
from fixtures.auth import USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD
from fixtures.fs import get_testdata_file_path
from fixtures.metrics import Metrics
from fixtures.querier import compare_values, get_all_warnings
from fixtures.querier import compare_values
ENDPOINT = "/api/v2/infra_monitoring/hosts"
@@ -56,8 +56,7 @@ def test_hosts_accuracy(
# Shape/contract.
assert data["total"] == len(expected["records"])
assert len(data["records"]) == len(expected["records"])
# Full data present -> no warnings surfaced.
assert get_all_warnings(response.json()) == []
assert data["requiredMetricsCheck"]["missingMetrics"] == []
assert data["endTimeBeforeRetention"] is False
assert {r["hostName"] for r in data["records"]} == set(exp_by_host.keys())
@@ -80,108 +79,45 @@ def test_hosts_accuracy(
assert compare_values(record[field], exp[field], 1e-9), f"{record['hostName']}.{field}: got {record[field]}, expected {exp[field]}"
@pytest.mark.parametrize(
"case",
[
# Scenario 1: a required host metric was never ingested. Post-#11754 the
# querier drops it instead of hard-erroring, so the endpoint returns 200
# with the hosts that DO have data; the never-seen metric's column is the
# -1 sentinel and a "has never been received" warning is surfaced.
pytest.param(
{
"dataset": "hosts_missing_metrics.jsonl", # seeds only system.cpu.time
"body": {"filter": {"expression": "host.name = 'miss-h1'"}},
# singular form is "has", plural (>1 missing) is "have" -> match the common stem
"warn_substrings": ["never been received"],
"warn_names": [
"system.memory.usage",
"system.cpu.load_average.15m",
"system.filesystem.usage",
],
# cpu/wait derive from the present system.cpu.time; the rest come
# from never-seen metrics -> -1 sentinel.
"data_fields": ["cpu", "wait"],
"no_data_fields": ["memory", "load15", "diskUsage"],
},
id="metric_never_seen",
),
# Scenario 2: groupBy a key that IS in metadata (seen on some metrics) but
# was never seen together with the host metrics. deployment.environment is
# seeded on system.memory.usage + system.filesystem.usage only, so the key
# resolves (the page-groups IN-filter parses -> no 400) but the cpu.time /
# load_average metrics miss the (metric, key) pair and the statement builder
# falls back to raw labels, surfacing "key `...` not found on metric ...".
# Still 200, no hard error.
pytest.param(
{
"dataset": "hosts_metric_key_pair.jsonl",
"body": {
"filter": {"expression": "host.name = 'kp-h1'"},
"groupBy": [
{
"name": "deployment.environment",
"fieldDataType": "string",
"fieldContext": "resource",
}
],
},
"warn_substrings": ["key `deployment.environment` not found on metric"],
"warn_names": [],
"data_fields": [],
"no_data_fields": [],
},
id="metric_key_pair_not_seen",
),
],
)
def test_hosts_warnings(
def test_hosts_missing_metrics(
signoz: types.SigNoz,
create_user_admin: None, # pylint: disable=unused-argument
get_token,
insert_metrics,
case: dict,
) -> None:
"""Data-availability gaps surface as non-blocking warnings (200 + data),
not hard errors. Covers never-seen metrics (scenario 1) and never-seen
(metric, key) pairs via groupBy (scenario 2)."""
"""Seed only system.cpu.time; assert other 3 required metrics flagged missing."""
now = datetime.now(tz=UTC).replace(microsecond=0)
insert_metrics(
Metrics.load_from_file(
get_testdata_file_path(f"inframonitoring/{case['dataset']}"),
get_testdata_file_path("inframonitoring/hosts_missing_metrics.jsonl"),
base_time=now - timedelta(minutes=4),
)
)
token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
body: dict = {
"start": int((now - timedelta(minutes=5)).timestamp() * 1000),
"end": int(now.timestamp() * 1000),
"limit": 50,
}
body.update(case["body"])
response = requests.post(
signoz.self.host_configs["8080"].get(ENDPOINT),
headers={"authorization": f"Bearer {token}"},
json=body,
json={
"start": int((now - timedelta(minutes=5)).timestamp() * 1000),
"end": int(now.timestamp() * 1000),
"limit": 50,
},
timeout=5,
)
assert response.status_code == HTTPStatus.OK, response.text
assert response.status_code == HTTPStatus.OK
data = response.json()["data"]
warnings = get_all_warnings(response.json())
for substr in case["warn_substrings"]:
assert any(substr in w["message"] for w in warnings), f"{substr!r} not surfaced: {warnings!r}"
for name in case["warn_names"]:
assert any(name in w["message"] for w in warnings), f"{name!r} not surfaced: {warnings!r}"
assert len(data["records"]) >= 1, f"expected at least one record: {data!r}"
if case["data_fields"] or case["no_data_fields"]:
record = data["records"][0]
for field in case["data_fields"]:
assert record[field] != -1, f"expected {field} populated, got {record[field]}"
for field in case["no_data_fields"]:
assert record[field] == -1, f"expected {field} == -1 sentinel, got {record[field]}"
assert set(data["requiredMetricsCheck"]["missingMetrics"]) == {
"system.memory.usage",
"system.cpu.load_average.15m",
"system.filesystem.usage",
}
# Endpoint short-circuits when any required metric is missing:
# records is empty and total=0 regardless of which hosts have partial data.
# See pkg/modules/inframonitoring/implinframonitoring/module.go:84-89.
assert data["records"] == []
assert data["total"] == 0
@pytest.mark.parametrize(

View File

@@ -11,11 +11,26 @@ from fixtures import types
from fixtures.auth import USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD
from fixtures.fs import get_testdata_file_path
from fixtures.metrics import Metrics
from fixtures.querier import compare_values, get_all_warnings
from fixtures.querier import compare_values
from fixtures.time import parse_timestamp
ENDPOINT = "/api/v2/infra_monitoring/pods"
# Required metrics for the v2 pods endpoint
# (pkg/modules/inframonitoring/implinframonitoring/pods_constants.go:24-32).
REQUIRED_METRICS = {
"k8s.pod.cpu.usage",
"k8s.pod.cpu_request_utilization",
"k8s.pod.cpu_limit_utilization",
"k8s.pod.memory.working_set",
"k8s.pod.memory_request_utilization",
"k8s.pod.memory_limit_utilization",
"k8s.pod.phase",
}
# Numeric values emitted by the k8s.pod.phase metric (OTel kubeletstatsreceiver).
PHASE_NUM = {"pending": 1, "running": 2, "succeeded": 3, "failed": 4, "unknown": 5}
# Placeholder in JSONL labels that gets substituted with a runtime ISO string.
START_TIME_PLACEHOLDER = "__START_TIME__"
@@ -101,8 +116,7 @@ def test_pods_accuracy(
# Shape/contract.
assert data["total"] == len(expected["records"])
assert len(data["records"]) == len(expected["records"])
# Full data present -> no warnings surfaced.
assert get_all_warnings(response.json()) == []
assert data["requiredMetricsCheck"]["missingMetrics"] == []
assert data["endTimeBeforeRetention"] is False
assert {r["meta"]["k8s.pod.name"] for r in data["records"]} == set(exp_by_name.keys())
@@ -148,115 +162,42 @@ def test_pods_accuracy(
assert record["podAge"] == expected_age_ms, f"{pod_name}.podAge: got {record['podAge']}, expected {expected_age_ms}"
@pytest.mark.parametrize(
"case",
[
# Scenario 1: required metrics were never ingested. Post-#11754 the querier
# drops them (no hard error), so the endpoint returns 200 with the pod that
# DOES have data; never-seen columns are the -1 sentinel and a
# "have never been received" warning is surfaced. Pods has no formulas, so
# each missing metric maps straight to one -1 column.
pytest.param(
{
"dataset": "pods_missing_metrics.jsonl", # seeds only k8s.pod.cpu.usage
"body": {"filter": {"expression": "k8s.pod.name = 'miss-p1'"}},
"warn_substrings": ["never been received"],
"warn_names": [
"k8s.pod.cpu_request_utilization",
"k8s.pod.cpu_limit_utilization",
"k8s.pod.memory.working_set",
"k8s.pod.memory_request_utilization",
"k8s.pod.memory_limit_utilization",
],
# podCPU derives from the present k8s.pod.cpu.usage; the rest from
# never-seen metrics -> -1 sentinel.
"data_fields": ["podCPU"],
"no_data_fields": [
"podCPURequest",
"podCPULimit",
"podMemory",
"podMemoryRequest",
"podMemoryLimit",
],
},
id="metric_never_seen",
),
# Scenario 2: groupBy a key that IS in metadata (deployment.environment is
# seeded on k8s.pod.cpu.usage only) but was never seen together with the
# other pod metrics. The key resolves (the page-groups IN-filter parses ->
# no 400), but B-F miss the (metric, key) pair and the statement builder
# falls back to raw labels, surfacing "key `...` not found on metric ...".
# Still 200, no hard error.
pytest.param(
{
"dataset": "pods_metric_key_pair.jsonl",
"body": {
"filter": {"expression": "k8s.pod.name = 'kp-p1'"},
"groupBy": [
{
"name": "deployment.environment",
"fieldDataType": "string",
"fieldContext": "resource",
}
],
},
"warn_substrings": ["key `deployment.environment` not found on metric"],
"warn_names": [],
"data_fields": [],
"no_data_fields": [],
},
id="metric_key_pair_not_seen",
),
],
)
def test_pods_warnings(
def test_pods_missing_metrics(
signoz: types.SigNoz,
create_user_admin: None, # pylint: disable=unused-argument
get_token,
insert_metrics,
case: dict,
) -> None:
"""Data-availability gaps surface as non-blocking warnings (200 + data), not
hard errors. Covers never-seen metrics (scenario 1) and never-seen
(metric, key) pairs via groupBy (scenario 2)."""
"""Seed only k8s.pod.cpu.usage; assert other 6 required metrics flagged missing.
The endpoint short-circuits and returns empty records + total=0 when any
required metric is missing (module.go:192-197).
"""
now = datetime.now(tz=UTC).replace(microsecond=0)
insert_metrics(
_load_pods_metrics(
f"inframonitoring/{case['dataset']}",
"inframonitoring/pods_missing_metrics.jsonl",
base_time=now - timedelta(minutes=4),
)
)
token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
body: dict = {
"start": int((now - timedelta(minutes=5)).timestamp() * 1000),
"end": int(now.timestamp() * 1000),
"limit": 50,
}
body.update(case["body"])
response = requests.post(
signoz.self.host_configs["8080"].get(ENDPOINT),
headers={"authorization": f"Bearer {token}"},
json=body,
json={
"start": int((now - timedelta(minutes=5)).timestamp() * 1000),
"end": int(now.timestamp() * 1000),
"limit": 50,
},
timeout=5,
)
assert response.status_code == HTTPStatus.OK, response.text
data = response.json()["data"]
warnings = get_all_warnings(response.json())
for substr in case["warn_substrings"]:
assert any(substr in w["message"] for w in warnings), f"{substr!r} not surfaced: {warnings!r}"
for name in case["warn_names"]:
assert any(name in w["message"] for w in warnings), f"{name!r} not surfaced: {warnings!r}"
assert len(data["records"]) >= 1, f"expected at least one record: {data!r}"
if case["data_fields"] or case["no_data_fields"]:
record = data["records"][0]
for field in case["data_fields"]:
assert record[field] != -1, f"expected {field} populated, got {record[field]}"
for field in case["no_data_fields"]:
assert record[field] == -1, f"expected {field} == -1 sentinel, got {record[field]}"
assert set(data["requiredMetricsCheck"]["missingMetrics"]) == (REQUIRED_METRICS - {"k8s.pod.cpu.usage"})
assert data["records"] == []
assert data["total"] == 0
@pytest.mark.parametrize(

View File

@@ -11,10 +11,24 @@ from fixtures import types
from fixtures.auth import USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD
from fixtures.fs import get_testdata_file_path
from fixtures.metrics import Metrics
from fixtures.querier import compare_values, get_all_warnings
from fixtures.querier import compare_values
ENDPOINT = "/api/v2/infra_monitoring/nodes"
# Required metrics for the v2 nodes endpoint
# (pkg/modules/inframonitoring/implinframonitoring/nodes_constants.go:22-29).
REQUIRED_METRICS = {
"k8s.node.cpu.usage",
"k8s.node.allocatable_cpu",
"k8s.node.memory.working_set",
"k8s.node.allocatable_memory",
"k8s.node.condition_ready",
"k8s.pod.phase",
}
# Numeric values emitted by k8s.node.condition_ready.
COND_NUM = {"ready": 1, "not_ready": 0}
def test_nodes_accuracy(
signoz: types.SigNoz,
@@ -57,8 +71,7 @@ def test_nodes_accuracy(
# Shape/contract.
assert data["total"] == len(expected["records"])
assert len(data["records"]) == len(expected["records"])
# Full data present -> no warnings surfaced.
assert get_all_warnings(response.json()) == []
assert data["requiredMetricsCheck"]["missingMetrics"] == []
assert data["endTimeBeforeRetention"] is False
assert {r["nodeName"] for r in data["records"]} == set(exp_by_name.keys())
@@ -94,107 +107,38 @@ def test_nodes_accuracy(
assert record["podCountsByPhase"] == exp["podCountsByPhase"]
@pytest.mark.parametrize(
"case",
[
# Scenario 1: required metrics were never ingested. Post-#11754 the querier
# drops them (no hard error), so the endpoint returns 200 with the node that
# DOES have data; never-seen columns are the -1 sentinel + a
# "have never been received" warning. Nodes has no formulas, so each missing
# metric maps straight to one -1 column.
pytest.param(
{
"dataset": "nodes_missing_metrics.jsonl", # seeds only k8s.node.cpu.usage
"body": {"filter": {"expression": "k8s.node.name = 'miss-n1'"}},
"warn_substrings": ["never been received"],
"warn_names": [
"k8s.node.allocatable_cpu",
"k8s.node.memory.working_set",
"k8s.node.allocatable_memory",
],
# nodeCPU derives from the present k8s.node.cpu.usage; the rest from
# never-seen metrics -> -1 sentinel.
"data_fields": ["nodeCPU"],
"no_data_fields": ["nodeCPUAllocatable", "nodeMemory", "nodeMemoryAllocatable"],
},
id="metric_never_seen",
),
# Scenario 2: groupBy a key that IS in metadata (deployment.environment is
# seeded on k8s.node.cpu.usage only) but was never seen together with the
# other node metrics. The key resolves (the page-groups IN-filter parses ->
# no 400), but B/C/D miss the (metric, key) pair and the statement builder
# falls back to raw labels, surfacing "key `...` not found on metric ...".
# Still 200, no hard error.
pytest.param(
{
"dataset": "nodes_metric_key_pair.jsonl",
"body": {
"filter": {"expression": "k8s.node.name = 'kp-n1'"},
"groupBy": [
{
"name": "deployment.environment",
"fieldDataType": "string",
"fieldContext": "resource",
}
],
},
"warn_substrings": ["key `deployment.environment` not found on metric"],
"warn_names": [],
"data_fields": [],
"no_data_fields": [],
},
id="metric_key_pair_not_seen",
),
],
)
def test_nodes_warnings(
def test_nodes_missing_metrics(
signoz: types.SigNoz,
create_user_admin: None, # pylint: disable=unused-argument
get_token,
insert_metrics,
case: dict,
) -> None:
"""Data-availability gaps surface as non-blocking warnings (200 + data), not
hard errors. Covers never-seen metrics (scenario 1) and never-seen
(metric, key) pairs via groupBy (scenario 2)."""
"""Seed only k8s.node.cpu.usage; assert other 5 required metrics flagged missing."""
now = datetime.now(tz=UTC).replace(microsecond=0)
insert_metrics(
Metrics.load_from_file(
get_testdata_file_path(f"inframonitoring/{case['dataset']}"),
get_testdata_file_path("inframonitoring/nodes_missing_metrics.jsonl"),
base_time=now - timedelta(minutes=4),
)
)
token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
body: dict = {
"start": int((now - timedelta(minutes=5)).timestamp() * 1000),
"end": int(now.timestamp() * 1000),
"limit": 50,
}
body.update(case["body"])
response = requests.post(
signoz.self.host_configs["8080"].get(ENDPOINT),
headers={"authorization": f"Bearer {token}"},
json=body,
json={
"start": int((now - timedelta(minutes=5)).timestamp() * 1000),
"end": int(now.timestamp() * 1000),
"limit": 50,
},
timeout=5,
)
assert response.status_code == HTTPStatus.OK, response.text
data = response.json()["data"]
warnings = get_all_warnings(response.json())
for substr in case["warn_substrings"]:
assert any(substr in w["message"] for w in warnings), f"{substr!r} not surfaced: {warnings!r}"
for name in case["warn_names"]:
assert any(name in w["message"] for w in warnings), f"{name!r} not surfaced: {warnings!r}"
assert len(data["records"]) >= 1, f"expected at least one record: {data!r}"
if case["data_fields"] or case["no_data_fields"]:
record = data["records"][0]
for field in case["data_fields"]:
assert record[field] != -1, f"expected {field} populated, got {record[field]}"
for field in case["no_data_fields"]:
assert record[field] == -1, f"expected {field} == -1 sentinel, got {record[field]}"
assert set(data["requiredMetricsCheck"]["missingMetrics"]) == (REQUIRED_METRICS - {"k8s.node.cpu.usage"})
assert data["records"] == []
assert data["total"] == 0
@pytest.mark.parametrize(

View File

@@ -11,10 +11,18 @@ from fixtures import types
from fixtures.auth import USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD
from fixtures.fs import get_testdata_file_path
from fixtures.metrics import Metrics
from fixtures.querier import compare_values, get_all_warnings
from fixtures.querier import compare_values
ENDPOINT = "/api/v2/infra_monitoring/namespaces"
# Required metrics for the v2 namespaces endpoint
# (pkg/modules/inframonitoring/implinframonitoring/namespaces_constants.go:22-26).
REQUIRED_METRICS = {
"k8s.pod.cpu.usage",
"k8s.pod.memory.working_set",
"k8s.pod.phase",
}
def test_namespaces_accuracy(
signoz: types.SigNoz,
@@ -63,8 +71,7 @@ def test_namespaces_accuracy(
# Shape/contract.
assert data["total"] == len(expected["records"])
assert len(data["records"]) == len(expected["records"])
# Full data present -> no warnings surfaced.
assert get_all_warnings(response.json()) == []
assert data["requiredMetricsCheck"]["missingMetrics"] == []
assert data["endTimeBeforeRetention"] is False
assert {r["namespaceName"] for r in data["records"]} == set(exp_by_name.keys())
@@ -92,103 +99,38 @@ def test_namespaces_accuracy(
assert record["podCountsByPhase"] == exp["podCountsByPhase"]
@pytest.mark.parametrize(
"case",
[
# Scenario 1: a required metric was never ingested. Post-#11754 the querier
# drops it (no hard error), so the endpoint returns 200 with the namespace
# that DOES have data; the never-seen column is the -1 sentinel + a
# "have never been received" warning. Namespaces has no formulas (2 columns:
# namespaceCPU=A, namespaceMemory=D). Default groupBy is two keys
# [k8s.namespace.name, k8s.cluster.name]; the seed carries both so the
# page-groups IN-filter parses.
pytest.param(
{
"dataset": "namespaces_missing_metrics.jsonl", # seeds only k8s.pod.cpu.usage
"body": {"filter": {"expression": "k8s.namespace.name = 'miss-ns'"}},
"warn_substrings": ["never been received", "k8s.pod.memory.working_set"],
"warn_names": [],
"data_fields": ["namespaceCPU"],
"no_data_fields": ["namespaceMemory"],
},
id="metric_never_seen",
),
# Scenario 2: groupBy a key that IS in metadata (deployment.environment is
# seeded on k8s.pod.cpu.usage only) but was never seen together with
# k8s.pod.memory.working_set. The key resolves (page-groups IN-filter parses
# -> no 400), but the memory metric misses the (metric, key) pair and the
# statement builder falls back to raw labels, surfacing
# "key `...` not found on metric ...". Still 200, no hard error.
pytest.param(
{
"dataset": "namespaces_metric_key_pair.jsonl",
"body": {
"filter": {"expression": "k8s.namespace.name = 'kp-ns'"},
"groupBy": [
{
"name": "deployment.environment",
"fieldDataType": "string",
"fieldContext": "resource",
}
],
},
"warn_substrings": ["key `deployment.environment` not found on metric"],
"warn_names": [],
"data_fields": [],
"no_data_fields": [],
},
id="metric_key_pair_not_seen",
),
],
)
def test_namespaces_warnings(
def test_namespaces_missing_metrics(
signoz: types.SigNoz,
create_user_admin: None, # pylint: disable=unused-argument
get_token,
insert_metrics,
case: dict,
) -> None:
"""Data-availability gaps surface as non-blocking warnings (200 + data), not
hard errors. Covers never-seen metrics (scenario 1) and never-seen
(metric, key) pairs via groupBy (scenario 2)."""
"""Seed only k8s.pod.cpu.usage; assert other 2 required metrics flagged missing."""
now = datetime.now(tz=UTC).replace(microsecond=0)
insert_metrics(
Metrics.load_from_file(
get_testdata_file_path(f"inframonitoring/{case['dataset']}"),
get_testdata_file_path("inframonitoring/namespaces_missing_metrics.jsonl"),
base_time=now - timedelta(minutes=4),
)
)
token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
body: dict = {
"start": int((now - timedelta(minutes=5)).timestamp() * 1000),
"end": int(now.timestamp() * 1000),
"limit": 50,
}
body.update(case["body"])
response = requests.post(
signoz.self.host_configs["8080"].get(ENDPOINT),
headers={"authorization": f"Bearer {token}"},
json=body,
json={
"start": int((now - timedelta(minutes=5)).timestamp() * 1000),
"end": int(now.timestamp() * 1000),
"limit": 50,
},
timeout=5,
)
assert response.status_code == HTTPStatus.OK, response.text
data = response.json()["data"]
warnings = get_all_warnings(response.json())
for substr in case["warn_substrings"]:
assert any(substr in w["message"] for w in warnings), f"{substr!r} not surfaced: {warnings!r}"
for name in case["warn_names"]:
assert any(name in w["message"] for w in warnings), f"{name!r} not surfaced: {warnings!r}"
assert len(data["records"]) >= 1, f"expected at least one record: {data!r}"
if case["data_fields"] or case["no_data_fields"]:
record = data["records"][0]
for field in case["data_fields"]:
assert record[field] != -1, f"expected {field} populated, got {record[field]}"
for field in case["no_data_fields"]:
assert record[field] == -1, f"expected {field} == -1 sentinel, got {record[field]}"
assert set(data["requiredMetricsCheck"]["missingMetrics"]) == (REQUIRED_METRICS - {"k8s.pod.cpu.usage"})
assert data["records"] == []
assert data["total"] == 0
@pytest.mark.parametrize(

View File

@@ -11,10 +11,21 @@ from fixtures import types
from fixtures.auth import USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD
from fixtures.fs import get_testdata_file_path
from fixtures.metrics import Metrics
from fixtures.querier import compare_values, get_all_warnings
from fixtures.querier import compare_values
ENDPOINT = "/api/v2/infra_monitoring/clusters"
# Required metrics for the v2 clusters endpoint
# (pkg/modules/inframonitoring/implinframonitoring/clusters_constants.go:23-30).
REQUIRED_METRICS = {
"k8s.node.cpu.usage",
"k8s.node.allocatable_cpu",
"k8s.node.memory.working_set",
"k8s.node.allocatable_memory",
"k8s.node.condition_ready",
"k8s.pod.phase",
}
def test_clusters_accuracy(
signoz: types.SigNoz,
@@ -63,8 +74,7 @@ def test_clusters_accuracy(
# Shape/contract.
assert data["total"] == len(expected["records"])
assert len(data["records"]) == len(expected["records"])
# Full data present -> no warnings surfaced.
assert get_all_warnings(response.json()) == []
assert data["requiredMetricsCheck"]["missingMetrics"] == []
assert data["endTimeBeforeRetention"] is False
assert {r["clusterName"] for r in data["records"]} == set(exp_by_name.keys())
@@ -103,106 +113,38 @@ def test_clusters_accuracy(
assert record["podCountsByPhase"] == exp["podCountsByPhase"]
@pytest.mark.parametrize(
"case",
[
# Scenario 1: a required metric was never ingested. Post-#11754 the querier
# drops it (no hard error), so the endpoint returns 200 with the cluster
# that DOES have data; never-seen columns are the -1 sentinel + a
# "have never been received" warning. Clusters has no formulas
# (clusterCPU=A, clusterCPUAllocatable=B, clusterMemory=C,
# clusterMemoryAllocatable=D).
pytest.param(
{
"dataset": "clusters_missing_metrics.jsonl", # seeds only k8s.node.cpu.usage
"body": {"filter": {"expression": "k8s.cluster.name = 'miss-cluster'"}},
"warn_substrings": ["never been received"],
"warn_names": [
"k8s.node.allocatable_cpu",
"k8s.node.memory.working_set",
"k8s.node.allocatable_memory",
],
"data_fields": ["clusterCPU"],
"no_data_fields": ["clusterCPUAllocatable", "clusterMemory", "clusterMemoryAllocatable"],
},
id="metric_never_seen",
),
# Scenario 2: groupBy a key that IS in metadata (deployment.environment is
# seeded on k8s.node.cpu.usage only) but was never seen together with the
# other node metrics. The key resolves (page-groups IN-filter parses -> no
# 400), but B/C/D miss the (metric, key) pair and the statement builder
# falls back to raw labels, surfacing "key `...` not found on metric ...".
# Still 200, no hard error.
pytest.param(
{
"dataset": "clusters_metric_key_pair.jsonl",
"body": {
"filter": {"expression": "k8s.cluster.name = 'kp-cluster'"},
"groupBy": [
{
"name": "deployment.environment",
"fieldDataType": "string",
"fieldContext": "resource",
}
],
},
"warn_substrings": ["key `deployment.environment` not found on metric"],
"warn_names": [],
"data_fields": [],
"no_data_fields": [],
},
id="metric_key_pair_not_seen",
),
],
)
def test_clusters_warnings(
def test_clusters_missing_metrics(
signoz: types.SigNoz,
create_user_admin: None, # pylint: disable=unused-argument
get_token,
insert_metrics,
case: dict,
) -> None:
"""Data-availability gaps surface as non-blocking warnings (200 + data), not
hard errors. Covers never-seen metrics (scenario 1) and never-seen
(metric, key) pairs via groupBy (scenario 2)."""
"""Seed only k8s.node.cpu.usage; assert other 5 required metrics flagged missing."""
now = datetime.now(tz=UTC).replace(microsecond=0)
insert_metrics(
Metrics.load_from_file(
get_testdata_file_path(f"inframonitoring/{case['dataset']}"),
get_testdata_file_path("inframonitoring/clusters_missing_metrics.jsonl"),
base_time=now - timedelta(minutes=4),
)
)
token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
body: dict = {
"start": int((now - timedelta(minutes=5)).timestamp() * 1000),
"end": int(now.timestamp() * 1000),
"limit": 50,
}
body.update(case["body"])
response = requests.post(
signoz.self.host_configs["8080"].get(ENDPOINT),
headers={"authorization": f"Bearer {token}"},
json=body,
json={
"start": int((now - timedelta(minutes=5)).timestamp() * 1000),
"end": int(now.timestamp() * 1000),
"limit": 50,
},
timeout=5,
)
assert response.status_code == HTTPStatus.OK, response.text
data = response.json()["data"]
warnings = get_all_warnings(response.json())
for substr in case["warn_substrings"]:
assert any(substr in w["message"] for w in warnings), f"{substr!r} not surfaced: {warnings!r}"
for name in case["warn_names"]:
assert any(name in w["message"] for w in warnings), f"{name!r} not surfaced: {warnings!r}"
assert len(data["records"]) >= 1, f"expected at least one record: {data!r}"
if case["data_fields"] or case["no_data_fields"]:
record = data["records"][0]
for field in case["data_fields"]:
assert record[field] != -1, f"expected {field} populated, got {record[field]}"
for field in case["no_data_fields"]:
assert record[field] == -1, f"expected {field} == -1 sentinel, got {record[field]}"
assert set(data["requiredMetricsCheck"]["missingMetrics"]) == (REQUIRED_METRICS - {"k8s.node.cpu.usage"})
assert data["records"] == []
assert data["total"] == 0
@pytest.mark.parametrize(

View File

@@ -11,10 +11,20 @@ from fixtures import types
from fixtures.auth import USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD
from fixtures.fs import get_testdata_file_path
from fixtures.metrics import Metrics
from fixtures.querier import compare_values, get_all_warnings
from fixtures.querier import compare_values
ENDPOINT = "/api/v2/infra_monitoring/pvcs"
# Required metrics for the v2 volumes endpoint
# (pkg/modules/inframonitoring/implinframonitoring/volumes_constants.go:20-27).
REQUIRED_METRICS = {
"k8s.volume.available",
"k8s.volume.capacity",
"k8s.volume.inodes",
"k8s.volume.inodes.free",
"k8s.volume.inodes.used",
}
def test_volumes_accuracy(
signoz: types.SigNoz,
@@ -61,8 +71,7 @@ def test_volumes_accuracy(
# Shape/contract.
assert data["total"] == len(expected["records"])
assert len(data["records"]) == len(expected["records"])
# Full data present -> no warnings surfaced.
assert get_all_warnings(response.json()) == []
assert data["requiredMetricsCheck"]["missingMetrics"] == []
assert data["endTimeBeforeRetention"] is False
assert {r["persistentVolumeClaimName"] for r in data["records"]} == set(exp_by_name.keys())
@@ -108,104 +117,38 @@ def test_volumes_accuracy(
assert compare_values(record[field], exp[field], 1e-6), f"{record['persistentVolumeClaimName']}.{field}: got {record[field]}, expected {exp[field]}"
@pytest.mark.parametrize(
"case",
[
# Scenario 1: a metric was never ingested. Post-#11754 the querier drops it
# (no hard error), so the endpoint returns 200 with whatever flowed; the
# never-seen column is the -1 sentinel + a "have never been received"
# warning. Here we omit the FORMULA OPERAND k8s.volume.available
# (volumeUsage = capacity - available): since A uses TimeAggregationAvg it is
# NOT zero-defaultable, so the formula drops the group -> volumeUsage == -1
# (it does NOT fall back to capacity). capacity + inodes stay real.
pytest.param(
{
"dataset": "volumes_formula_operand_missing.jsonl",
"body": {"filter": {"expression": "k8s.persistentvolumeclaim.name = 'fop-pvc'"}},
"warn_substrings": ["never been received", "k8s.volume.available"],
"warn_names": [],
"data_fields": ["volumeCapacity", "volumeInodes", "volumeInodesFree", "volumeInodesUsed"],
"no_data_fields": ["volumeAvailable", "volumeUsage"],
},
id="metric_never_seen",
),
# Scenario 2: groupBy a key that IS in metadata (deployment.environment is
# seeded on k8s.volume.capacity only) but was never seen together with the
# other volume metrics. The key resolves (page-groups IN-filter parses ->
# no 400), but the other metrics miss the (metric, key) pair and the
# statement builder falls back to raw labels, surfacing
# "key `...` not found on metric ...". Still 200, no hard error.
pytest.param(
{
"dataset": "volumes_metric_key_pair.jsonl",
"body": {
"filter": {"expression": "k8s.persistentvolumeclaim.name = 'kp-pvc'"},
"groupBy": [
{
"name": "deployment.environment",
"fieldDataType": "string",
"fieldContext": "resource",
}
],
},
"warn_substrings": ["key `deployment.environment` not found on metric"],
"warn_names": [],
"data_fields": [],
"no_data_fields": [],
},
id="metric_key_pair_not_seen",
),
],
)
def test_volumes_warnings(
def test_volumes_missing_metrics(
signoz: types.SigNoz,
create_user_admin: None, # pylint: disable=unused-argument
get_token,
insert_metrics,
case: dict,
) -> None:
"""Data-availability gaps surface as non-blocking warnings (200 + data), not
hard errors. Covers a never-seen formula operand (scenario 1: volumeUsage
stays -1, not capacity) and a never-seen (metric, key) pair via groupBy
(scenario 2)."""
"""Seed only k8s.volume.available; other 4 required metrics flagged missing."""
now = datetime.now(tz=UTC).replace(microsecond=0)
insert_metrics(
Metrics.load_from_file(
get_testdata_file_path(f"inframonitoring/{case['dataset']}"),
get_testdata_file_path("inframonitoring/volumes_missing_metrics.jsonl"),
base_time=now - timedelta(minutes=4),
)
)
token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
body: dict = {
"start": int((now - timedelta(minutes=5)).timestamp() * 1000),
"end": int(now.timestamp() * 1000),
"limit": 50,
}
body.update(case["body"])
response = requests.post(
signoz.self.host_configs["8080"].get(ENDPOINT),
headers={"authorization": f"Bearer {token}"},
json=body,
json={
"start": int((now - timedelta(minutes=5)).timestamp() * 1000),
"end": int(now.timestamp() * 1000),
"limit": 50,
},
timeout=5,
)
assert response.status_code == HTTPStatus.OK, response.text
data = response.json()["data"]
warnings = get_all_warnings(response.json())
for substr in case["warn_substrings"]:
assert any(substr in w["message"] for w in warnings), f"{substr!r} not surfaced: {warnings!r}"
for name in case["warn_names"]:
assert any(name in w["message"] for w in warnings), f"{name!r} not surfaced: {warnings!r}"
assert len(data["records"]) >= 1, f"expected at least one record: {data!r}"
if case["data_fields"] or case["no_data_fields"]:
record = data["records"][0]
for field in case["data_fields"]:
assert record[field] != -1, f"expected {field} populated, got {record[field]}"
for field in case["no_data_fields"]:
assert record[field] == -1, f"expected {field} == -1 sentinel, got {record[field]}"
assert set(data["requiredMetricsCheck"]["missingMetrics"]) == (REQUIRED_METRICS - {"k8s.volume.available"})
assert data["records"] == []
assert data["total"] == 0
@pytest.mark.parametrize(

View File

@@ -11,10 +11,24 @@ from fixtures import types
from fixtures.auth import USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD
from fixtures.fs import get_testdata_file_path
from fixtures.metrics import Metrics
from fixtures.querier import compare_values, get_all_warnings
from fixtures.querier import compare_values
ENDPOINT = "/api/v2/infra_monitoring/deployments"
# Required metrics for the v2 deployments endpoint
# (pkg/modules/inframonitoring/implinframonitoring/deployments_constants.go:24-34).
REQUIRED_METRICS = {
"k8s.pod.phase",
"k8s.pod.cpu.usage",
"k8s.pod.cpu_request_utilization",
"k8s.pod.cpu_limit_utilization",
"k8s.pod.memory.working_set",
"k8s.pod.memory_request_utilization",
"k8s.pod.memory_limit_utilization",
"k8s.deployment.desired",
"k8s.deployment.available",
}
def test_deployments_accuracy(
signoz: types.SigNoz,
@@ -61,8 +75,7 @@ def test_deployments_accuracy(
# Shape/contract.
assert data["total"] == len(expected["records"])
assert len(data["records"]) == len(expected["records"])
# Full data present -> no warnings surfaced.
assert get_all_warnings(response.json()) == []
assert data["requiredMetricsCheck"]["missingMetrics"] == []
assert data["endTimeBeforeRetention"] is False
assert {r["deploymentName"] for r in data["records"]} == set(exp_by_name.keys())
@@ -110,113 +123,38 @@ def test_deployments_accuracy(
assert record["podCountsByPhase"] == exp["podCountsByPhase"]
@pytest.mark.parametrize(
"case",
[
# Scenario 1: required metrics were never ingested. Post-#11754 the querier
# drops them (no hard error), so the endpoint returns 200 with the deployment
# that DOES have data; never-seen columns are the -1 sentinel + a
# "have never been received" warning. No formulas; pod- and deployment-level
# metrics each map to one column.
pytest.param(
{
"dataset": "deployments_missing_metrics.jsonl", # seeds only k8s.pod.cpu.usage
"body": {"filter": {"expression": "k8s.deployment.name = 'miss-dep'"}},
"warn_substrings": ["never been received"],
"warn_names": [
"k8s.pod.memory.working_set",
"k8s.deployment.desired",
"k8s.deployment.available",
],
"data_fields": ["deploymentCPU"],
"no_data_fields": [
"deploymentCPURequest",
"deploymentCPULimit",
"deploymentMemory",
"deploymentMemoryRequest",
"deploymentMemoryLimit",
"desiredPods",
"availablePods",
],
},
id="metric_never_seen",
),
# Scenario 2: groupBy a key that IS in metadata (deployment.environment is
# seeded on k8s.pod.cpu.usage only) but was never seen together with the
# other metrics. The key resolves (page-groups IN-filter parses -> no 400),
# but the other metrics miss the (metric, key) pair and the statement builder
# falls back to raw labels, surfacing "key `...` not found on metric ...".
# Still 200, no hard error.
pytest.param(
{
"dataset": "deployments_metric_key_pair.jsonl",
"body": {
"filter": {"expression": "k8s.deployment.name = 'kp-dep'"},
"groupBy": [
{
"name": "deployment.environment",
"fieldDataType": "string",
"fieldContext": "resource",
}
],
},
"warn_substrings": ["key `deployment.environment` not found on metric"],
"warn_names": [],
"data_fields": [],
"no_data_fields": [],
},
id="metric_key_pair_not_seen",
),
],
)
def test_deployments_warnings(
def test_deployments_missing_metrics(
signoz: types.SigNoz,
create_user_admin: None, # pylint: disable=unused-argument
get_token,
insert_metrics,
case: dict,
) -> None:
"""Data-availability gaps surface as non-blocking warnings (200 + data), not
hard errors. Covers never-seen metrics (scenario 1) and never-seen
(metric, key) pairs via groupBy (scenario 2)."""
"""Seed only k8s.pod.cpu.usage; assert other 8 required metrics flagged missing."""
now = datetime.now(tz=UTC).replace(microsecond=0)
insert_metrics(
Metrics.load_from_file(
get_testdata_file_path(f"inframonitoring/{case['dataset']}"),
get_testdata_file_path("inframonitoring/deployments_missing_metrics.jsonl"),
base_time=now - timedelta(minutes=4),
)
)
token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
body: dict = {
"start": int((now - timedelta(minutes=5)).timestamp() * 1000),
"end": int(now.timestamp() * 1000),
"limit": 50,
}
body.update(case["body"])
response = requests.post(
signoz.self.host_configs["8080"].get(ENDPOINT),
headers={"authorization": f"Bearer {token}"},
json=body,
json={
"start": int((now - timedelta(minutes=5)).timestamp() * 1000),
"end": int(now.timestamp() * 1000),
"limit": 50,
},
timeout=5,
)
assert response.status_code == HTTPStatus.OK, response.text
data = response.json()["data"]
warnings = get_all_warnings(response.json())
for substr in case["warn_substrings"]:
assert any(substr in w["message"] for w in warnings), f"{substr!r} not surfaced: {warnings!r}"
for name in case["warn_names"]:
assert any(name in w["message"] for w in warnings), f"{name!r} not surfaced: {warnings!r}"
assert len(data["records"]) >= 1, f"expected at least one record: {data!r}"
if case["data_fields"] or case["no_data_fields"]:
record = data["records"][0]
for field in case["data_fields"]:
assert record[field] != -1, f"expected {field} populated, got {record[field]}"
for field in case["no_data_fields"]:
assert record[field] == -1, f"expected {field} == -1 sentinel, got {record[field]}"
assert set(data["requiredMetricsCheck"]["missingMetrics"]) == (REQUIRED_METRICS - {"k8s.pod.cpu.usage"})
assert data["records"] == []
assert data["total"] == 0
@pytest.mark.parametrize(

View File

@@ -11,10 +11,24 @@ from fixtures import types
from fixtures.auth import USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD
from fixtures.fs import get_testdata_file_path
from fixtures.metrics import Metrics
from fixtures.querier import compare_values, get_all_warnings
from fixtures.querier import compare_values
ENDPOINT = "/api/v2/infra_monitoring/statefulsets"
# Required metrics for the v2 statefulsets endpoint
# (pkg/modules/inframonitoring/implinframonitoring/statefulsets_constants.go:24-34).
REQUIRED_METRICS = {
"k8s.pod.phase",
"k8s.pod.cpu.usage",
"k8s.pod.cpu_request_utilization",
"k8s.pod.cpu_limit_utilization",
"k8s.pod.memory.working_set",
"k8s.pod.memory_request_utilization",
"k8s.pod.memory_limit_utilization",
"k8s.statefulset.desired_pods",
"k8s.statefulset.current_pods",
}
def test_statefulsets_accuracy(
signoz: types.SigNoz,
@@ -61,8 +75,7 @@ def test_statefulsets_accuracy(
# Shape/contract.
assert data["total"] == len(expected["records"])
assert len(data["records"]) == len(expected["records"])
# Full data present -> no warnings surfaced.
assert get_all_warnings(response.json()) == []
assert data["requiredMetricsCheck"]["missingMetrics"] == []
assert data["endTimeBeforeRetention"] is False
assert {r["statefulSetName"] for r in data["records"]} == set(exp_by_name.keys())
@@ -110,116 +123,38 @@ def test_statefulsets_accuracy(
assert record["podCountsByPhase"] == exp["podCountsByPhase"]
@pytest.mark.parametrize(
"case",
[
# Scenario 1: required metrics were never ingested. Post-#11754 the querier
# drops them (no hard error), so the endpoint returns 200 with the
# statefulset that DOES have data; never-seen columns are the -1 sentinel +
# a "have never been received" warning. No formulas; each missing metric
# maps to one -1 column.
pytest.param(
{
"dataset": "statefulsets_missing_metrics.jsonl", # seeds only k8s.pod.cpu.usage
"body": {"filter": {"expression": "k8s.statefulset.name = 'miss-ss'"}},
"warn_substrings": ["never been received"],
"warn_names": [
"k8s.pod.memory.working_set",
"k8s.statefulset.desired_pods",
"k8s.statefulset.current_pods",
],
"data_fields": ["statefulSetCPU"],
"no_data_fields": [
"statefulSetCPURequest",
"statefulSetCPULimit",
"statefulSetMemory",
"statefulSetMemoryRequest",
"statefulSetMemoryLimit",
"desiredPods",
"currentPods",
],
},
id="metric_never_seen",
),
# Scenario 2 (FAITHFUL (metric,key)-pair): pods are NOT labelled with
# k8s.statefulset.name, while the statefulset-level metrics ARE. Grouping by
# the default [statefulset.name, namespace.name, cluster.name], the base
# filter (k8s.statefulset.name != '') excludes the label-less pod metrics ->
# statefulSet* (pod-derived) come back -1, while desiredPods/currentPods
# (statefulset metrics) stay real. Reproduces the production response.
# The "key ... not found on metric" warning fires deterministically: the
# (pod-metric, k8s.statefulset.name) pair is absent from distributed_metadata
# (insert_metrics truncates it per function; the suite runs serially), so the
# statement builder falls back to raw labels and warns. The -1 partial render
# is the robust core.
pytest.param(
{
"dataset": "statefulsets_metric_key_pair.jsonl",
"body": {"filter": {"expression": "k8s.statefulset.name = 'kp-sts'"}},
"warn_substrings": ["key `k8s.statefulset.name` not found on metric"],
"warn_names": [],
"data_fields": ["desiredPods", "currentPods"],
"no_data_fields": [
"statefulSetCPU",
"statefulSetCPURequest",
"statefulSetCPULimit",
"statefulSetMemory",
"statefulSetMemoryRequest",
"statefulSetMemoryLimit",
],
},
id="metric_key_pair_not_seen",
),
],
)
def test_statefulsets_warnings(
def test_statefulsets_missing_metrics(
signoz: types.SigNoz,
create_user_admin: None, # pylint: disable=unused-argument
get_token,
insert_metrics,
case: dict,
) -> None:
"""Data-availability gaps surface as non-blocking warnings (200 + data), not
hard errors. Covers never-seen metrics (scenario 1) and a faithful never-seen
(metric, key) pair (scenario 2: pod columns -1, statefulset counts real)."""
"""Seed only k8s.pod.cpu.usage; assert other 8 required metrics flagged missing."""
now = datetime.now(tz=UTC).replace(microsecond=0)
insert_metrics(
Metrics.load_from_file(
get_testdata_file_path(f"inframonitoring/{case['dataset']}"),
get_testdata_file_path("inframonitoring/statefulsets_missing_metrics.jsonl"),
base_time=now - timedelta(minutes=4),
)
)
token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
body: dict = {
"start": int((now - timedelta(minutes=5)).timestamp() * 1000),
"end": int(now.timestamp() * 1000),
"limit": 50,
}
body.update(case["body"])
response = requests.post(
signoz.self.host_configs["8080"].get(ENDPOINT),
headers={"authorization": f"Bearer {token}"},
json=body,
json={
"start": int((now - timedelta(minutes=5)).timestamp() * 1000),
"end": int(now.timestamp() * 1000),
"limit": 50,
},
timeout=5,
)
assert response.status_code == HTTPStatus.OK, response.text
data = response.json()["data"]
warnings = get_all_warnings(response.json())
for substr in case["warn_substrings"]:
assert any(substr in w["message"] for w in warnings), f"{substr!r} not surfaced: {warnings!r}"
for name in case["warn_names"]:
assert any(name in w["message"] for w in warnings), f"{name!r} not surfaced: {warnings!r}"
assert len(data["records"]) >= 1, f"expected at least one record: {data!r}"
if case["data_fields"] or case["no_data_fields"]:
record = data["records"][0]
for field in case["data_fields"]:
assert record[field] != -1, f"expected {field} populated, got {record[field]}"
for field in case["no_data_fields"]:
assert record[field] == -1, f"expected {field} == -1 sentinel, got {record[field]}"
assert set(data["requiredMetricsCheck"]["missingMetrics"]) == (REQUIRED_METRICS - {"k8s.pod.cpu.usage"})
assert data["records"] == []
assert data["total"] == 0
@pytest.mark.parametrize(

View File

@@ -11,10 +11,26 @@ from fixtures import types
from fixtures.auth import USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD
from fixtures.fs import get_testdata_file_path
from fixtures.metrics import Metrics
from fixtures.querier import compare_values, get_all_warnings
from fixtures.querier import compare_values
ENDPOINT = "/api/v2/infra_monitoring/jobs"
# Required metrics for the v2 jobs endpoint
# (pkg/modules/inframonitoring/implinframonitoring/jobs_constants.go:24-36).
REQUIRED_METRICS = {
"k8s.pod.phase",
"k8s.pod.cpu.usage",
"k8s.pod.cpu_request_utilization",
"k8s.pod.cpu_limit_utilization",
"k8s.pod.memory.working_set",
"k8s.pod.memory_request_utilization",
"k8s.pod.memory_limit_utilization",
"k8s.job.active_pods",
"k8s.job.failed_pods",
"k8s.job.successful_pods",
"k8s.job.desired_successful_pods",
}
def test_jobs_accuracy(
signoz: types.SigNoz,
@@ -62,8 +78,7 @@ def test_jobs_accuracy(
# Shape/contract.
assert data["total"] == len(expected["records"])
assert len(data["records"]) == len(expected["records"])
# Full data present -> no warnings surfaced.
assert get_all_warnings(response.json()) == []
assert data["requiredMetricsCheck"]["missingMetrics"] == []
assert data["endTimeBeforeRetention"] is False
assert {r["jobName"] for r in data["records"]} == set(exp_by_name.keys())
@@ -113,115 +128,38 @@ def test_jobs_accuracy(
assert record["podCountsByPhase"] == exp["podCountsByPhase"]
@pytest.mark.parametrize(
"case",
[
# Scenario 1: required metrics were never ingested. Post-#11754 the querier
# drops them (no hard error), so the endpoint returns 200 with the job that
# DOES have data; never-seen columns are the -1 sentinel + a
# "have never been received" warning. No formulas; pod- and job-level
# metrics each map to one column.
pytest.param(
{
"dataset": "jobs_missing_metrics.jsonl", # seeds only k8s.pod.cpu.usage
"body": {"filter": {"expression": "k8s.job.name = 'miss-job'"}},
"warn_substrings": ["never been received"],
"warn_names": [
"k8s.pod.memory.working_set",
"k8s.job.desired_successful_pods",
"k8s.job.successful_pods",
],
"data_fields": ["jobCPU"],
"no_data_fields": [
"jobCPURequest",
"jobCPULimit",
"jobMemory",
"jobMemoryRequest",
"jobMemoryLimit",
"desiredSuccessfulPods",
"activePods",
"failedPods",
"successfulPods",
],
},
id="metric_never_seen",
),
# Scenario 2: groupBy a key that IS in metadata (deployment.environment is
# seeded on k8s.pod.cpu.usage only) but was never seen together with the
# other metrics. The key resolves (page-groups IN-filter parses -> no 400),
# but the other metrics miss the (metric, key) pair and the statement builder
# falls back to raw labels, surfacing "key `...` not found on metric ...".
# Still 200, no hard error.
pytest.param(
{
"dataset": "jobs_metric_key_pair.jsonl",
"body": {
"filter": {"expression": "k8s.job.name = 'kp-job'"},
"groupBy": [
{
"name": "deployment.environment",
"fieldDataType": "string",
"fieldContext": "resource",
}
],
},
"warn_substrings": ["key `deployment.environment` not found on metric"],
"warn_names": [],
"data_fields": [],
"no_data_fields": [],
},
id="metric_key_pair_not_seen",
),
],
)
def test_jobs_warnings(
def test_jobs_missing_metrics(
signoz: types.SigNoz,
create_user_admin: None, # pylint: disable=unused-argument
get_token,
insert_metrics,
case: dict,
) -> None:
"""Data-availability gaps surface as non-blocking warnings (200 + data), not
hard errors. Covers never-seen metrics (scenario 1) and never-seen
(metric, key) pairs via groupBy (scenario 2)."""
"""Seed only k8s.pod.cpu.usage; assert other 10 required metrics flagged missing."""
now = datetime.now(tz=UTC).replace(microsecond=0)
insert_metrics(
Metrics.load_from_file(
get_testdata_file_path(f"inframonitoring/{case['dataset']}"),
get_testdata_file_path("inframonitoring/jobs_missing_metrics.jsonl"),
base_time=now - timedelta(minutes=4),
)
)
token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
body: dict = {
"start": int((now - timedelta(minutes=5)).timestamp() * 1000),
"end": int(now.timestamp() * 1000),
"limit": 50,
}
body.update(case["body"])
response = requests.post(
signoz.self.host_configs["8080"].get(ENDPOINT),
headers={"authorization": f"Bearer {token}"},
json=body,
json={
"start": int((now - timedelta(minutes=5)).timestamp() * 1000),
"end": int(now.timestamp() * 1000),
"limit": 50,
},
timeout=5,
)
assert response.status_code == HTTPStatus.OK, response.text
data = response.json()["data"]
warnings = get_all_warnings(response.json())
for substr in case["warn_substrings"]:
assert any(substr in w["message"] for w in warnings), f"{substr!r} not surfaced: {warnings!r}"
for name in case["warn_names"]:
assert any(name in w["message"] for w in warnings), f"{name!r} not surfaced: {warnings!r}"
assert len(data["records"]) >= 1, f"expected at least one record: {data!r}"
if case["data_fields"] or case["no_data_fields"]:
record = data["records"][0]
for field in case["data_fields"]:
assert record[field] != -1, f"expected {field} populated, got {record[field]}"
for field in case["no_data_fields"]:
assert record[field] == -1, f"expected {field} == -1 sentinel, got {record[field]}"
assert set(data["requiredMetricsCheck"]["missingMetrics"]) == (REQUIRED_METRICS - {"k8s.pod.cpu.usage"})
assert data["records"] == []
assert data["total"] == 0
@pytest.mark.parametrize(

View File

@@ -11,10 +11,24 @@ from fixtures import types
from fixtures.auth import USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD
from fixtures.fs import get_testdata_file_path
from fixtures.metrics import Metrics
from fixtures.querier import compare_values, get_all_warnings
from fixtures.querier import compare_values
ENDPOINT = "/api/v2/infra_monitoring/daemonsets"
# Required metrics for the v2 daemonsets endpoint
# (pkg/modules/inframonitoring/implinframonitoring/daemonsets_constants.go:24-34).
REQUIRED_METRICS = {
"k8s.pod.phase",
"k8s.pod.cpu.usage",
"k8s.pod.cpu_request_utilization",
"k8s.pod.cpu_limit_utilization",
"k8s.pod.memory.working_set",
"k8s.pod.memory_request_utilization",
"k8s.pod.memory_limit_utilization",
"k8s.daemonset.desired_scheduled_nodes",
"k8s.daemonset.current_scheduled_nodes",
}
def test_daemonsets_accuracy(
signoz: types.SigNoz,
@@ -61,8 +75,7 @@ def test_daemonsets_accuracy(
# Shape/contract.
assert data["total"] == len(expected["records"])
assert len(data["records"]) == len(expected["records"])
# Full data present -> no warnings surfaced.
assert get_all_warnings(response.json()) == []
assert data["requiredMetricsCheck"]["missingMetrics"] == []
assert data["endTimeBeforeRetention"] is False
assert {r["daemonSetName"] for r in data["records"]} == set(exp_by_name.keys())
@@ -110,116 +123,38 @@ def test_daemonsets_accuracy(
assert record["podCountsByPhase"] == exp["podCountsByPhase"]
@pytest.mark.parametrize(
"case",
[
# Scenario 1: required metrics were never ingested. Post-#11754 the querier
# drops them (no hard error), so the endpoint returns 200 with the daemonset
# that DOES have data; never-seen columns are the -1 sentinel + a
# "have never been received" warning. No formulas; pod- and daemonset-level
# metrics each map to one column.
pytest.param(
{
"dataset": "daemonsets_missing_metrics.jsonl", # seeds only k8s.pod.cpu.usage
"body": {"filter": {"expression": "k8s.daemonset.name = 'miss-ds'"}},
"warn_substrings": ["never been received"],
"warn_names": [
"k8s.pod.memory.working_set",
"k8s.daemonset.desired_scheduled_nodes",
"k8s.daemonset.current_scheduled_nodes",
],
"data_fields": ["daemonSetCPU"],
"no_data_fields": [
"daemonSetCPURequest",
"daemonSetCPULimit",
"daemonSetMemory",
"daemonSetMemoryRequest",
"daemonSetMemoryLimit",
"desiredNodes",
"currentNodes",
],
},
id="metric_never_seen",
),
# Scenario 2 (FAITHFUL (metric,key)-pair): pods are NOT labelled with
# k8s.daemonset.name, while the daemonset-level metrics ARE. Grouping by the
# default [daemonset.name, namespace.name, cluster.name], the base filter
# (k8s.daemonset.name != '') excludes the label-less pod metrics ->
# daemonSet* (pod-derived) come back -1, while desiredNodes/currentNodes
# (daemonset metrics) stay real. Mirrors the statefulsets faithful case.
# The "key ... not found on metric" warning fires deterministically: the
# (pod-metric, k8s.daemonset.name) pair is absent from distributed_metadata
# (insert_metrics truncates it per function; the suite runs serially), so the
# statement builder falls back to raw labels and warns. The -1 partial render
# is the robust core.
pytest.param(
{
"dataset": "daemonsets_metric_key_pair.jsonl",
"body": {"filter": {"expression": "k8s.daemonset.name = 'kp-ds'"}},
"warn_substrings": ["key `k8s.daemonset.name` not found on metric"],
"warn_names": [],
"data_fields": ["desiredNodes", "currentNodes"],
"no_data_fields": [
"daemonSetCPU",
"daemonSetCPURequest",
"daemonSetCPULimit",
"daemonSetMemory",
"daemonSetMemoryRequest",
"daemonSetMemoryLimit",
],
},
id="metric_key_pair_not_seen",
),
],
)
def test_daemonsets_warnings(
def test_daemonsets_missing_metrics(
signoz: types.SigNoz,
create_user_admin: None, # pylint: disable=unused-argument
get_token,
insert_metrics,
case: dict,
) -> None:
"""Data-availability gaps surface as non-blocking warnings (200 + data), not
hard errors. Covers never-seen metrics (scenario 1) and a faithful never-seen
(metric, key) pair (scenario 2: pod columns -1, daemonset counts real)."""
"""Seed only k8s.pod.cpu.usage; assert other 8 required metrics flagged missing."""
now = datetime.now(tz=UTC).replace(microsecond=0)
insert_metrics(
Metrics.load_from_file(
get_testdata_file_path(f"inframonitoring/{case['dataset']}"),
get_testdata_file_path("inframonitoring/daemonsets_missing_metrics.jsonl"),
base_time=now - timedelta(minutes=4),
)
)
token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
body: dict = {
"start": int((now - timedelta(minutes=5)).timestamp() * 1000),
"end": int(now.timestamp() * 1000),
"limit": 50,
}
body.update(case["body"])
response = requests.post(
signoz.self.host_configs["8080"].get(ENDPOINT),
headers={"authorization": f"Bearer {token}"},
json=body,
json={
"start": int((now - timedelta(minutes=5)).timestamp() * 1000),
"end": int(now.timestamp() * 1000),
"limit": 50,
},
timeout=5,
)
assert response.status_code == HTTPStatus.OK, response.text
data = response.json()["data"]
warnings = get_all_warnings(response.json())
for substr in case["warn_substrings"]:
assert any(substr in w["message"] for w in warnings), f"{substr!r} not surfaced: {warnings!r}"
for name in case["warn_names"]:
assert any(name in w["message"] for w in warnings), f"{name!r} not surfaced: {warnings!r}"
assert len(data["records"]) >= 1, f"expected at least one record: {data!r}"
if case["data_fields"] or case["no_data_fields"]:
record = data["records"][0]
for field in case["data_fields"]:
assert record[field] != -1, f"expected {field} populated, got {record[field]}"
for field in case["no_data_fields"]:
assert record[field] == -1, f"expected {field} == -1 sentinel, got {record[field]}"
assert set(data["requiredMetricsCheck"]["missingMetrics"]) == (REQUIRED_METRICS - {"k8s.pod.cpu.usage"})
assert data["records"] == []
assert data["total"] == 0
@pytest.mark.parametrize(